編輯:關於Android編程
Android支持的數據格式
數據格式的Intent filter
AndroidManifest.xml文件中,要像向下列示例那樣,在元素內的
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHByZSBjbGFzcz0="brush:java;">
...
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
也可創建多個資源文件(多個資源文件是OR關系,每個資源文件中的芯片是AND關系):
android.nfc.tech.NfcA android.nfc.tech.Ndef android.nfc.tech.NdefFormatable
或者在同一個資源文件中創建多個android.nfc.tech.Ndef android.nfc.tech.NdefFormatable
android.nfc.tech.NfcA android.nfc.tech.NfcB android.nfc.tech.MifareClassic
通過Tag.getTechlist()方法,獲得標簽所支持的數據格式
通過Tag.getId()方法,獲得標簽的唯一ID標識
NfcAdapter == null:表示設備不支持NFC硬件
NfcAdapter.isEnable()方法:判斷NFC是否開啟
綜上所述:
一個Tag通過Tag.getTechlist()方法獲取它所支持的所有標簽類型,如果清單文件中所引用的
MifareClassic標簽的外形結構
MifareClassic標簽的數據結構
注意事項(假設1k空間):
第一扇區的第一塊一般用於制造商占用塊
0-15個扇區:一個扇區對應4個塊,所以總共有64個塊,序號分別為0-63,第一個扇區對應:0-3塊,第二個扇區對應:4-7塊...
每個扇區的最後一個塊用來存放密碼或控制位,其余為數據塊,一個塊占用16個字節,keyA占用6字節,控制位占用4字節,keyB占用6字節
MifareClassic類的常用方法
get():根據Tag對象來獲得MifareClassic對象;
Connect():允許對MifareClassic標簽進行IO操作;
getType():獲得MifareClassic標簽的具體類型:TYPE_CLASSIC,TYPE_PLUA,TYPE_PRO,TYPE_UNKNOWN;
getSectorCount():獲得標簽總共有的扇區數量;
getBlockCount():獲得標簽總共有的的塊數量;
getSize():獲得標簽的容量:SIZE_1K,SIZE_2K,SIZE_4K,SIZE_MINI
authenticateSectorWithKeyA(int SectorIndex,byte[] Key):驗證當前扇區的KeyA密碼,返回值為ture或false。
常用KeyA:默認出廠密碼:KEY_DEFAULT,
各種用途的供貨商必須配合該技術的MAD:KEY_MIFARE_APPLICATION_DIRECTORY
被格式化成NDEF格式的密碼:KEY_NFC_FORUM
getBlockCountInSector(int):獲得當前扇區的所包含塊的數量;
sectorToBlock(int):當前扇區的第1塊的塊號;
WriteBlock(int,data):將數據data寫入當前塊;
readBlock(int):讀取當前塊的數據。
close():禁止對標簽的IO操作,釋放資源。
MifareClassic標簽的讀寫流程
獲得Adapter對象
獲得Tag對象
獲得MifareClassic對象
讀取數據塊的數據
Connect(),readBlock(),close()
獲得Adapter對象
獲得Tag對象
獲得MifareClassic對象
將數據塊寫入標簽
Connect(),writeBlock(),close()
官方文檔:
When a device scans a tag that has NDEF data on it, but could not be mapped to a MIME or URI, the tag dispatch system tries to start an activity with the ACTION_TECH_DISCOVERED
intent.
The ACTION_TECH_DISCOVERED
is
also used when a tag with non-NDEF data is scanned. Having this fallback allows you to work with the data on the tag directly if the tag dispatch system could not parse it for you. The basic steps when working with tag technologies are as follows:
ACTION_TECH_DISCOVERED
intent
specifying the tag technologies that you want to handle. SeeFiltering for NFC intents for more information.
In general, the tag dispatch system tries to start aACTION_TECH_DISCOVERED
intent
when an NDEF message cannot be mapped to a MIME type or URI, or if the tag scanned did not contain NDEF data. For more information on how this is determined, see The
Tag Dispatch System.Tag
object
from the intent:
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
TagTechnology
,
by calling one of the get
factory methods of the classes in theandroid.nfc.tech
package.
You can enumerate the supported technologies of the tag by callinggetTechList()
before
calling a get
factory method. For example, to obtain an instance of MifareUltralight
from
a Tag
, do the following:
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
Reading and writing to an NFC tag involves obtaining the tag from the intent and opening communication with the tag. You must define your own protocol stack to read and write data to the tag. Keep in mind, however, that you can still read and write NDEF data when working directly with a tag. It is up to you how you want to structure things. The following example shows how to work with a MIFARE Ultralight tag.
package com.example.android.nfc; import android.nfc.Tag; import android.nfc.tech.MifareUltralight; import android.util.Log; import java.io.IOException; import java.nio.charset.Charset; public class MifareUltralightTagTester { private static final String TAG = MifareUltralightTagTester.class.getSimpleName(); public void writeTag(Tag tag, String tagText) { MifareUltralight ultralight = MifareUltralight.get(tag); try { ultralight.connect(); ultralight.writePage(4, "abcd".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(5, "efgh".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(6, "ijkl".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(7, "mnop".getBytes(Charset.forName("US-ASCII"))); } catch (IOException e) { Log.e(TAG, "IOException while closing MifareUltralight...", e); } finally { try { ultralight.close(); } catch (IOException e) { Log.e(TAG, "IOException while closing MifareUltralight...", e); } } } public String readTag(Tag tag) { MifareUltralight mifare = MifareUltralight.get(tag); try { mifare.connect(); byte[] payload = mifare.readPages(4); return new String(payload, Charset.forName("US-ASCII")); } catch (IOException e) { Log.e(TAG, "IOException while writing MifareUltralight message...", e); } finally { if (mifare != null) { try { mifare.close(); } catch (IOException e) { Log.e(TAG, "Error closing tag...", e); } } } return null; } }
例子程序:
package mobile.android.mifareultralight; import java.io.IOException; import java.nio.charset.Charset; import android.app.Activity; import android.app.PendingIntent; import android.content.Intent; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.MifareClassic; import android.os.Bundle; import android.util.Log; import android.widget.CheckBox; import android.widget.Toast; public class MifareultralightMainActivity extends Activity { private CheckBox mWriteData; private NfcAdapter mNfcAdapter; private PendingIntent mPendingIntent; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_mifareultralight); mWriteData = (CheckBox) findViewById(R.id.checkbox_write); mNfcAdapter = mNfcAdapter.getDefaultAdapter(this); if (mNfcAdapter == null) { Toast.makeText(this, "設備不支持NFC!", Toast.LENGTH_LONG).show(); finish(); return; } if (!mNfcAdapter.isEnabled()) { Toast.makeText(this, "請在系統設置中先啟用NFC功能!", Toast.LENGTH_LONG).show(); finish(); return; } mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()), 0); } @Override public void onResume() { super.onResume(); if (mNfcAdapter != null) mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null); } @Override public void onNewIntent(Intent intent) { Tag tag = intent.getParcelableExtra(mNfcAdapter.EXTRA_TAG); String[] techList = tag.getTechList(); boolean haveMifareUltralight = false; for (String tech : techList) { if (tech.indexOf("MifareClassic") >= 0) { haveMifareUltralight = true; break; } } if (!haveMifareUltralight) { Toast.makeText(this, "不支持MifareClassic", Toast.LENGTH_LONG).show(); return; } if (mWriteData.isChecked()) { writeTag(tag); } else { String data = readTag(tag); if (data != null) { Log.i(data, "ouput"); Toast.makeText(this, data, Toast.LENGTH_LONG).show(); } } } @Override public void onPause() { super.onPause(); if (mNfcAdapter != null) mNfcAdapter.disableForegroundDispatch(this); } public void writeTag(Tag tag) { MifareClassic mfc = MifareClassic.get(tag); try { mfc.connect(); boolean auth = false; short sectorAddress = 1; auth = mfc.authenticateSectorWithKeyA(sectorAddress, MifareClassic.KEY_NFC_FORUM); if (auth) { // the last block of the sector is used for KeyA and KeyB cannot be overwritted mfc.writeBlock(4, "1313838438000000".getBytes()); mfc.writeBlock(5, "1322676888000000".getBytes()); mfc.close(); Toast.makeText(this, "寫入成功", Toast.LENGTH_SHORT).show(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { mfc.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //字符序列轉換為16進制字符串 private String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder("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.forDigit((src[i] >>> 4) & 0x0F, 16); buffer[1] = Character.forDigit(src[i] & 0x0F, 16); System.out.println(buffer); stringBuilder.append(buffer); } return stringBuilder.toString(); } public String readTag(Tag tag) { MifareClassic mfc = MifareClassic.get(tag); for (String tech : tag.getTechList()) { System.out.println(tech); } boolean auth = false; //讀取TAG try { String metaInfo = ""; //Enable I/O operations to the tag from this TagTechnology object. mfc.connect(); int type = mfc.getType();//獲取TAG的類型 int sectorCount = mfc.getSectorCount();//獲取TAG中包含的扇區數 String typeS = ""; switch (type) { case MifareClassic.TYPE_CLASSIC: typeS = "TYPE_CLASSIC"; break; case MifareClassic.TYPE_PLUS: typeS = "TYPE_PLUS"; break; case MifareClassic.TYPE_PRO: typeS = "TYPE_PRO"; break; case MifareClassic.TYPE_UNKNOWN: typeS = "TYPE_UNKNOWN"; break; } metaInfo += "卡片類型:" + typeS + "\n共" + sectorCount + "個扇區\n共" + mfc.getBlockCount() + "個塊\n存儲空間: " + mfc.getSize() + "B\n"; for (int j = 0; j < sectorCount; j++) { //Authenticate a sector with key A. auth = mfc.authenticateSectorWithKeyA(j, MifareClassic.KEY_NFC_FORUM); int bCount; int bIndex; if (auth) { metaInfo += "Sector " + j + ":驗證成功\n"; // 讀取扇區中的塊 bCount = mfc.getBlockCountInSector(j); bIndex = mfc.sectorToBlock(j); for (int i = 0; i < bCount; i++) { byte[] data = mfc.readBlock(bIndex); metaInfo += "Block " + bIndex + " : " + bytesToHexString(data) + "\n"; bIndex++; } } else { metaInfo += "Sector " + j + ":驗證失敗\n"; } } return metaInfo; } catch (Exception e) { Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show(); e.printStackTrace(); } finally { if (mfc != null) { try { mfc.close(); } catch (IOException e) { Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG) .show(); } } } return null; } }
Socket Android手機客戶端與PC服務端局域網內聯測試,筆者采用的是 PC服務器,Android平板客戶端 ,PC模擬器客戶端, 前段時間為了加深對Socket
在Android開發中,網絡請求必然是必不可少。一般而言,都是基於http的網絡請求。有時候也會有SOCKET請求,這個後續的專題再講。今天,我們就先講講常用的Http請
本文的目的是用比較容易理解的方式,介紹一下整個Android項目的編譯。至少知道大概的編譯流程是怎麼樣的,項目裡面的Android.mk文件包含些什麼內容。makefil
開發Android APP微信支付功能,需要完成三個步驟:第一步生成預支付訂單、第二步生成微信支付參數、第三步調起微信APP支付。除了需要審核通過的APP應用外,還需要獲