基于Titanium的NFC应用不被标签触发
NFC app based on Titanium is not triggered by tag
我对 Appcelerator Titanium 的 ti.nfc module
有疑问。
我添加了模块并遵循了本指南:
http://vizteck.com/test/blog/nfc-data-communication-android-using-titanium
我也关注了Appcelerator的官方文档。
index.js:
var nfc = require("ti.nfc");
var nfcAdapter;
// This creates an NFC adapter associated with the current activity.
// Each activity should have only ONE NFC adapter.
nfcAdapter = nfc.createNfcAdapter({
onNdefDiscovered: handleNDEFDiscovery,
onTagDiscovered: handleTagDiscovery,
onTechDiscovered: handleTechDiscovery
});
function handleNDEFDiscovery(data){
// alert('NDEF DISCOVERED:: ' + data.messages[0].records[0].getPayload());
// Our required payload fits in the first record of the first Ndef msg
var payload = data.messages[0].records[0].getPayload();
// First byte of payload is control byte
// Bits 5 to 0 of the control bytes contain
// length of language code succeeding the control byte
var langCodeLength = payload[0] & 0077;
// Received NFC text data starts after textOffset bytes in payload
var textOffset = langCodeLength + 1;
// Payload contains byte array which needs to be converted to a string
// nfc_text contains the exact text string sent by the sending NFC device
var nfc_text = payload.toString().substring(textOffset);
/* process nfc_text as required by application logic here */
}
function handleTagDiscovery(data){
alert('TAG DISCOVERED:: ' + data.messages[0].records[0].getPayload());
}
function handleTechDiscovery(data){
alert('TECH DISCOVERED:: ' + data.messages[0].records[0].getPayload());
}
// Check for NFC support on device
if (!nfcAdapter.isEnabled()) {
alert('NFC is not enabled on this device!');
}else{
// Tag scans are received by the current activity as new intents. We
// need to pass scan intents to the nfc adapter for processing.
var act = Ti.Android.currentActivity;
act.addEventListener('newintent', function(e) {
nfcAdapter.onNewIntent(e.intent);
});
// Since we want the app to only use NFC while active in the foreground
// We disable and enable foreground dispatch on app pause and resume respectively
act.addEventListener('resume', function(e) {
nfcAdapter.enableForegroundDispatch(dispatchFilter);
});
act.addEventListener('pause', function(e) {
nfcAdapter.disableForegroundDispatch();
});
// The foreground dispatch filter specifies the types of NFC
// messages the app wants to receive and handle. The only entry in our case
// specifies type ‘text/plain’ since we want to send and receive plain text
dispatchFilter = nfc.createNfcForegroundDispatchFilter({
intentFilters: [
{ action: nfc.ACTION_NDEF_DISCOVERED, mimeType: 'text/plain' },
],
techLists: [
[ "android.nfc.tech.NfcF" ],
[ "android.nfc.tech.Ndef" ],
[ "android.nfc.tech.MifareClassic" ],
[ "android.nfc.tech.NfcA" ]
]
});
// This enables foreground dispatch for the first time
nfcAdapter.enableForegroundDispatch(dispatchFilter);
}
Android tiapp.xml:
<android xmlns:android="http://schemas.android.com/apk/res/android">
<manifest>
<uses-permission android:name="android.permission.NFC"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-sdk android:minSdkVersion="14" />
<application>
<activity
android:label="TagViewer" android:theme="@style/Theme.Titanium"
android:configChanges="keyboardHidden|orientation"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"/>
</intent-filter>
</activity>
</application>
</manifest>
</android>
当我启动应用程序时,nfcAdapter 已启用并且我看到了以下 4 个警报:
[INFO] : ALERT: (KrollRuntimeThread) [322,322] org.appcelerator.titanium.proxy.ActivityProxy@1a252dad
[INFO] : ALERT: (KrollRuntimeThread) [0,322] org.appcelerator.kroll.runtime.v8.V8Function@368d58e2
[INFO] : ALERT: (KrollRuntimeThread) [0,322] org.appcelerator.kroll.runtime.v8.V8Function@2c0fe473
[INFO] : ALERT: (KrollRuntimeThread) [1,323] org.appcelerator.kroll.runtime.v8.V8Function@3e517f30
每次我拿着标签(卡片靠在 phone 的背面时,我都会在 appcelerator 的控制台中看到类似这样的内容:
[INFO] : Timeline: Timeline: Activity_idle id: android.os.BinderProxy@30a1f176 time:23801469
[INFO] : Timeline: Timeline: Activity_idle id: android.os.BinderProxy@30a1f176 time:23802093
etc...
我使用了在 Play 商店中找到的另一个应用程序 (NFC Reader)。我的标签包含的数据是:标签 ID(十六进制)、标签 ID(十进制)、ID(反转)。我使用的标签具有以下特征:
标签类型:ISO 15693
技术:NfcV、NdefFormatable
序列号:a2:3b:6b:1e:50:01:04:e0
Output from NFC Reader
问题是什么?为什么它不能很好地解释 tag/card?
我希望你能帮助我。
非常感谢 ;)
鉴于 NFC Reader 的输出,您的标签不包含 NDEF 消息(因为它显示 "NdefFormatable" 而不是 "Ndef" 标签技术)。但是,您注册了 NFC intent 过滤器(在清单中和用于前台调度)以仅对包含文本记录(或 MIME 类型 "text/plain")或 "http://" 的 NFC 标签敏感URL(仅在清单中注册):
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"/>
</intent-filter>
nfc.createNfcForegroundDispatchFilter({
intentFilters: [
{ action: nfc.ACTION_NDEF_DISCOVERED, mimeType: 'text/plain' },
],
...
因此,您的应用程序不会选取标签。
对此你能做什么?
您可以使用应用程序期望的数据类型对标签进行编程(因此,您将文本记录写入标签),或者更改应用程序的 Intent 过滤器以正确发现该标签类型。
对于前台派发,可以用这段代码实现:
dispatchFilter = nfc.createNfcForegroundDispatchFilter({
intentFilters: [
{ action: nfc.ACTION_TECH_DISCOVERED },
],
techLists: [
[ "android.nfc.tech.NfcV" ]
]
});
然后您将在 onTechDiscovered
回调中收到标签发现事件:
function handleTechDiscovery(data) {
// do something
}
然后您可以根据需要处理标签。例如。如果你想读取标签 UID/anti-collision 标识符,你可以从 data
参数中获取 NfcTag
对象:
var tag = data.tag;
并通过查询getId()方法获取UID:
alert('Tag ID: ' + tag.getId());
谢谢迈克尔!
我用你的替换了我的 "dispatchFilter" 并修改了函数 "handleTechDiscovery" 将 "data.messages[0].records[0].getPayload()" 更改为 "data".
现在,当我在 phone 的背面拿着标签卡时,我在 appcelerator 的控制台中看到如下内容:
[INFO]:I/Nfc 模块:android.nfc.action.TECH_DISCOVERED 收到意图但没有消息
[信息]:启用 NFC
[信息]:发现技术:: [对象对象]
我该怎么做才能正确读取 [object Object]?
为什么 "android.nfc.action.TECH_DISCOVERED intent received with no messages" 如果 Tag/card 包含数据?
再次感谢您的回复。
我对 Appcelerator Titanium 的 ti.nfc module
有疑问。
我添加了模块并遵循了本指南:
http://vizteck.com/test/blog/nfc-data-communication-android-using-titanium
我也关注了Appcelerator的官方文档。
index.js:
var nfc = require("ti.nfc");
var nfcAdapter;
// This creates an NFC adapter associated with the current activity.
// Each activity should have only ONE NFC adapter.
nfcAdapter = nfc.createNfcAdapter({
onNdefDiscovered: handleNDEFDiscovery,
onTagDiscovered: handleTagDiscovery,
onTechDiscovered: handleTechDiscovery
});
function handleNDEFDiscovery(data){
// alert('NDEF DISCOVERED:: ' + data.messages[0].records[0].getPayload());
// Our required payload fits in the first record of the first Ndef msg
var payload = data.messages[0].records[0].getPayload();
// First byte of payload is control byte
// Bits 5 to 0 of the control bytes contain
// length of language code succeeding the control byte
var langCodeLength = payload[0] & 0077;
// Received NFC text data starts after textOffset bytes in payload
var textOffset = langCodeLength + 1;
// Payload contains byte array which needs to be converted to a string
// nfc_text contains the exact text string sent by the sending NFC device
var nfc_text = payload.toString().substring(textOffset);
/* process nfc_text as required by application logic here */
}
function handleTagDiscovery(data){
alert('TAG DISCOVERED:: ' + data.messages[0].records[0].getPayload());
}
function handleTechDiscovery(data){
alert('TECH DISCOVERED:: ' + data.messages[0].records[0].getPayload());
}
// Check for NFC support on device
if (!nfcAdapter.isEnabled()) {
alert('NFC is not enabled on this device!');
}else{
// Tag scans are received by the current activity as new intents. We
// need to pass scan intents to the nfc adapter for processing.
var act = Ti.Android.currentActivity;
act.addEventListener('newintent', function(e) {
nfcAdapter.onNewIntent(e.intent);
});
// Since we want the app to only use NFC while active in the foreground
// We disable and enable foreground dispatch on app pause and resume respectively
act.addEventListener('resume', function(e) {
nfcAdapter.enableForegroundDispatch(dispatchFilter);
});
act.addEventListener('pause', function(e) {
nfcAdapter.disableForegroundDispatch();
});
// The foreground dispatch filter specifies the types of NFC
// messages the app wants to receive and handle. The only entry in our case
// specifies type ‘text/plain’ since we want to send and receive plain text
dispatchFilter = nfc.createNfcForegroundDispatchFilter({
intentFilters: [
{ action: nfc.ACTION_NDEF_DISCOVERED, mimeType: 'text/plain' },
],
techLists: [
[ "android.nfc.tech.NfcF" ],
[ "android.nfc.tech.Ndef" ],
[ "android.nfc.tech.MifareClassic" ],
[ "android.nfc.tech.NfcA" ]
]
});
// This enables foreground dispatch for the first time
nfcAdapter.enableForegroundDispatch(dispatchFilter);
}
Android tiapp.xml:
<android xmlns:android="http://schemas.android.com/apk/res/android">
<manifest>
<uses-permission android:name="android.permission.NFC"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-sdk android:minSdkVersion="14" />
<application>
<activity
android:label="TagViewer" android:theme="@style/Theme.Titanium"
android:configChanges="keyboardHidden|orientation"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"/>
</intent-filter>
</activity>
</application>
</manifest>
</android>
当我启动应用程序时,nfcAdapter 已启用并且我看到了以下 4 个警报:
[INFO] : ALERT: (KrollRuntimeThread) [322,322] org.appcelerator.titanium.proxy.ActivityProxy@1a252dad
[INFO] : ALERT: (KrollRuntimeThread) [0,322] org.appcelerator.kroll.runtime.v8.V8Function@368d58e2
[INFO] : ALERT: (KrollRuntimeThread) [0,322] org.appcelerator.kroll.runtime.v8.V8Function@2c0fe473
[INFO] : ALERT: (KrollRuntimeThread) [1,323] org.appcelerator.kroll.runtime.v8.V8Function@3e517f30
每次我拿着标签(卡片靠在 phone 的背面时,我都会在 appcelerator 的控制台中看到类似这样的内容:
[INFO] : Timeline: Timeline: Activity_idle id: android.os.BinderProxy@30a1f176 time:23801469
[INFO] : Timeline: Timeline: Activity_idle id: android.os.BinderProxy@30a1f176 time:23802093
etc...
我使用了在 Play 商店中找到的另一个应用程序 (NFC Reader)。我的标签包含的数据是:标签 ID(十六进制)、标签 ID(十进制)、ID(反转)。我使用的标签具有以下特征:
标签类型:ISO 15693
技术:NfcV、NdefFormatable
序列号:a2:3b:6b:1e:50:01:04:e0
Output from NFC Reader 问题是什么?为什么它不能很好地解释 tag/card? 我希望你能帮助我。
非常感谢 ;)
鉴于 NFC Reader 的输出,您的标签不包含 NDEF 消息(因为它显示 "NdefFormatable" 而不是 "Ndef" 标签技术)。但是,您注册了 NFC intent 过滤器(在清单中和用于前台调度)以仅对包含文本记录(或 MIME 类型 "text/plain")或 "http://" 的 NFC 标签敏感URL(仅在清单中注册):
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"/>
</intent-filter>
nfc.createNfcForegroundDispatchFilter({
intentFilters: [
{ action: nfc.ACTION_NDEF_DISCOVERED, mimeType: 'text/plain' },
],
...
因此,您的应用程序不会选取标签。
对此你能做什么?
您可以使用应用程序期望的数据类型对标签进行编程(因此,您将文本记录写入标签),或者更改应用程序的 Intent 过滤器以正确发现该标签类型。
对于前台派发,可以用这段代码实现:
dispatchFilter = nfc.createNfcForegroundDispatchFilter({
intentFilters: [
{ action: nfc.ACTION_TECH_DISCOVERED },
],
techLists: [
[ "android.nfc.tech.NfcV" ]
]
});
然后您将在 onTechDiscovered
回调中收到标签发现事件:
function handleTechDiscovery(data) {
// do something
}
然后您可以根据需要处理标签。例如。如果你想读取标签 UID/anti-collision 标识符,你可以从 data
参数中获取 NfcTag
对象:
var tag = data.tag;
并通过查询getId()方法获取UID:
alert('Tag ID: ' + tag.getId());
谢谢迈克尔! 我用你的替换了我的 "dispatchFilter" 并修改了函数 "handleTechDiscovery" 将 "data.messages[0].records[0].getPayload()" 更改为 "data".
现在,当我在 phone 的背面拿着标签卡时,我在 appcelerator 的控制台中看到如下内容:
[INFO]:I/Nfc 模块:android.nfc.action.TECH_DISCOVERED 收到意图但没有消息
[信息]:启用 NFC
[信息]:发现技术:: [对象对象]
我该怎么做才能正确读取 [object Object]?
为什么 "android.nfc.action.TECH_DISCOVERED intent received with no messages" 如果 Tag/card 包含数据?
再次感谢您的回复。