安卓NFC开发学习笔记讲述.docx
- 文档编号:8707739
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:11
- 大小:87.13KB
安卓NFC开发学习笔记讲述.docx
《安卓NFC开发学习笔记讲述.docx》由会员分享,可在线阅读,更多相关《安卓NFC开发学习笔记讲述.docx(11页珍藏版)》请在冰豆网上搜索。
安卓NFC开发学习笔记讲述
大家学习android开发建议首选android开发文档,该文档在你下载的sdk中,路径:
/sdk/docs/index.html
目前NFC应用的大的框架上的理解:
我使用的APILEVEL是19,支持的API有三个:
android.nfc,android.nfc.cardemulator,android.nfc.tech
NFC在手机上的应用大体分为两类:
读卡器和卡
android.nfc.cardemulator接口是为NFC作为卡应用提供的接口,在较低版本的API上是没有的
android.nfc.tech,android.nfc接口是为NFC作为读卡器应用提供的接口
首先说作为卡,nfc有两种实现方式,一个是使用NFC芯片作为卡,另一个是使用SIM作为卡
Figure1.NFCcardemulationwithasecureelement.
至于从读卡器发送的指令到底是传递到NFC芯片还是SIM由NFCControler控制,图中SecureElement是指SIM,Host-CPU指NFC芯片
android提供HostApduService用于NFC芯片,OffHostApduService用于SIM芯片,传递方向在res/xml文件中通过AID来控制
ps:
Host-BasedCardEmulator简称为HCE
代码实现:
AndroidManifest.xml中配置service,因为作为卡实现的话,NFC功能是作为service存在的
name="com.shhic.nfcapp.NFCService"android: exported="true" android: permission="android.permission.BIND_NFC_SERVICE"> name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/> name="android.nfc.cardemulation.host_apdu_service" android: resource="@xml/apduservice"/> res/xml/apduservice.xml中配置service响应的AID android=" android: description="@string/servicedesc" android: requireDeviceUnlock="false"> description="@string/aiddescription" android: category="other"> name="F0010203040506"/> 配置文件完成后编写service的处理方法: NFCService需要继承HostApduService,如果需要与Activity通信,建议采用广播方式 也可以自己实现观察者模式,只是这样就需要持有Activity的引用,感觉不太好 NFCService.java publicclassNFCServiceextendsHostApduService{ privateIntentintent=newIntent("munication.RECEIVER"); @Override publicvoidonCreate() { //启动Acivity Intenti=newIntent(); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//需要启动的Activity不是当前Activity的时候需要用FLAG_ACTIVITY_NEW_TASK i.setAction("com.apdu.nfc"); getApplication().startActivity(i); Toast.makeText(getApplicationContext(),"Service启动",Toast.LENGTH_LONG).show(); } @Override publicbyte[]processCommandApdu(byte[]commandApdu,Bundleextras){//当注册的AID被选中后,后续指令被分发到这个处理函数中 byte[]sw=newbyte[]{(byte)0x90,(byte)0x00}; byte[]response=newbyte[5]; if(commandApdu[0]==(byte)0x00&&commandApdu[1]==(byte)0xA4&&commandApdu[2]==(byte)0x04 &&commandApdu[4]==(byte)0x07&&commandApdu[5]==(byte)0xF0) { returnsw; } else { //apdu处理逻辑 switch(commandApdu[1]) { case(byte)0xA8: break; case(byte)0xAE: break; default: returnsw; } } intent.putExtra("command",commandApdu); intent.putExtra("response",response); sendBroadcast(intent); //利用广播与Activity通信 returnresponse; //SW值需要包含在response中 } @Override publicvoidonDeactivated(intreason){ if(reason==HostApduService.DEACTIVATION_DESELECTED) { Toast.makeText(getApplicationContext(),"已选择其它应用",Toast.LENGTH_LONG).show(); } else { Toast.makeText(getApplicationContext(),"连接断开",Toast.LENGTH_LONG).show(); } } @Override publicvoidonDestroy() { Toast.makeText(getApplicationContext(),"Service关闭",Toast.LENGTH_LONG).show(); super.onDestroy(); } 框架搭建好剩余的事情就很简单了,apdu的处理逻辑在processCommandApdu方法中实现即可 以上是Host-CPU方式的实现,SIM方式,API介绍中说该方式没有提供可供操作的API,也就是说Android不会监听SIM卡与读卡器之间的通信 所以NFCOffService只需要实现onBind接口,这样绑定该Service的Activity可以对NFCOffService进行有限操作 publicclassNFCOffServiceextendsOffHostApduService{ @Override publicIBinderonBind(Intentintent){ //TODOAuto-generatedmethodstub returnnull; } } 上面没有提到的就是,如果你需要使用NFC,需要在Manifest中申请NFC权限: name="android.permission.NFC"/> name="android.hardware.nfc"android: required="true"/> 现在来说说NFC芯片作为读卡器的应用场景以及实现 android.nfc.tech,android.nfc接口是为NFC作为读卡器应用提供的接口 接口定义了三种ActionTags: ACTION_NDEF_DISCOVERED,ACTION_TECH_DISCOVERED,ACTION_TAG_DISCOVERED。 当你在Manifest文件中将Activity的action-filter设置为这三个Tag中的一种或几种时,NFC响应事件会按照如图流程处理 我的理解是ACTION_NDEF_DISCOVERED是用于两台NFC手机之间传输文件的 ACTION_TECH_DISCOVERED,ACTION_TAG_DISCOVERED才是用于NFC与卡进行通讯的 所以开发第一步是在Manifest中配置你的Action: android: name="com.shhic.nfcapp.POSActivity" android: label="@string/app_name"> name="com.nfc.pos"/> name="android.intent.category.DEFAULT"/> name="android.nfc.action.TECH_DISCOVERED"/> name="android.intent.category.DEFAULT"/> name="android.nfc.action.TECH_DISCOVERED" android: resource="@xml/nfc_tech_filter"/> name="android.nfc.action.TAG_DISCOVERED"/> name="android.intent.category.DEFAULT"/> TECH_DISCOVERED还需要配置meta-data,meta-data的作用相当于补充说明或者一些配置信息 nfc_tech_filter.xml xliff="urn: oasis: names: tc: xliff: document: 1.2"> 当然API中说明你可以将多个tech写在一个tech-list中,我做了尝试,这样做会引出一个问题,在程序未启动的情况下当手机刷卡时不会自动打开程序 如果想要自动打开需要按照上面这种写法,tech的个数可以根据你想要支持的卡类型进行调整 配置完成后,可以开始编写自己的Activity的java代码了 在onCreate方法中,需要获取NfcAdapter的引用,从名字可以看出这是一个适配器 NfcAdapternfcAdapter; PendingIntentpendingIntent; @Override protectedvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.pos_main); dc=(Button)findViewById(R.id.button4DC); ecc=(Button)findViewById(R.id.button4ECC); qpboc=(Button)findViewById(R.id.button4QPBOC); logWindow=(TextView)findViewById(Rmunication4Financy); nfcAdapter=NfcAdapter.getDefaultAdapter(this); pendingIntent=PendingIntent.getActivity( this,0,newIntent(this,getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),0); onNewIntent(getIntent()); } 这里使用PendingIntent,该Intent与普通的Intent不同的是它是有一个延迟启动的功能,它启动时会回调onNewIntent函数,这样能够实现NFC与Activity的交互 pendingIntent=PendingIntent.getActivity(this,0,newIntent(this,getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),0);的含义是将Intent传递给thisActivity 在onPause与onResume中需要添加代码 publicvoidonPause(){ super.onPause(); nfcAdapter.disableForegroundDispatch(this); } publicvoidonResume(){ super.onResume(); nfcAdapter.enableForegroundDispatch(this,pendingIntent,FILTERS,TECHLISTS); } enableForegroundDispatch的作用是,当NFC事件发生时如果当前Activity不是注册了NFCaction-filter的Activity,手机会显示注册了NFC事件的Activity供用户选择 如果当前Activity注册了NFCaction则将事件优先交由当前Activity处理。 onNewIntent实现: @Override publicvoidonNewIntent(Intentintent){ Parcelablep=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); if(p==null) { return; } TagnfcTag=(Tag)p; finalIsoDepisodep=IsoDep.get(nfcTag); // finalNfcAisodep=NfcA.get(nfcTag); finalbyte[]cmd={(byte)0x00,//CLAClass (byte)0xB4,//INSInstruction (byte)0x04,//P1Parameter1 (byte)0x00,//P2Parameter2 (byte)0x00,//Le }; try{ isodep.connect(); byte[]reaponse=null; logWindow.append("00B4040000"+'\n'); try{ reaponse=isodep.getHistoricalBytes(); logWindow.append(Util.bytes2HexString(reaponse)+'\n'); reaponse=isodep.transceive(cmd); logWindow.append(Util.bytes2HexString(reaponse)+'\n'); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } }catch(IOExceptione1){ //TODOAuto-generatedcatchblock e1.printStackTrace(); }finally{ try{ isodep.close(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } } 首先需要获取Tag,Tag是操作NFC的基础 Parcelablep=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); if(p==null) { return; } TagnfcTag=(Tag)p; 再将tag转换成特定的通讯协议 finalIsoDepisodep=IsoDep.get(nfcTag); 连接读卡器: isodep.connect(); 获取历史字节: rea
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- NFC 开发 学习 笔记 讲述