Android获取NFC标签和NFC十进制16进制ID
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android获取NFC标签和NFC十进制16进制ID相关的知识,希望对你有一定的参考价值。
参考技术A <uses-featureandroid:name="android.hardware.nfc"
android:required="true"/>
<uses-permission android:name="android.permission.NFC"/>
```
class NfcActivity :BaseActivity()
private lateinit var imgBack:ImageView
private lateinit var mNfcAdapter:NfcAdapter
private lateinit var mPendingIntent:PendingIntent
//nfc标签信息
private lateinit var tvNfcTag:TextView
//nfc十进制ID
private lateinit var tvNfcD:TextView
//nfc16进制ID
private lateinit var tvNfcH:TextView
/**
* 启动Activity
*/
override fun onStart()
super.onStart()
mNfcAdapter =NfcAdapter.getDefaultAdapter(this)
//一旦截获NFC消息,就会通过PendingIntent调用窗口
mPendingIntent =PendingIntent.getActivity(this,0,Intent(this,javaClass),0)
override fun getLayoutId():Int
return R.layout.activity_nfc
override fun eventBus(event:Any?)
override fun onCreate(savedInstanceState:Bundle?)
super.onCreate(savedInstanceState)
imgBack =findViewById(R.id.img_nfc_back)
tvNfcD =findViewById(R.id.tv_nfc_d)
tvNfcH =findViewById(R.id.tv_nfc_h)
tvNfcTag =findViewById(R.id.tv_nfc_tag)
imgBack.setOnClickListener finish()
override fun onResume()
super.onResume()
//设置处理优于所有其他NFC的处理
mNfcAdapter.enableForegroundDispatch(
this,
mPendingIntent,
null,
null
)
override fun onPause()
super.onPause()
//恢复默认状态
mNfcAdapter.disableForegroundDispatch(this)
override fun onNewIntent(intent:Intent?)
super.onNewIntent(intent)
// readFromTag(intent);
readNfcTag(intent!!)
/**
* 读取NFC标签文本数据
*/
private fun readNfcTag(intent:Intent)
val tag:Tag? =intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
if (tag !=null)
val cardNo =flipHexStr(ByteArrayToHexString(tag.id)).toLong(16)
tvNfcD.text = cardNo.toString()
tvNfcH.text =ByteArrayToHexString(tag.id)
if (NfcAdapter.ACTION_NDEF_DISCOVERED ==intent.action)
val rawMessages =intent.getParcelableArrayExtra(
NfcAdapter.EXTRA_NDEF_MESSAGES
)
var msgs:Array? =null
var contentSize =0
if (rawMessages !=null)
msgs =arrayOfNulls(rawMessages.size)
for (iin rawMessages.indices)
msgs[i] = rawMessages[i]as NdefMessage
contentSize +=msgs[i]!!.toByteArray().size
try
if (null !=msgs)
val record =msgs[0]!!.records[0]
val textRecord:String? =
NfcUtil.parseTextRecord(record)
Log.e("nfcTag-->","" + textRecord)
tvNfcTag.text = textRecord
catch (e:Exception)
e.printStackTrace()
Log.e("nfcError-->","" + e)
```
获取标签及其ID的工具类
import android.nfc.NdefRecord;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class NfcUtil
/**
* 解析NDEF文本数据,从第三个字节开始,后面的文本数据
* @param ndefRecord
* @return
*/
public static String parseTextRecord(NdefRecord ndefRecord)
/**
* 判断数据是否为NDEF格式
* 判断TNF
*/
if (ndefRecord.getTnf() !=NdefRecord.TNF_WELL_KNOWN)
return null;
//判断可变的长度的类型
if (!Arrays.equals(ndefRecord.getType(),NdefRecord.RTD_TEXT))
return null;
try
//获得字节数组,然后进行分析
byte[] payload =ndefRecord.getPayload();
//下面开始NDEF文本数据第一个字节,状态字节
//判断文本是基于UTF-8还是UTF-16的,取第一个字节"位与"上16进制的80,16进制的80也就是最高位是1,
//其他位都是0,所以进行"位与"运算后就会保留最高位
String textEncoding = ((payload[0] &0x80) ==0) ?"UTF-8" :"UTF-16";
//3f最高两位是0,第六位是1,所以进行"位与"运算后获得第六位
int languageCodeLength = payload[0] &0x3f;
//下面开始NDEF文本数据第二个字节,语言编码
//获得语言编码
String languageCode =new String(payload,1, languageCodeLength,StandardCharsets.US_ASCII);
//下面开始NDEF文本数据后面的字节,解析出文本
String textRecord =new String(payload, languageCodeLength +1,
payload.length - languageCodeLength -1, textEncoding);
return textRecord;
catch (Exception e)
throw new IllegalArgumentException();
// 16转10进制
public static String flipHexStr(String s)
StringBuilder result =new StringBuilder();
for (int i =0; i <=s.length() -2; i = i +2)
result.append(new StringBuilder(s.substring(i, i +2)).reverse());
return result.reverse().toString();
public static String ByteArrayToHexString(byte[]inarray)
int i, j, in;
String[] hex = "0","1","2","3","4","5","6","7","8","9","A",
"B","C","D","E","F";
StringBuilder out =new StringBuilder();
for (j =0; j
in = (int)inarray[j] &0xff;
i = (in >>4) &0x0f;
out.append(hex[i]);
i = in &0x0f;
out.append(hex[i]);
return out.toString();
如何通过 NFC 标签启动我的应用程序?
【中文标题】如何通过 NFC 标签启动我的应用程序?【英文标题】:How to launch my app via NFC tag? 【发布时间】:2016-03-17 06:20:49 【问题描述】:我目前正在将应用移植到 UWP。该应用程序有一个带有“写入 NFC”按钮的页面。用户点击后,它会等待 NFC 标签并写入LaunchApp:WriteTag
二进制消息。
在 WP8.1 下运行良好,在 Windows 10 UWP 下根本无法运行:
var proximityDevice = Windows.Networking.Proximity.ProximityDevice.GetDefault();
if (proximityDevice != null)
var launchArgs = "user=default";
var appId = "App";
var appName = Windows.ApplicationModel.Package.Current.Id.FamilyName + "!" + appId;
var launchAppMessage = launchArgs + "\tWindows\t" + appName;
var dataWriter = new Windows.Storage.Streams.DataWriter();
dataWriter.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf16LE;
dataWriter.WriteString(launchAppMessage);
var launchAppPubId = proximityDevice.PublishBinaryMessage("LaunchApp:WriteTag", dataWriter.DetachBuffer());
不幸的是,这不起作用。 NFC 功能已启用且 WP8.1 应用程序可在同一部手机上运行,因此这应该不是问题。
我已经尝试了多种格式,因为问题似乎是 launchAppMessage
,我没有找到 UWP 文档。有一篇Windows 8+MSDN 文章,描述了字符串的格式:
myArgs\tWindows\tAppFamilyName!App
我尝试了什么:
myArgs
足够短 - 应该不是问题。
Windows
或 WindowsPhone
没有任何区别。两者都不起作用。
AppFamilyName
是我的应用清单中的正确应用系列名称。该应用与商店相关联,看起来这也不应该是问题。
App
是我的应用清单中 <Application id="App" ... />
的内容。尝试 MyAppNamespace.App
效果不佳,调用 CurrentApp.AppId
(在 WinRT 应用程序中使用)会引发异常。
“不工作”是指它写入标签,但 Windows 10 根本无法识别标签。
我发现的另一件事是,对于myArgs\tWindows\tAppFamilyName!App
,应用程序抛出以下异常 - 没有任何进一步的细节:
System.ExecutionEngineException was unhandled
Message: An unhandled exception of type 'System.ExecutionEngineException' occurred in Unknown Module.
我真的希望有人知道如何解决这个问题。不幸的是,目前还没有 UWP 示例,文档仍然是旧的......:/
PS:将自定义协议与 WindowsUri:WriteTag
一起使用可以正常工作,但我希望只使用 NFC 标签打开我的应用程序。此外,确认对话框看起来像“您要打开与 mycustomprotocol 关联的应用程序吗?” - 这看起来不是很用户友好。所以这对我来说不是真正的解决方案,更多的是我不想使用的解决方法。
【问题讨论】:
【参考方案1】:Windows 10 移动版 UWP
如果您只针对 Windows 10 移动版,8.1 方式仍然有效,前提是您获得了正确的 App ID。可以通过以下方式检索:
Windows.ApplicationModel.Store.CurrentApp.AppId
但是,这仅在通过商店安装应用时有效,因为 ID 是在商店关联/发布期间分配的。在开发人员部署的构建中,API 将因“HRESULT 异常:0x803F6107”而崩溃。
然后,生成的 LaunchApp 记录需要平台“WindowsPhone”和该应用 ID。以下代码通过开源 NFC / NDEF 库 (https://github.com/andijakl/ndef-nfc) 创建一个 LaunchApp 标签,适用于 Windows 10 移动版 - 用于编写标签和启动应用程序。再次 - 鉴于它已通过商店发布和安装:
var record = new NdefLaunchAppRecord Arguments = "Hello World" ;
var appId = Windows.ApplicationModel.Store.CurrentApp.AppId; // Note: crashes when app is not installed through app store!
record.AddPlatformAppId("WindowsPhone", appId);
var message = new NdefMessage record ;
proximityDevice.PublishBinaryMessage("NDEF:WriteTag", msgArray.AsBuffer(), MessageWrittenHandler);
Windows 10 电脑
不幸的是,PC 的情况有所不同。上面的方法在那里不起作用,Windows 8.1 的记录方法也不起作用。
到目前为止,我能做到的最接近的方法是让 Windows 10 识别 LaunchApp 标签并在正确的页面上打开商店。但是Windows/商店没有意识到该应用程序已经安装,因此没有打开它。
这是代码,再次使用 NFC / NDEF 库:
var record = new NdefLaunchAppRecord Arguments = "Hello World" ;
var familyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;
var appId = Windows.ApplicationModel.Store.CurrentApp.AppId; // Note: crashes when app is not installed through app store!
record.AddPlatformAppId("Windows", "" + familyName + "!" + appId + "");
var message = new NdefMessage record ;
proximityDevice.PublishBinaryMessage("NDEF:WriteTag", msgArray.AsBuffer(), MessageWrittenHandler);
当然,如果您有足够的可写内存,您也可以将两个平台 ID 组合到一个 NFC 标签中,因为这些应用 ID 很大。
【讨论】:
谢谢安德烈亚斯!我已经在您的代码中看到了我的 SO 问题的链接,所以感谢您的详细回答:) 我认为这里真正的问题是如果应用程序没有通过商店安装,则会引发异常,所以让我们看看 MS 是否可以这样做someone from the NFC team of MSFT answered in my MSDN forum thread about this problem。 很高兴看到这一点,感谢您的链接!我还在跟进我们的 MVP 邮件列表 - 当我们从 MS 得到明确答复时,让我们保持更新 SO 帖子!【参考方案2】:这是一种方法:
-
注册后台任务并使用 NFC 触发器
注册您的应用以激活 uri。
将后台任务编程为在使用 NFC 标签点击时激活,然后启动应用 URI 方案
//设置推荐应用
var options = new Windows.System.LauncherOptions();
options.PreferredApplicationPackageFamilyName= "Contoso.URIApp_8wknc82po1e";
options.PreferredApplicationDisplayName = "Contoso URI Ap";
// Launch the URI and pass in the recommended app
// in case the user has no apps installed to handle the URI
var success = await Windows.System.Launcher.LaunchUriAsync(uriContoso, options);
【讨论】:
请问“NFC 触发器”应该是什么?我找不到任何IBackgroundTaskTrigger
会在找到 NFC 标签时触发?
您同时回答了其他几个问题,我猜您在这里也不知道您的“答案”......太糟糕了。 :/ 我希望其他人可以提供帮助。
我试图找到解决方案。我遇到了 sensordatathreshold 触发器的这个触发器,但不幸的是我没有启用 NFC 的 WINdows 设备来测试或实验这个..所以我现在无法进一步帮助你..有一个艰难的方法,但我不值得痛苦..它正在构建自定义触发器..我认为普通开发人员无法访问它..如果你想采取 lokk 去msdn.microsoft.com/en-us/library/windows/hardware/…
也许您可以尝试研究低级 api 并获取 dll 并围绕它创建一个 c# 包装器并将其用作触发器.. 只是理论.. 未经测试..【参考方案3】:
如果您有一个 WP8.1 应用程序并在 Windows Phone 10 上运行此应用程序,并且想要在您的手机上写入 NFC 标签,您必须检索AppId
。这是通过打开Windows Dev Center 打开相应的应用程序,单击App Management
,然后单击App identity
来完成的。然后在URL for Windows Phone 8.1 and earlier
点下复制GUID
并替换Windows.ApplicationModel.Store.CurrentApp.AppId
【讨论】:
以上是关于Android获取NFC标签和NFC十进制16进制ID的主要内容,如果未能解决你的问题,请参考以下文章
Broadcom NFC 堆栈对基于二进制读取的存在检查的预期响应