Android读取NfcA,TypeA类型的卡片抛Tag was Lost的异常。nfcaTag.transceive(cmd)中的Apdu命令怎么写

太坑不好 2014-12-23 11:23:12
用安卓的nfc现在读取一个标签,是NfcA类型,TypeA类型的卡片。
得到的Tag是:
android.nfc.tech.NfcA

下面是主程序:
package com.Qing.nfctest1;

import java.io.IOException;

import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.MifareUltralight;
import android.nfc.tech.Ndef;
import android.nfc.tech.NfcA;
import android.nfc.tech.NfcF;
import android.os.Bundle;
import android.os.Parcelable;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter.MalformedMimeTypeException;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
private NfcAdapter mNfcAdapter;
private TextView cardNoTxt;
private Boolean firstRun=true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cardNoTxt=(TextView)this.findViewById(R.id.cardNoTxt);
mNfcAdapter=NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter == null) {
Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();
// finish();
return;
}
//mNfcAdapter.setNdefPushMessageCallback(this, this);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void onNewIntent(Intent intent) {//响应intent
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
System.out.println("tagFromIntent..."+tagFromIntent.toString());
processTag(intent);
//do something with tagFromIntent
}
@Override
public void onResume() {//响应intent
super.onResume();
Intent intent=getIntent();
// new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
if(firstRun){//当第一次运行时,把应用注册成nfc tagdiscover intent的处理程序
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0,intent, 0);
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
IntentFilter techIntent=new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
IntentFilter tagIntent=new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
String[][] techListsArray = new String[][] { new String[] { NfcF.class.getName(),NfcA.class.getName()//程序可处理的tech类型
,MifareClassic.class.getName(),MifareUltralight.class.getName()} };
try {
ndef.addDataType("*/*"); /* Handles all MIME based dispatches.
You should specify only the ones that you need. */
}catch (MalformedMimeTypeException e) {
throw new RuntimeException("fail", e);
}
IntentFilter[] intentFiltersArray = new IntentFilter[] {ndef, techIntent,tagIntent};
mNfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);//
firstRun=false;
}
Log.i("NFCOnResume",intent.getAction());
// Check to see that the Activity started due to an Android Beam
if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
processTechDiscover(intent);
}else if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())){
processTagDiscover(intent);
}else if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())){
processNdefDiscover(intent);
}
}
public void processTag(Intent intent){//处理tag
String str="";
Boolean isNdef=false;
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
str+="Tech List:"+tagFromIntent.getTechList()[0]+"\n";//打印卡的技术列表
byte[] aa=tagFromIntent.getId();
str+="Card UID:"+bytesToHexString(aa)+"\n";//获取卡的UID
for(String tech:tagFromIntent.getTechList()){
if(tech.equals("android.nfc.tech.NfcA")){
isNdef=true;
}
}
if(isNdef){
NfcA nfcaTag=NfcA.get((Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));//我们的厂牌是NfcA技术,所以生成一个NfcaTag
			
try {
//ndefTag.connect();
nfcaTag.connect();//连接卡
String atqa="";
for(byte tmpByte:nfcaTag.getAtqa())
{
atqa+=tmpByte;
}
str+="tag Atqa:"+bytesToHexString(nfcaTag.getAtqa())+"\n";//获取卡的atqa
str+="tag SAK:"+nfcaTag.getSak()+"\n";//获取卡的sak
str+="max len:"+nfcaTag.getMaxTransceiveLength()+"\n";//获取卡片能接收的最大指令长度
byte[] cmd=null;
//cmd=new byte[]{0x41,0x54,0x4D,0x0A,0x52,0x01,0x00,0x01,(byte) 0xff,(byte)0xff,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,0x0D};
cmd=new byte[]{0x60,0x08,0xff,0xff,0xff,0xff,0xff,0xff};//卡请求
//TypeA 类型的第一个数据是0x60,我要想读的扇区是第2扇区的第0块,
//也就是第8块的数据,KeyA密码是六个字节的0xff,0xff,0xff,0xff,0xff,0xff
str+="Card Number:"+nfcaTag.transceive(cmd);
//发送命令到卡片(找不到这个标签扇区读取指令,有知道的同学告诉一声我们的卡是ISO/IEC 14443 typeA标准的),主要就是这个方法得不到返回的结果。因为指令不正确
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
nfcaTag.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
cardNoTxt.setText(str);
}
//字符序列转换为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();
}


运行的结果如下图:
有知道的联系我453161659@qq.com 感激不尽!
...全文
2907 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
清清0118 2017-03-10
  • 打赏
  • 举报
回复
有解决的嘛= =
sendy1211 2016-08-22
  • 打赏
  • 举报
回复
各位大神,有没有解决的?
满意 2016-06-12
  • 打赏
  • 举报
回复
楼主解决了吗
cike110120 2015-07-17
  • 打赏
  • 举报
回复
楼主解决了吗
zou607 2015-03-20
  • 打赏
  • 举报
回复
楼主,搞定了没?我最近也在接触andord nfc,读取的也是mifare S50(TYPE A)。方法也和你一样,不过我还没搞出来,请教你你老人家,望你能慷慨帮忙!我QQ: 181900156,希望你能指教一下,相互学习。
lfqsy 2015-03-06
  • 打赏
  • 举报
回复
老兄,搞定了没,其实我也知道这个是NFC芯片的问题,用命令也应该可以实现的
wind299792458 2015-01-28
  • 打赏
  • 举报
回复
手机问题,有的手机不支持mifareClassic,换个手机就可以读了
最爱麦丽素 2014-12-26
  • 打赏
  • 举报
回复
话说命令你是哪里找的,我只有iso的英文文档。

58,454

社区成员

发帖
与我相关
我的任务
社区描述
Java Eclipse
社区管理员
  • Eclipse
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧