您的位置:首页 > 移动开发 > Android开发

[置顶] Android应用接收NFC读卡

2018-01-19 16:14 501 查看
最近在看NFC功能,重点就是我在页面上设置了一个按钮,要点击此按钮才会开启NFC读卡功能(并非跳转下个Activity),为了方便使用,为此可以专门设置一个基类Activity作为NFC功能的管理,此处我命名为TestNfcBaseActivity

public abstract class TestNfcBaseActivity extends BaseActivity {

//    private NfcManager mNfc;
private boolean mIsWidthLifeCycle = true;
public static final int REQ_NFC_OPEN = 0X9000;
private boolean isOpenNfcByManual = false;

private Activity activity;
private NfcAdapter nfcAdapter;
private PendingIntent pendingIntent;

private static String[][] TECHLISTS;  //设置你要处理的tag technologies到String数组中
private static IntentFilter[] TAGFILTERS;
private int status;

/** 设备不支持NFC */
public static final int NFC_NOT_SUPPORT = -1;
/** NFC已关闭 */
public static final int NFC_DISABLED = 0;
/** NFC开启了 */
public static final int NFC_ABLED = 1;

/** nfc tag */
private Tag mTag;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initDatas();
}

/**
* 是否需要开启NFC相关对象,由于nfc 圈存和ble 圈存公用一套UI,ble圈存是不需要初始化NFC,所以需要让子类决定。
* @return true 需要初始化nfc
*/
public abstract boolean isOpenNfc();

private void initDatas() {
setTECHLISTSandTAGFILTERS();
activity = getActivity();
pendingIntent = PendingIntent.getActivity(activity, 0,
new Intent(activity, activity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
//        pendingIntent = PendingIntent.getActivity(activity, 0,
//                new Intent(activity, getClass()), 0);
if(isOpenNfc()){
initNfcManagerByManual(false);
}
if(isOpenNfcByManual){
initNfcManagerByManual(true);
}
}

public BaseNfcNewActivity getActivity(){
return this;
}

public void initNfcManagerByManual(boolean isOpenNfcByManual){
this.isOpenNfcByManual = isOpenNfcByManual;
if(nfcAdapter != null){
ReaderManager.destory();
nfcAdapter = null;
}
nfcAdapter = NfcAdapter.getDefaultAdapter(activity);
status = getNfcStatus();
LogUtils.LogError("lenita","nfc status = "+status);
if(isOpenNfcByManual){
onResume(); //在生成Adapte后执行,否则无法进入
}
}

public Tag getNfcTag() {
return mTag;
}

public void setNfcTag(Tag mTag) {
this.mTag = mTag;
}

private void setTECHLISTSandTAGFILTERS(){
try {
TECHLISTS = new String[][] { {  IsoDep.class.getName() } };
TAGFILTERS = new IntentFilter[] { new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED, "*/*") };
} catch (Exception e) {
}
}

public boolean updateNfcStatus() {
int sta = getNfcStatus();
if (sta != status) {
status = sta;
return true;
}
return false;
}

/** 获取设备NFC状态 */
public int getNfcStatus() {
return (nfcAdapter == null) ? NFC_NOT_SUPPORT : nfcAdapter.isEnabled() ? NFC_ABLED : NFC_DISABLED;
}

/**
* 读卡信息并初始化android.nfc.Tag
*
* @param intent
* @param requesetCode
*            请求码,回调使用
* @param listener
*            回调监听
* @return 是否执行成功
*/
public boolean readCard(Intent intent, int requesetCode, ReaderListener listener) {
final Tag tag = (Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
this.mTag = tag;
if (tag != null) {
ReaderManager.readCardExecute(requesetCode, tag, listener);
return true;
}
return false;
}

/**
* 已经初始化tag,可直接调用读取方法
*
* @param requesetCode
* @param listener
* @return
*/
public boolean readCard(int requesetCode, ReaderListener listener) {
if (mTag != null) {
ReaderManager.readCardExecute(requesetCode, mTag, listener);
return true;
}
return false;
}

/**
* 发送tlv格式指令,执行出错根据tlv解析
*
* @param requesetCode
* @param instructions
*            tlv指令集
* @param listener
* @return 是否执行成功
*/
public boolean sendTlvCmd(int requesetCode, String instructions, ReaderListener listener) {
if (mTag != null) {
ReaderManager.sendTlvCmdExecute(requesetCode, mTag, instructions, listener);
return true;
}
return false;
}

public boolean sendCmd(int requesetCode, String cmd, ReaderListener listener) {
return sendCmds(requesetCode, new String[] { cmd }, listener);
}

/**
* 发送数组指令集,执行当条出错时,仍然继续执行
*
* @param requesetCode
* @param cmds
*            数组指令集
* @param listener
* @return 是否执行成功
*/
public boolean sendCmds(int requesetCode, String[] cmds, ReaderListener listener) {
if (mTag != null) {
ReaderManager.sendArrayCmdExecute(requesetCode, mTag, cmds, listener);
return true;
}
return false;
}

public void destory() {
ReaderManager.destory();
}

/* public final NfcManager getNfc() {
return mNfc;
}*/

@Override
protected void onResume() {
super.onResume();
LogUtils.LogError("lenita","onResume() - isOpenNfcByManual = " +isOpenNfcByManual);
if(isOpenNfc() || isOpenNfcByManual){
if (mIsWidthLifeCycle) {
//设置处理优于所有其他NFC的处理
if (nfcAdapter != null){
nfcAdapter.enableForegroundDispatch(activity, pendingIntent, TAGFILTERS, TECHLISTS);
}
}
}
}

@Override
protected void onPause() {
super.onPause();
LogUtils.LogError("lenita","onPause()");
if(isOpenNfc() || isOpenNfcByManual){
if (mIsWidthLifeCycle) {
if (nfcAdapter != null){
nfcAdapter.disableForegroundDispatch(activity);
}
}
}
}

/**
* Nfc 是否根据生命开启关闭
*
* @param enable
*/
public void setNfcWidthLifeCycle(boolean enable) {
mIsWidthLifeCycle = enable;
}

/**
* 如果nfc 不支持,或未开启。打开对话提示
* @return 如果已经开启,返回true 不做任何对话框提示
*/
public final boolean showNfcProblemDialog() {
/*if(mNfc == null){
showLongToastCenter("NFC管理器为空,无法初始化NFC功能");
}*/
int nfcStatus = getNfcStatus();
if (!isFinishing()) {
if (nfcStatus == NfcManager.NFC_NOT_SUPPORT) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(false);
builder.setTitle("提示").setMessage(com.uroad.nfc.R.string.info_nfc_not_support).setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
onNfcNotSupportClick();
}
});
builder.create().show();
} else if (nfcStatus == NfcManager.NFC_DISABLED) {
DialogHelper.showComfirmDialog(this, getString(android.R.string.cancel), "去开启", getString(com.uroad.nfc.R.string.info_nfc_tips_open),  new ComfirmDialog.DialogOnclick() {

@Override
public void PerDialogclick(ComfirmDialog dialog) {//取消
onNfcDisabledCancelClick(dialog);
}

}, new ComfirmDialog.DialogOnclick() {

@Override
public void PerDialogclick(ComfirmDialog dialog) {//确定
onNfcDisabledGoOpenClick(dialog);
}

});

}
}

if(nfcStatus == NfcManager.NFC_ABLED){
return true;
}

return false;

}

/**
* 设备不支持NFC功能
*/
public void onNfcNotSupportClick() {

};

/**
* NFC 未开启,前往开启
*/
public void onNfcDisabledGoOpenClick(ComfirmDialog dialog) {
startNfcSettingsActivity();
dialog.dismiss();
}

/**
* NFC 未开启,前往开启
*/
public void onNfcDisabledCancelClick(ComfirmDialog dialog) {
dialog.dismiss();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
LogUtils.i("onActivityResult requestCode:"+requestCode);
LogUtils.i("onActivityResult resultCode:"+resultCode);
}

private void startNfcSettingsActivity() {
try {
startActivityForResult(new Intent("android.settings.NFC_SETTINGS"), REQ_NFC_OPEN);
} catch (Exception e) {
startActivityForResult(new Intent(ACTION_SETTINGS), REQ_NFC_OPEN);
}
}

@Override
protected void onDestroy() {
super.onDestroy();
if(isOpenNfc() || isOpenNfcByManual){
destory();
}
}
}


封装好基类后,首先先分析一下,上面弄了两种方法,一种是重写isOpenNfc()方法,一种是手动开启方法,下面将写出这两种启动方法的区别,我们设计一个布局来显现,一段提示文字和一张图片
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:layout_marginTop="40dp">
<TextView
android:layout_width="match_parent"
android:layout_height="40dp"
android:text = "点击图片开启NFC读卡功能"
android:textColor="@color/red"
android:gravity="center"
android:textSize="20dp"/>
<ImageView
android:id="@+id/iv_nfc_click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:src="@drawable/bg_quancun_connect_nfc" />
</LinearLayout>

</LinearLayout>


然后是使用的Activity:

一、自动开启NFC,不需要点击才开启的
/**
*@date 创建时间:2018/01/15
*@author  lan.zheng
*/
public class PhotographActivity extends TestNfcBaseActivity{
ImageView imageView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//初始化
setBaseContentLayout(R.layout.test_nfc_activity);
//        initView();
}

/**
* 是否是自动进入该页面初始化Nfc功能,false:不启动,true:初始化
* @return
*/
@Override
public boolean isOpenNfc() {
return true;
}

}
二、手动开启的,假设点击图片可以开启Nfc功能

/**
*@date 创建时间:2018/01/15
*@author  lan.zheng
*/
public class PhotographActivity extends TestNfcBaseActivity{
ImageView imageView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//初始化
setBaseContentLayout(R.layout.test_nfc_activity);
initView();
}

private void initView() {
imageView = (ImageView) findViewById(R.id.iv_nfc_click);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//TODO 手动开启Nfc
initNfcManagerByManual(true);
}
});
}

/**
* 是否是自动进入该页面初始化Nfc功能,false:不启动,true:初始化
* @return
*/
@Override
public boolean isOpenNfc() {
return false;
}

}
开启了Nfc功能,接下来就是要进行贴卡后数据的监听回调和处理,此处需要实现implements ReaderListener接口,然后重写onReadEvent方法,首先我们先写用于监听读卡的,在Activity中:


public final static int REQ_READ_CARD = 0x01;

    @Override
protected void onNewIntent(final Intent intent) {
super.onNewIntent(intent);
LogUtils.i("onNewIntent Thread ID:" + Thread.currentThread().getId());
runOnUiThread(new Runnable() {

@Override
public void run() {
readCard(intent, REQ_READ_CARD, PhotographActivity.this);
}
});

}


当贴卡后,onReadEvent就会拦截到读到的卡片:

@Override
public void onReadEvent(int requestCode, SPEC.EVENT event, Object... obj) {
if (requestCode == REQ_READ_CARD) {
if (event == SPEC.EVENT.SUCCESS) {
PCard pCard = (PCard) obj[0];
LogUtils.e(pCard.toString());
if (XXX) {
//是否为满足条件的卡
final String cardno = pCard.getSn()+pCard.getCardNumber();
showLongToastCenter("卡号为:"+cardno);
}
}
else if (event == SPEC.EVENT.ERROR) {
Integer resultCode = (Integer) obj[0];
LogUtils.e("onReadEvent - error - code :" + resultCode);
showLongToastCenter(getString(R.string.info_nfc_read_card_error));
}
}

来手动启动NFC读卡的图片,首先需要你赋予应用NFC权限:



开启后拿卡片进行读卡,此处模拟读到卡号:



好了,以上就是NFC读卡的功能,网上面的参考资料很多,由于没有太多注解,所以还是给个参考文章吧:

http://blog.csdn.net/zhuangxiaotang/article/details/45248093


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: