《Android NFC开发实战详解》——6.2节Android NFC P2P开发基础

简介:

本节书摘来自异步社区《Android NFC开发实战详解》一书中的第6章,第6.2节Android NFC P2P开发基础,作者 赵波,更多章节内容可以访问云栖社区“异步社区”公众号查看

6.2 Android NFC P2P开发基础
Android NFC开发实战详解
本节主要介绍Android NFC P2P开发中的一些基础知识,为后续的实例开发提供基础。通过本章的学习,使读者熟悉Android中Beam实现的几种方式,Beam NDEF消息和接收Beam消息的方法,同时也会对第4章中提到的Intent过滤机制在P2P中的使用进行阐述。

6.2.1 Android Beam实现的几种方式
在Android中,目前,Beam功能实现的方式可以概括为三种,分别为setNdefPushMessage Callback( )、setNdefPushMessage( )以及enableForegroundNdefPush( )。

上述方法中,enableForegroundNdefPush( )是在API 10中加入的提供Android NFC P2P功能方法。从严格意义上,该方法并不能称为Beam方法,API 14中加入的前面两个方法才算真正的Beam功能。因为Beam的概念是在API 14中提出的,其操作过程中需要用户的介入(用户点击从而选择Beam的发送端),所以,此处为了描述方便(且Beam功能的本质也即P2P),故将其与Beam功能放一处,读者只需搞清其中的原因即可。

1.enableForegroundNdefPush( )方法的原型
void enableForegroundNdefPush(Activity activity, NdefMessage message):在指定的activity中,enable前台通过P2P Push NDEF消息功能。

其中,activity为前台activity;message为将要Push的NDEF消息。当调用该方法的该activity不再前台时,将会抛出异常。

使用enableForegroundNdefPush()方法时,应注意以下几点:

(1)在activity中,必须确保每次Resume时,调用该方法,同时每次Paused时调用disable ForegroundNdefPush方法;

(2)Android官方强烈推荐使用setNdefPushMessage方法(API 14+)代替该方法,因为setNdefPushMessage方法将自动根据Android的生命周期来使能,无需开发者自己enable和disable;

(3)activity在调用该方法时,必须是在主线程中;

(4)使用该方法需要在AndroidManifest.xml中添加NFC权限;

(5)使用该方法需要在Android API 10+以上的系统中进行。

2.disableForegroundNdefPush ( )方法的原型
void disableForegroundNdefPush(Activity activity):在指定的activity中,disable 通过P2P Push NDEF消息的功能。

其中,activity为前台activity。如果当调用该方法的该activity已经停止了(paused),那么将会抛出异常信息。

使用disableForegroundNdefPush()方法时,应注意以下几点:

(1)activity在调用该方法时,必须在onPause( )之前;

(2)activity在调用该方法时,必须是在主线程中;

(3)Android官方强烈推荐使用setNdefPushMessage方法(API 14+)代替该方法,因为setNdefPushMessage方法将自动根据Android的生命周期来使能,无需开发者自己enable和disable;

(4)使用该方法需要在AndroidManifest.xml中添加NFC权限;

(5)使用该方法需要在Android API 10+以上的系统中进行。

setNdefPushMessageCallback( )和setNdefPushMessage( )是API 14+中加入的实现Beam功能的方法。setNdefPushMessage( )中把接收到的NdefMessage对象作为一个消息设置给Beam,当两个设备足够近的时候,就会自动的发送消息;setNdefPushMessageCallback()方法中将接收包含createNdefMessage()方法的回调,当设备在发射数据的范围内时,这个回调方法会被调用,回调会让你只在需要的时候创建NDEF消息。

3.setNdefPushMessage ( )方法的原型
public void setNdefPushMessage (NdefMessage message, Activity activity, Activity... activities):通过Android Beam发送静态NDEF消息句。

其中,message为待发送的静态NDEF消息。为NULL时,当前activity的setNdefPushMessage功能将会disable;activity为当前push消息的activity;activities为附加activity。强烈建议在每个activity中,该方法只注册一次。

使用setNdefPushMessage()方法时注意以下几点:

(1)activity在调用该方法时,可以在onDestroy( )之前的任何地方,官方建议在onCreate()中调用;

(2)该方法并不阻塞线程,所以可以在UI主线程中使用;

(3)使用该方法时,如果message为null,则调用该方法的Activity的setNdefPushMessage功能将会disable;

(4)当同时使用该方法和setNdefPushMessageCallback( )方法时,setNdefPushMessage Callback方法具有较高优先级;

(5)如6.1.2节所述,在两个Android NFC设备靠近时,如果发送设备上(BNM)当前打开的应用程序并没有实现Android Beam功能,那么系统也会自动发送一条默认的NDEF消息给接收端(RBM);如果要想阻止Android系统发送默认的NDEF消息,那么可以在AndroidManifest.xml中的application添加如下代码:

<application ...>
    <meta-data android:name="android.nfc.disable_beam_default"
        android:value="true" />
</application>
(6)关于该方法的使用,官方提供的使用范例如下(关于更详细的使用方法,读者可以参考本节后面的具体实例):

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
    if (nfcAdapter == null) return;  // NFC not available on this device
    nfcAdapter.setNdefPushMessage(ndefMessage, this);
}

(7)使用该方法需要在AndroidManifest.xml中添加NFC权限;

(8)使用该方法需要在Android API 10+以上的系统中进行。

4.setNdefPushMessageCallback ( ) 方法的原型
public void setNdefPushMessageCallback (NfcAdapter.CreateNdefMessageCallback callback, Activity activity, Activity... activities):其中,callback为回调接口;activity为待Push NDEF消息的activity;activities为附加activity选项。强烈建议在每个activity中,该方法只注册一次。

使用setNdefPushMessageCallback()方法时,应注意以下几点:

(1)activity在调用该方法时,可以在onDestroy( )之前的任何地方,官方建议在onCreate()中调用;

(2)该方法并不阻塞线程,所以可以在UI主线程中使用;

(3)使用该方法时,如果callback为null,则该Activity的NDEF Push功能将会disable;

(4)当同时使用该方法和 setNdefPushMessage( )方法时,该方法具有较高优先级;

(5)如6.1.2节所述,在两个Android NFC设备靠近时,如果发送设备上(BNM)当前打开的应用程序并没有实现Android Beam功能,那么系统也会自动发送一条默认的NDEF消息给接收端(RBM),如果要想阻止Android系统发送默认的NDEF消息,那么可以在AndroidManifest.xml中的application添加如下代码:

<meta-data android:name="android.nfc.disable_beam_default"
    android:value="true" />


(6)关于该方法的使用,官方提供的使用范例如下(关于更详细的使用方法,读者可以参考本节后面的具体实例):

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
    if (nfcAdapter == null) return;  // NFC not available on this device
    nfcAdapter.setNdefPushMessageCallback(callback, this);
}

(7)使用该方法需要在AndroidManifest.xml中添加NFC权限;

(8)使用该方法需要在Android API 10+以上的系统中进行。

6.2.2 Beam NDEF消息(BNM)
两个NFC设备之间通过Beam实现数据传递时,数据发送端即Beam NDEF消息端,本书中简写为BNM(Beam NDEF Message)。在BNM时,首先需要准备NDEF记录和消息。创建NDEF记录和消息的方法和第5章中相同,读者可参考第5章的相关内容。

Android中提供了两种BNM的方法(enableForegroundNdefPush()除外),分别为setNdefPush MessageCallback( )和setNdefPushMessage( ),下面分别对这两种方法BNM的实现步骤进行阐述,具体实例参考本章6.3中的相关内容。

1.BNM By setNdefPushMessageCallback( )的使用步骤
(1)在Activity中实现CreateNdefMessageCallback接口;

(2)在需要的地方调用setNdefPushMessageCallback( )方法;

(3)在回调函数(createNdefMessage(NfcEvent))中实现Beam Data。

其中,在第2步中,setNdefPushMessageCallback( )中NDEF消息的生成是动态的,开发中可以在其Activity中的任何地方实现调用(笔者建议首选onCreate( ))。当有BNM发现有目标设备(RBM)时,系统会自动激活createNdefMessage(NfcEvent)回调接口函数,此时,该回调接口函数中返回的NDEF消息被发送给RBM,开发者需要做的就是在回调接口中准备Beam Data即可。

2.BNM By setNdefPushMessage ( )的使用步骤
(1)创建NDEF消息;

(2)在需要的地方调用setNdefPushMessage( )方法。

其中,在第2步中,setNdefPushMessage( )中NDEF消息的生成是静态的,即由用户选择生成然后作为参数进行传递。

3.setNdefPushMessageCallback( )和setNdefPushMessage( )的选择
当应用程序Activity需要在任何时候都推送相同的NDEF消息时,可使用setNdefPushMessage( )方法;当应用程序Activity希望根据用户不同的操作行为来进行推送时,可使用setNdefPush MessageCallback( )方法。当Activity中两者都使用时,由于setNdefPushMessageCallback( )的优先级要高于setNdefPushMessage ( ),因此系统会首选setNdefPushMessageCallback( )方法。

注意,在上述两种方法中,若NDEF消息为NULL,此时,NDEF Push功能在该Activity中将被Disable。

6.2.3 接收Beam消息(RBM)
两个NFC设备之间通过Beam实现数据传递时,数据接收端即接收Beam消息端,本书中简写为RBM(Receive Beam Message)。接收Beam消息的方法与第五章中接收Tag消息类似,实现步骤如下:

(1)在应用中实现onNewIntent( Intent)方法,该方法会调用setIntent(Intent),由第3章的Android生命周期描述中可知,在使用onNewIntent(Intent)方法后,onResume()方法会自动调用;

(2)在应用的onResume( )方法中,检测当前消息是否来自Beam,如果是,获取并处理该NDEF消息;

(3)调用自己定义的消息解析函数,将获取的NDEF消息解析并获取Payload,再对Payload进行进一步UI操作。

6.2.4 enableForegroundNdefPush的使用
在API 14+的Android系统中,可以使用上述两种方法实现Beam功能的开发。若系统在API 10~API 13之间,或者说希望在API 10~API 13之间的Android系统的用户也同样能够使用该APP,此时需要考虑第3种方式:enableForegroundNdefPush( )方法。

关于enableForegroundNdefPush( )方法可参考6.2.1节中的描述,同时还可参阅第4章中介绍的NFC前台调度系统的相关知识。本节为大家介绍通过enableForegroundNdefPush( )方法实现Beam功能的开发步骤,具体实例参见6.3节的内容。

通过enableForegroundNdefPush( )方法实现(发送端)Beam 功能开发步骤如下:

(1)创建需要Beam的NDEF数据;

(2)在Activity需要的地方中调用enableForegroundNdefPush (Activity activity, NdefMessage message)方法;在该方法中,message为步骤1中创建的NDEF消息,该方法创建后,message处于挂起状态;一旦系统检测到RBM设备,该message就会通过Beam传输给接收端;

(3)在应用程序的onPause( )方法中,需要调用disableForegroundNdefPush(Activity)方法;由于这是一种前台推送方法,因此,一旦Activity不出于前台,Foreground NDEF Push就要立即停止;

(4)在应用程序的onResume( )方法中,可以通过调用enableForegroundNdefPush (Activity activity, NdefMessage message)再次启用Foreground NDEF Push推送。

通过enableForegroundNdefPush( )方法实现(接收端)Beam 功能开发步骤如下:

(1)在应用中实现onNewIntent( Intent)方法,在该方法中调用setIntent(Intent);由第3章介绍的Android生命周期的描述中可知,在使用onNewIntent(Intent)方法后,onResume()方法会自动调用;

(2)在应用程序的onResume( )方法中,检测当前消息是否来自Beam,如果是,获取该NDEF消息;

(3)解析并处理接收到的NDEF数据。

上述接收端的实现方法其实还是NFC标签调度系统实现的。与enableForegroundNdefPush( )对应的,如果需要彻底的使用前台调度系统,那么可以使用enableForegroundDispatch()方法。关于该方法的描述如下。

1.enableForegroundDispatch ( )方法的原型
void enableForegroundDispatch(Activity activity, PendingIntent intent, IntentFilter[] filters, String[][] techLists):在指定的activity中enable前台dispatch功能。

其中,activity为将要dispatch to的activity;intent为将启动dispatch的PendingIntent;filters为过滤dispatch信息。activity为null时,表示一直处理所有信息。techLists用来匹配ACTIONTECH DISCOVERED意图。

如果当调用该方法的该activity已经不再前台了,就会抛出异常信息。

使用enableForegroundDispatch()方法时,应注意以下几点:

(1)当使用该方法时,当前activity发现有Tag信息时,前台Dispatch拥有最高优先级 ——即,第4章中所描述的当APP同时拥有NFC前台调度系统和NFC标签调度系统时,NFC前台调度系统优先级高于NFC标签调度系统;

(2)IntentFilter过滤dispatch信息,包括ACTIONNDEF_DISCOVERED和ACTION Tag_DISCOVERED两种;

(3)当APP中的filters和techLists都为NULL时,当前activity将接收所有的Tag信息通过ACTION_NDEF_DISCOVERED意图;

(4)activity在调用该方法时,必须是在主线程中,且必须是前台activity——即,当activity即将处于后台时(onPause或onDestroy),需要调用disableForegroundDispatch方法;

(5)使用该方法需要在AndroidManifest.xml中添加NFC权限;

(6)使用该方法需要在Android API 10+以上的系统中进行。

2.disableForegroundDispatch ( )方法的原型。
void disableForegroundDispatch(Activity activity):在指定的activity中disable前台dispatch功能。

其中,activity为将要disable的activity。如果调用该方法的activity的ForegroundDispatch已经disable了,就会抛出异常信息。

使用disableForegroundDispatch()方法时,应注意以下几点:

(1)activity在调用该方法时,必须在onPause( )之前;

(2)activity在调用该方法时,必须是在主线程中;

(3)使用该方法需要在AndroidManifest.xml中添加NFC权限;

(4)使用该方法需要在Android API 10+以上的系统中进行。

3.具体开发步骤
(1)在应用中实现onNewIntent( Intent)方法,并在该方法中调用setIntent(Intent)。由第3章所介绍的Android生命周期的描述中可知,在使用onNewIntent(Intent)方法后,onResume()方法会自动调用。

(2)在应用的onResume( )方法中,调用enableForegroundDispatch( ),使当前activity的前台调度系统有效。

(3)在应用的onPause ( )方法中,调用disableForegroundDispatch ( ),使当前activity的前台调度系统disable。

相关文章
|
6天前
|
开发工具 Android开发 iOS开发
探索Android与iOS开发的差异与挑战
【7月更文挑战第11天】在移动应用开发的广阔天地中,Android和iOS两大平台如同双子星座般耀眼,各自拥有独特的开发生态和用户群体。本文将深入分析这两个平台的显著差异,从技术架构到开发工具,再到市场定位,揭示它们之间的异同。通过比较,我们不仅能够更好地理解各自的优势和局限,还能洞察未来移动应用开发的趋势。
|
3天前
|
Android开发 Kotlin
kotlin开发安卓app,如何让布局自适应系统传统导航和全面屏导航
使用`navigationBarsPadding()`修饰符实现界面自适应,自动处理底部导航栏的内边距,再加上`.padding(bottom = 10.dp)`设定内容与屏幕底部的距离,以完成全面的布局适配。示例代码采用Kotlin。
32 15
|
3天前
|
存储 API Android开发
kotlin开发安卓app,使用webivew 触发 onShowFileChooser, 但只能触发一次,第二次无法触发,是怎么回事。 如何解决
在Android WebView开发中,`onShowFileChooser`方法用于开启文件选择。当用户只能选择一次文件可能是因为未正确处理选择回调。解决此问题需确保:1) 实现`WebChromeClient`并覆写`onShowFileChooser`;2) 用户选择文件后调用`ValueCallback.onReceiveValue`传递URI;3) 传递结果后将`ValueCallback`设为`null`以允许再次选择。下面是一个Kotlin示例,展示如何处理文件选择和结果回调。别忘了在Android 6.0+动态请求存储权限,以及在Android 10+处理分区存储。
|
4天前
|
存储 移动开发 Android开发
使用kotlin Jetpack Compose框架开发安卓app, webview中h5如何访问手机存储上传文件
在Kotlin和Jetpack Compose中,集成WebView以支持HTML5页面访问手机存储及上传音频文件涉及关键步骤:1) 添加`READ_EXTERNAL_STORAGE`和`WRITE_EXTERNAL_STORAGE`权限,考虑Android 11的分区存储;2) 配置WebView允许JavaScript和文件访问,启用`javaScriptEnabled`、`allowFileAccess`等设置;3) HTML5页面使用`<input type="file">`让用户选择文件,利用File API;
|
7天前
|
开发者 Kotlin Android开发
Kotlin协程在Android开发中的应用
【7月更文挑战第10天】Kotlin协程简化了Android异步编程,提供轻量级并发。挂起函数让异步代码看起来同步,不阻塞线程,便于管理。在项目中,添加Kotlin和协程依赖,如`kotlinx.coroutines-core`和`kotlinx-coroutines-android`。使用`CoroutineScope`和`launch`处理耗时任务,如网络请求,避免主线程阻塞。挂起函数和调度器控制执行上下文,适应不同任务需求。
|
6天前
|
Java 开发工具 Android开发
探索Android与iOS开发的差异与挑战
【7月更文挑战第11天】在移动应用开发的广阔天地中,Android和iOS两大平台各领风骚。本文将深入探讨这两个平台的开发差异,从编程语言、用户界面设计到开发工具等方面进行比较,并分析开发者面临的挑战。通过对比分析,旨在为开发者提供一个全面的视角,帮助他们更好地选择适合自己项目需求的开发平台。
11 0
|
8天前
|
搜索推荐 Android开发 iOS开发
探索Android与iOS开发的差异:平台特性与用户体验的对比分析
【7月更文挑战第9天】在移动应用开发的浩瀚海洋中,Android和iOS两大操作系统如同两座灯塔,指引着开发者们的航向。本文将深入探讨这两个平台在开发环境、用户界面设计、性能优化以及市场策略上的根本差异。我们将通过比较分析,揭示各自平台的独特优势和潜在挑战,为开发者提供决策支持,同时也为用户体验的提升指明方向。
|
19天前
|
安全 Android开发 iOS开发
探索安卓与iOS开发的差异:平台特性与用户体验的深度对比
在移动应用开发的广阔天地中,安卓和iOS两大平台各占半壁江山。本文旨在通过数据驱动的分析方法,深入探讨这两大操作系统在开发环境、用户界面设计及市场表现等方面的差异。引用最新的行业报告和科研数据,结合技术专家的观点,本文将提供对开发者和市场分析师均有价值的洞见。
|
9天前
|
Java Android开发 iOS开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
【7月更文挑战第8天】在移动应用开发的广阔天地中,Android与iOS两大平台各自占据着半壁江山。本文将深入探讨这两个平台在开发环境、用户界面设计、性能优化以及市场覆盖等方面的根本差异,并分析这些差异如何影响项目的成功。通过比较和分析,旨在为开发者在选择平台时提供更全面的视角,帮助他们根据项目需求和目标市场做出更明智的决策。