安卓开发中应用的NFC基础知识点 Android安全

桃汁 2017-10-27 16745

NFC科技代表近场通信,通常可以在 NFC论坛上找到 NFC的详细信息。下面我们将分析NFC 的一些基础知识,并且我们还将描述如何在安卓系统中实现一个利用 NFCAPP(应用程序)。

 

如果你想做 NFC 实验,那么你在几个网站上花费几欧元就能买到NFC

 

NFC 可以用于不同的情景:在家中时,我们可以使用它来打开 WiFi或者执行一些任务操作等等。

 

我们将注意力集中在 NDEF数据,它是一种特殊类型的 NFC标记。不过,在使用 NFC之前,我们必须遵循一些基本步骤。

 

NFC 过滤器

 

当我们使用 NFC标记时,我们要做的第一件事就是,当我们接近一个 NFC标记的时候,我们的 APP 可以收到通知。为了实现这个目的,我们需要使用一个意图过滤器。安卓SDK中提供了三种不同的过滤器,我们可以以不同的优先级来使用它们:

 

ACTION_NDEF_DISCOVERED

ACTION_TECH_DISCOVERED

ACTION_TAG_DISCOVERED

 

我们重点关注 ACTION_NDEF_DISCOVERED,它拥有最高的优先级。正如前面所说的,我们的目的是,当智能手机接近一个 NFC 标记时能够收到通知,并且如果我们只安装了这一个 APP,并且它能够处理这个NFC标记,那么我们希望该APP能够立即开始处理。为了实现这一点,我们在Manifest.xml中注册过滤器:

 

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.survivingwithandroid.nfc" >

....

<intent-filter>

<action android:name="android.nfc.action.NDEF_DISCOVERED" />

<category android:name="android.intent.category.DEFAULT" />

<data android:mimeType="text/plain"/>

</intent-filter>

<manifest>

 

在第6行,我们注册了 APP,以使得它可以收到 ACTION_NDEF_DISCOVERED通知。我们使用不同类型的过滤器,在这个例子中(第 8 行)我们使用了 mine 类型。换句话说,当发现一个 NFC标记NDEF并且它的 mine类型为“text/plain”时,我们的 APP将会启动。其实,我们可以使用几种 mine 类型来过滤,而不仅仅是 text/plain。此外,我们还能以协议或一个字符串模式来使用其他类型的过滤器(如 android:scheme)来过滤。

 

NFC 前台调度

 

如果我们的 APP 没处于前台,就会开始意图过滤。如果我们的应用程序运行在前台,那么当我们的智能手机移动到一个NFC标记时,它将不会收到通知。在这种情况下,我们必须使用一种称为NFC前台调度的技术。第一步是,在我们的代码中定义意图过滤器(正如我们在 Manifest.xml 中做的那样):

 

@Override

protected void onCreate(Bundle savedInstanceState) {

...

Intent nfcIntent = new Intent(this, getClass());

nfcIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

nfcPendingIntent =

PendingIntent.getActivity(this, 0, nfcIntent, 0);

IntentFilter tagIntentFilter =

new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);

try {

tagIntentFilter.addDataType("text/plain");

intentFiltersArray = new IntentFilter[]{tagIntentFilter};

}

catch (Throwable t) {

t.printStackTrace();

}

}

 

现在,我们必须注册我们的过滤器,在 onResume方法中以这种方式实现它:

 

protected void onResume() {

super.onResume();

nfcAdpt.enableForegroundDispatch(

this,

nfcPendingIntent,

intentFiltersArray,

null);

handleIntent(getIntent());

}

 

此外,也应该记住,只要APP退回到后台,我们就应该关闭前台调度,而要实现这一点,最好的地方是在onPause方法中。

 

@Override

protected void onPause() {

super.onPause();

nfcAdpt.disableForegroundDispatch(this);

}

 

其中,nfcAdpt NFC适配器。

 

使用 NFCAdapter处理NFC

 

一旦我们创建了过滤器,我们必须与智能手机中的 NFC 组件交互。为此,我们使用安卓 SDK 提供的 NfcAdapter。使用这个类,我们能够检测智能手机是否支持NFC,或者NFC功能是否开启或关闭。

 

@Override

protected void onCreate(Bundle savedInstanceState) {

...

nfcAdpt = NfcAdapter.getDefaultAdapter(this);

// Check if the smartphone has NFC

if (nfcAdpt == null) {

Toast.makeText(this, "NFC not supported", Toast.LENGTH_LONG).show();

finish();

}

// Check if NFC is enabled

if (!nfcAdpt.isEnabled()) {

Toast.makeText(this, "Enable NFC before using the app", Toast.LENGTH_LONG).show();

}

}

 

NFC数据:负载

 

既然我们知道了如何处理NFC标记,接着我们就想读取标记内容。在NFC说明文档中,定义了几种程序开发类型的内容:

 

NFC Forum well-known type

Media-type

Absolute URI

NFC Forum external type

 

每种类型都有它自己的有效负载。一般来说,一个NFC NDEF数据由一条信息组成,一条信息可以包含一个或多个记录,每个记录由一个头和一个负载(真正的信息)组成。现在,如果我们想读取NFC NDEF标记中的数据,我们可以使用下面的代码:

 

@Override

public void onNewIntent(Intent intent) {

Log.d("Nfc", "New intent");

getTag(intent);

}

private void getTag(Intent i) {

if (i == null)

return ;

String type = i.getType();

String action = i.getAction();

List dataList = new ArrayList();

if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {

Log.d("Nfc", "Action NDEF Found");

Parcelable[] parcs = i.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);

for (Parcelable p : parcs) {

recNumberTxt.setText(String.valueOf(numRec));

NdefRecord[] records = msg.getRecords();

for (NdefRecord record: records) {

short tnf = record.getTnf();

// Here we handle the payload

}

}

}

}


最新回复 (1)
全部楼主
返回
发新帖