Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> android NFC開發

android NFC開發

編輯:關於android開發

android NFC開發


先說說NFC開發總結,看了幾天NFC開發資料,搜集了不少關於這方面的資料、demo、以及他人的總結。以下有部分是摘錄總結的。因為要是現在總結也是那些,最後附送代碼。關於demo我也有,有需要在評論去發郵箱給我。

一、NFC的配置總結

第一:屏幕沒有鎖住 。 第二:NFC功能已經在設置中打開
當系統檢測到一個NFC標簽的時候,他會自動去尋找最合適的activity去處理這個intent.
NFC發出的這個Intent將會有三種action:
ACTION_NDEF_DISCOVERED:當系統檢測到tag中含有NDEF格式的數據時,且系統中有activity聲明可以接受包含NDEF數據的Intent的時候,系統會優先發出這個action的intent。

ACTION_TECH_DISCOVERED:當沒有任何一個activity聲明自己可以響應ACTION_NDEF_DISCOVERED時,系統會嘗試發出TECH的intent.即便你的tag中所包含的數據是NDEF的,但是如果這個數據的MIMEtype或URI不能和任何一個activity所聲明的想吻合,系統也一樣會嘗試發出tech格式的intent,而不是NDEF.

ACTION_TAG_DISCOVERED:當系統發現前兩個intent在系統中無人會接受的時候,就只好發這個默認的TAG類型的

 

二、NFC相關androidManifest文件設置

首先是權限:


然後是sdk級別限制:我個人建議API11開始比較合適:


如果是API8,在代碼中,nfc功能設置的代碼會出錯,要拋出
例如:
NfcAdapter mAdapter = NfcAdapter.getDefaultAdapter(this);
mAdapter.isEnabled()

接著是特殊功能限制:
這個生命可以讓你的應用在googleplay上被聲明使用者必須擁有nfc功能。

 

三、NFC標簽過濾,也在androidManifest文件設置

在activity的intent過濾xml聲明中,你可以同時聲明過濾這三種action.但是由之前所說,你應該知道系統在發送intent的時候是有優先級的,所以你最好清楚自己最想處理哪個。
 

1:過濾ACTION_TAG_DISCOVERED:

    
        
        
    
這個最簡單,也是最後一個被嘗試接受intent的選項。

2:過濾ACTION_NDEF_DISCOVERED:

 
 
 

 
其中最重要的應該算是data的mimeType類型了,這個定義的越准確,intent指向你這個activity的成功率就越高,否則系統可能不會發出你想要的NDEF intent了。下面在講如何使用NDEF寫入NFC標簽的時候會多舉幾個類型的例子。

 

 

3:過濾ACTION_TECH_DISCOVERED:

 

你首先需要在你的/res/xml下面創建一個過濾規則文件。名字任取,比如可以叫做nfc_tech_filter.xml。這個裡面定義的是nfc實現的各種標准,每一個nfc卡都會符合多個不同的標准,個人理解為這些標准有些相互之間也是兼容的。你可以在檢測到nfc標簽後使用getTechList()方法來查看你所檢測的tag到底支持哪些nfc標准。
一個nfc_tech_filter.xml中可以定義多個結構組。

 


 

android.nfc.tech.IsoDep
 android.nfc.tech.NfcA 
  android.nfc.tech.NfcB 
android.nfc.tech.NfcF 


android.nfc.tech.NfcV 
android.nfc.tech.Ndef 
android.nfc.tech.NdefFormatable
 android.nfc.tech.MifareClassic 
android.nfc.tech.MifareUltralight
  

 

在androidManifest文件中聲明xml過濾的舉例如下:

 

 
  
 
 

 

 

四、看具體代碼:

 

1、主要代碼實現如下:

 

package org.reno.Beam;

import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import org.nfc.read.ParsedNdefRecord;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.MifareUltralight;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.Settings;
import android.widget.TextView;

public class MainActivity extends Activity {
	private static final DateFormat TIME_FORMAT = SimpleDateFormat
			.getDateTimeInstance();
	private NfcAdapter mAdapter;
	private PendingIntent mPendingIntent;
	private NdefMessage mNdefPushMessage;
	private TextView promt;
	private AlertDialog mDialog;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		promt = (TextView) findViewById(R.id.promt);

		resolveIntent(getIntent());

		mDialog = new AlertDialog.Builder(this).setNeutralButton("Ok", null)
				.create();
		// 獲取默認的NFC控制器
		mAdapter = NfcAdapter.getDefaultAdapter(this);

		//攔截系統級的NFC掃描,例如掃描藍牙
		mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
				getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
		mNdefPushMessage = new NdefMessage(new NdefRecord[] { newTextRecord("",
				Locale.ENGLISH, true) });
	}

	@Override
	protected void onResume() {
		super.onResume();
		if (mAdapter == null) {
			if (!mAdapter.isEnabled()) {
				showWirelessSettingsDialog();
			}

			showMessage(R.string.error, R.string.no_nfc);
			promt.setText("設備不支持NFC!");
			return;
		}
		if (!mAdapter.isEnabled()) {
			promt.setText("請在系統設置中先啟用NFC功能!");
			return;
		}

		if (mAdapter != null) {
			//隱式啟動
			mAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
			mAdapter.enableForegroundNdefPush(this, mNdefPushMessage);
		}
	}

	@Override
	protected void onPause() {
		super.onPause();
		if (mAdapter != null) {
			//隱式啟動
			mAdapter.disableForegroundDispatch(this);
			mAdapter.disableForegroundNdefPush(this);
		}
	}

	//16進制字符串轉換為String
	private String hexString = "0123456789ABCDEF";
	public String decode(String bytes) {
		if (bytes.length() != 30) {
			return null;
		}
		ByteArrayOutputStream baos = new ByteArrayOutputStream(
				bytes.length() / 2);
		// 將每2位16進制整數組裝成一個字節
		for (int i = 0; i < bytes.length(); i += 2)
			baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString
					.indexOf(bytes.charAt(i + 1))));
		return new String(baos.toByteArray());
	}

	// 字符序列轉換為16進制字符串
	private static String bytesToHexString(byte[] src, boolean isPrefix) {
		StringBuilder stringBuilder = new StringBuilder();
		if (isPrefix == true) {
			stringBuilder.append("0x");
		}
		if (src == null || src.length <= 0) {
			return null;
		}
		char[] buffer = new char[2];
		for (int i = 0; i < src.length; i++) {
			buffer[0] = Character.toUpperCase(Character.forDigit(
					(src[i] >>> 4) & 0x0F, 16));
			buffer[1] = Character.toUpperCase(Character.forDigit(src[i] & 0x0F,
					16));
			System.out.println(buffer);
			stringBuilder.append(buffer);
		}
		return stringBuilder.toString();
	}

	private void showMessage(int title, int message) {
		mDialog.setTitle(title);
		mDialog.setMessage(getText(message));
		mDialog.show();
	}

	private NdefRecord newTextRecord(String text, Locale locale,
			boolean encodeInUtf8) {
		byte[] langBytes = locale.getLanguage().getBytes(
				Charset.forName("US-ASCII"));

		Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset
				.forName("UTF-16");
		byte[] textBytes = text.getBytes(utfEncoding);

		int utfBit = encodeInUtf8 ? 0 : (1 << 7);
		char status = (char) (utfBit + langBytes.length);

		byte[] data = new byte[1 + langBytes.length + textBytes.length];
		data[0] = (byte) status;
		System.arraycopy(langBytes, 0, data, 1, langBytes.length);
		System.arraycopy(textBytes, 0, data, 1 + langBytes.length,
				textBytes.length);

		return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT,
				new byte[0], data);
	}

	private void showWirelessSettingsDialog() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(R.string.nfc_disabled);
		builder.setPositiveButton(android.R.string.ok,
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialogInterface, int i) {
						Intent intent = new Intent(
								Settings.ACTION_WIRELESS_SETTINGS);
						startActivity(intent);
					}
				});
		builder.setNegativeButton(android.R.string.cancel,
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialogInterface, int i) {
						finish();
					}
				});
		builder.create().show();
		return;
	}

	//初步判斷是什麼類型NFC卡
	private void resolveIntent(Intent intent) {
		String action = intent.getAction();
		if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
				|| NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
				|| NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
			Parcelable[] rawMsgs = intent
					.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
			NdefMessage[] msgs;
			if (rawMsgs != null) {
				msgs = new NdefMessage[rawMsgs.length];
				for (int i = 0; i < rawMsgs.length; i++) {
					msgs[i] = (NdefMessage) rawMsgs[i];
				}
			} else {
				// Unknown tag type
				byte[] empty = new byte[0];
				byte[] id = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
				Parcelable tag = intent
						.getParcelableExtra(NfcAdapter.EXTRA_TAG);
				byte[] payload = dumpTagData(tag).getBytes();
				NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN,
						empty, id, payload);
				NdefMessage msg = new NdefMessage(new NdefRecord[] { record });
				msgs = new NdefMessage[] { msg };
			}
			// Setup the views
			buildTagViews(msgs);
		}
	}

	//一般公家卡,掃描的信息
	private String dumpTagData(Parcelable p) {
		StringBuilder sb = new StringBuilder();
		Tag tag = (Tag) p;
		byte[] id = tag.getId();
		sb.append("Tag ID (hex): ").append(getHex(id)).append("\n");
		sb.append("Tag ID (dec): ").append(getDec(id)).append("\n");
		sb.append("ID (reversed): ").append(getReversed(id)).append("\n");

		String prefix = "android.nfc.tech.";
		sb.append("Technologies: ");
		for (String tech : tag.getTechList()) {
			sb.append(tech.substring(prefix.length()));
			sb.append(", ");
		}
		sb.delete(sb.length() - 2, sb.length());
		for (String tech : tag.getTechList()) {
			if (tech.equals(MifareClassic.class.getName())) {
				sb.append('\n');
				MifareClassic mifareTag = MifareClassic.get(tag);
				String type = "Unknown";
				switch (mifareTag.getType()) {
				case MifareClassic.TYPE_CLASSIC:
					type = "Classic";
					break;
				case MifareClassic.TYPE_PLUS:
					type = "Plus";
					break;
				case MifareClassic.TYPE_PRO:
					type = "Pro";
					break;
				}
				sb.append("Mifare Classic type: ");
				sb.append(type);
				sb.append('\n');

				sb.append("Mifare size: ");
				sb.append(mifareTag.getSize() + " bytes");
				sb.append('\n');

				sb.append("Mifare sectors: ");
				sb.append(mifareTag.getSectorCount());
				sb.append('\n');

				sb.append("Mifare blocks: ");
				sb.append(mifareTag.getBlockCount());
			}

			if (tech.equals(MifareUltralight.class.getName())) {
				sb.append('\n');
				MifareUltralight mifareUlTag = MifareUltralight.get(tag);
				String type = "Unknown";
				switch (mifareUlTag.getType()) {
				case MifareUltralight.TYPE_ULTRALIGHT:
					type = "Ultralight";
					break;
				case MifareUltralight.TYPE_ULTRALIGHT_C:
					type = "Ultralight C";
					break;
				}
				sb.append("Mifare Ultralight type: ");
				sb.append(type);
			}
		}

		return sb.toString();
	}

	private String getHex(byte[] bytes) {
		StringBuilder sb = new StringBuilder();
		for (int i = bytes.length - 1; i >= 0; --i) {
			int b = bytes[i] & 0xff;
			if (b < 0x10)
				sb.append('0');
			sb.append(Integer.toHexString(b));
			if (i > 0) {
				sb.append(" ");
			}
		}
		return sb.toString();
	}

	private long getDec(byte[] bytes) {
		long result = 0;
		long factor = 1;
		for (int i = 0; i < bytes.length; ++i) {
			long value = bytes[i] & 0xffl;
			result += value * factor;
			factor *= 256l;
		}
		return result;
	}

	private long getReversed(byte[] bytes) {
		long result = 0;
		long factor = 1;
		for (int i = bytes.length - 1; i >= 0; --i) {
			long value = bytes[i] & 0xffl;
			result += value * factor;
			factor *= 256l;
		}
		return result;
	}

	//顯示NFC掃描的數據
	private void buildTagViews(NdefMessage[] msgs) {
		if (msgs == null || msgs.length == 0) {
			return;
		}
		// Parse the first message in the list
		// Build views for all of the sub records
		Date now = new Date();
		List records = NdefMessageParser.parse(msgs[0]);
		final int size = records.size();
		for (int i = 0; i < size; i++) {
			TextView timeView = new TextView(this);
			timeView.setText(TIME_FORMAT.format(now));
			ParsedNdefRecord record = records.get(i);
			promt.append(record.getViewText());
		}
	}

	//獲取系統隱式啟動的
	@Override
	public void onNewIntent(Intent intent) {
		setIntent(intent);
		resolveIntent(intent);
	}
}

 

2、androidManifest配置

 

 




    

    
    

    
    

    
        
            
                

                
            
            
                
                
                
            

            
        
    



 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved