从上一篇的NFC支持所类型的卡读取之后,下面要解决的就是NFC的拦截响应,如果这一步没有做,当系统内有多个支持NFC的应用的时候,就会在nfc刷卡的时候弹出多个应用选择,我们需要的场景是,当前应用需要用NFC才去刷卡,然后本应用拦截intent分发(Using the Foreground Dispatch System).
具体的方案:
1.创建PendingIntent来分发要响应的Activity
mPendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, NFCActivity.class).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
2.当刷卡的时候,使用intent过滤器来过滤出你要拦截的Intent
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
ndef.addDataType("*/*");
} catch (IntentFilter.MalformedMimeTypeException e) {
throw new RuntimeException("fail", e);
}
intentFiltersArray = new IntentFilter[]{ndef,};
3.设置你要处理的tag technologies到String数组中
techListsArray = new String[][]{new String[]{NfcA.class.getName()}};
4.在onResume和onPause中设置NFCAdapter
public void onPause() {
super.onPause();
mAdapter.disableForegroundDispatch(this);
}
public void onResume() {
super.onResume();
mAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
}
当然之前要定义NfcAdapter
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
import com.hwuao.ocis.R;
import com.hwuao.ocis.components.easyAndroid.BaseActivity;
import com.hwuao.ocis.components.easyAndroid.ContentView;
import com.hwuao.ocis.components.easyAndroid.tool.AppLogger;
import com.hwuao.ocis.event.GetNFCCardEvent;
import com.hwuao.ocis.util.StringUtils;
import com.hwuao.ocis.util.ToastUtil;
/**
* NFC响应页面
*
* @author Jinyang
*/
@SuppressLint("NewApi")
@ContentView(R.layout.activity_nfc)
public class NFCActivity extends BaseActivity {
public static final String TAG = "NFCActivity";
private NfcAdapter nfcAdapter;
private String mClientCardNfcId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initNfcParse();
resolveIntent(getIntent());
}
private void initNfcParse() {
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter == null) {
AppLogger.e("---->Nfc error !!!");
Toast.makeText(getApplicationContext(), "不支持NFC功能!", Toast.LENGTH_SHORT).show();
} else if (!nfcAdapter.isEnabled()) {
AppLogger.e("---->Nfc close !!!");
Toast.makeText(getApplicationContext(), "请打开NFC功能!", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
resolveIntent(intent);
}
@Override
public void onResume() {
super.onResume();
AppLogger.e("---->onDestroy");
if (nfcAdapter != null) {
if (!nfcAdapter.isEnabled()) {
showWirelessSettingsDialog();
}
}
}
private void showWirelessSettingsDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("不支持此卡");
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;
}
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 tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String nfcId = dumpTagData(tag);
if (!nfcId.isEmpty()) {
mClientCardNfcId = nfcId;
Log.i(TAG, "卡的内容" + mClientCardNfcId);
eventBus.post(new GetNFCCardEvent(mClientCardNfcId));
finish();
} else {
ToastUtil.showToastLong(getApplicationContext(), "识别失败!请重新刷卡!");
}
}
}
private String dumpTagData(Parcelable p) {
Tag tag = (Tag) p;
byte[] id = tag.getId();
return StringUtils.hexToHexString(id);
}
}
这个问题的解决体会到一件事,这个问题在国内的博客论坛都没有搜索到,在StackOverFlow上有一篇
里面的链接指向的是Android develop。。。NFC foreground dispatching.
所有的基础教程都可以在developer中找到,以后再也不瞎折腾了,有问题找google
源码请见
https://github.com/xujinyang/NFCALL