热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

uniapp使用nfc功能及详解

公司使用uniapp在android手机端要增加一个nfc识别的功能。在此记录一下实现的过程。资料查找我的代码逻辑主要来源于找到的这篇文章:uniapp-安卓N

公司使用uniapp在android手机端要增加一个nfc识别的功能。在此记录一下实现的过程。


资料查找

我的代码逻辑主要来源于找到的这篇文章:

uniapp-安卓NFC读取 - 我要找到我的全世界 - 博客园

 文章内附有代码,为防止文章失效代码消失,在这篇文章里面也记录一下。

var NfcAdapter;
var NdefRecord;
var NdefMessage;
var _getCardNo;export default {initNFC() {if (uni.getSystemInfoSync().platform == 'android') {listenNFCStatus()}},readNFC(callback) {if (uni.getSystemInfoSync().platform == 'android') {readData(callback);}},closeNFC() {if (uni.getSystemInfoSync().platform == 'android') {closeReadAndWrite();}}
}function listenNFCStatus() {try {var main = plus.android.runtimeMainActivity();var Intent = plus.android.importClass('android.content.Intent');var Activity = plus.android.importClass('android.app.Activity');var PendingIntent = plus.android.importClass('android.app.PendingIntent');var IntentFilter = plus.android.importClass('android.content.IntentFilter');NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');var nfcAdapter = NfcAdapter.getDefaultAdapter(main);if (nfcAdapter == null) {uni.showToast({title: '设备不支持NFC!',icon: 'none'})return;}if (!nfcAdapter.isEnabled()) {uni.showToast({title: '请在系统设置中先启用NFC功能!',icon: 'none'});return;}var intent = new Intent(main, main.getClass());intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);var pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);var ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");ndef.addDataType("*/*");var intentFiltersArray = [ndef];var techListsArray = [["android.nfc.tech.IsoDep"],["android.nfc.tech.NfcA"],["android.nfc.tech.NfcB"],["android.nfc.tech.NfcF"],["android.nfc.tech.Nfcf"],["android.nfc.tech.NfcV"],["android.nfc.tech.NdefFormatable"],["android.nfc.tech.MifareClassic"],["android.nfc.tech.MifareUltralight"]];plus.globalEvent.addEventListener("newintent",function() {setTimeout(handle_nfc_data1, 1000);}, false);plus.globalEvent.addEventListener("pause", function(e) {if (nfcAdapter) {nfcAdapter.disableForegroundDispatch(main);}}, false);plus.globalEvent.addEventListener("resume", function(e) {if (nfcAdapter) {//console.log('resume'); nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);}}, false);nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);} catch (e) {console.error(e);}
}function handle_nfc_data1() {NdefRecord = plus.android.importClass("android.nfc.NdefRecord");NdefMessage = plus.android.importClass("android.nfc.NdefMessage");var main = plus.android.runtimeMainActivity();var intent = main.getIntent();//console.log("action type:" + intent.getAction()); if ("android.nfc.action.TECH_DISCOVERED" == intent.getAction()) {if (readyWriteData) {//__write(intent);readyWriteData = false;} else if (readyRead) {__read(intent);readyRead = false;}}
}function showToast(msg) {plus.nativeUI.toast(msg);
}// function __write(intent) {
// try {
// waiting.setTitle('请勿移开标签\n正在写入...');
// var text = document.getElementById('text').value;
// console.log("text=" + text);
// var textBytes = plus.android.invoke(text, "getBytes");
// var textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
// plus.android.invoke("text/plain", "getBytes"), plus.android.invoke("", "getBytes"), textBytes);
// var message = new NdefMessage([textRecord]);
// var Ndef = plus.android.importClass('android.nfc.tech.Ndef');
// var NdefFormatable = plus.android.importClass('android.nfc.tech.NdefFormatable');
// var tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
// var ndef = Ndef.get(tag);
// if (ndef != null) {
// var size = message.toByteArray().length;
// console.log("size=" + size);
// ndef.connect();
// if (!ndef.isWritable()) {
// showToast("tag不允许写入");
// waiting.close();
// return;
// }
// if (ndef.getMaxSize() // showToast("文件大小超出容量");
// waiting.close();
// return;
// }// ndef.writeNdefMessage(message);
// waiting.close();
// showToast("写入数据成功.");
// return;
// } else {
// var format = NdefFormatable.get(tag);
// if (format != null) {
// try {
// format.connect();
// format.format(message);
// showToast("格式化tag并且写入message");
// waiting.close();
// return;
// } catch (e) {
// showToast("格式化tag失败.");
// waiting.close();
// return;
// }
// } else {
// showToast("Tag不支持NDEF");
// waiting.close();
// return;
// }
// }
// } catch (e) {
// console.log("error=" + e);
// waiting.close();
// alert('写入失败');
// }// }function __read(intent) {try {var cOntent= "";waiting.setTitle('请勿移开标签\n正在读取数据...');var tag = plus.android.importClass("android.nfc.Tag");tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);var bytesId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);waiting.close();var tagid = bytesToHexString(tag.getId())if (typeof _getCardNo === 'function') {_getCardNo(tagid);}} catch (e) {uni.showToast({title: e,icon: 'none'});}
}function bytesToHexString(inarray) {var i, j, x;var hex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A","B", "C", "D", "E", "F"];var out = "";for (j = 0; j > 4) & 0x0f;out += hex[i];i = x & 0x0f;out += hex[i];}return out;
}function reverseTwo(str) {var str1 = "";for (var i = 1; i <= str.length; i++) {str1 += str[i - 1];if (i % 2 == 0) {if (i == str.length) {break;}str1 += ":";}}var str2 = "";for (var i = str1.split(":").length - 1; i >= 0; i--) {str2 += str1.split(":")[i];}return str2;
}if (uni.getSystemInfoSync().platform == &#39;android&#39;) {//plus.globalEvent.addEventListener(&#39;plusready&#39;, listenNFCStatus, false);
}var waiting;
var readyWriteData = false;
var readyRead = false;function writeData() {var textEle = plus.globalEvent.getElementById(&#39;text&#39;);if (!textEle.value) {uni.showToast({title: &#39;请输入要写入的内容!&#39;,icon: &#39;none&#39;});return;}readyWriteData = true;waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");
}function readData(getCardNo) {readyRead = true;_getCardNo = getCardNowaiting = plus.nativeUI.showWaiting("请将NFC标签靠近!", {modal: false});
}function closeReadAndWrite() {readyWriteData = false;readyRead = false;if (waiting) {waiting.close();}
}

代码内部是存在着写入功能的,被注释掉了,单单使用读取功能。

读取到的NFC类型有比较多种,这是我找到的比较好的一篇解释,大部分文章都有提到的4种类型。

搞懂Nfc刷卡看这篇就够了 - 知乎

文章里面附带了NFC相关的android官方文档,因为解析代码逻辑需要用到,我就把官网的链接也贴在下面。

NFC 基础知识  |  Android 开发者  |  Android Developers  

NfcAdapter  |  Android Developers 


代码使用:

 第一步:新建一个js文件,进去。

第二步:在涉及到使用nfc识别的页面,引入这个js文件。主要三个方法:初始化,关闭识别,识别成功回调方法

onload里面执行初始化initNFC,在离开页面的时候closeNFC(博主本人放在unload),点击某个按钮BUTTON的时候开始识别readNFC。

开启识别的时候会一直等待识别,建议添加一个setTimeout定时器,在固定时间调用closeNFC关闭识别,点击BUTTON的时候先清除再调用,识别成功的回调方法里面也要清理这个定时器。


代码逻辑个人理解:

uniapp需要在manifest.json中开启手机的NFC识别权限。

代码中也添加了判断手机是否开启了NFC识别,NFC的识别功能是调用了手机自身的一个intent,然后跳转回来。

 NfcAdapter适配器里面包含了许多的识别到的信息,这些信息都是要经过序列化才能使用的,如果不确定该调用哪个序列化方法,或者想知道还有哪些方法,可以去官方文档 里面找。

代码中就有使用到这两个值。

 从启动开始讲起,调用手机自身的nfc识别,就意味着当前的intent跳转到另外一个intent,读取到数据之后就跳转回来。

var main = plus.android.runtimeMainActivity();var Intent = plus.android.importClass(&#39;android.content.Intent&#39;);var Activity = plus.android.importClass(&#39;android.app.Activity&#39;);var PendingIntent = plus.android.importClass(&#39;android.app.PendingIntent&#39;);var IntentFilter = plus.android.importClass(&#39;android.content.IntentFilter&#39;);NfcAdapter = plus.android.importClass(&#39;android.nfc.NfcAdapter&#39;);var nfcAdapter = NfcAdapter.getDefaultAdapter(main);。。。。。。。。。。。。。。。。。。。。。。。。。。。。。var intent = new Intent(main, main.getClass());intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);var pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);var ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");ndef.addDataType("*/*");var intentFiltersArray = [ndef];var techListsArray = [["android.nfc.tech.IsoDep"],["android.nfc.tech.NfcA"],["android.nfc.tech.NfcB"],["android.nfc.tech.NfcF"],["android.nfc.tech.Nfcf"],["android.nfc.tech.NfcV"],["android.nfc.tech.NdefFormatable"],["android.nfc.tech.MifareClassic"],["android.nfc.tech.MifareUltralight"]];nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);

这些就是一些跳转的设置,下半部分设置了跳转的启动方式为Intent.FLAG_ACTIVITY_SINGLE_TOP,并且设置了intent过滤器。

下一步就是监听这些跳转,并处理放回的数据。于是在代码中可以看到下面的这些监听方法。

plus.globalEvent.addEventListener("newintent",function() {setTimeout(handle_nfc_data1, 1000);}, false);plus.globalEvent.addEventListener("pause", function(e) {if (nfcAdapter) {nfcAdapter.disableForegroundDispatch(main);}}, false);plus.globalEvent.addEventListener("resume", function(e) {if (nfcAdapter) {//console.log(&#39;resume&#39;); nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);}}, false);

主要是“newintent"的监听,里面实现了主要的逻辑。

手机识别到nfc跳转回到应用的时候,intent会携带返回的信息。进行判断是否是"android.nfc.action.TECH_DISCOVERED"。意味着识别到了信息。

__read方法就是主要的处理信息的内容了,也是最重要的。

intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);将数据进行序列化。应用与应用直接传递数据,都要进行序列化和反序列化处理的。

bytesToHexString将数据转换。


推荐阅读
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 第四章高阶函数(参数传递、高阶函数、lambda表达式)(python进阶)的讲解和应用
    本文主要讲解了第四章高阶函数(参数传递、高阶函数、lambda表达式)的相关知识,包括函数参数传递机制和赋值机制、引用传递的概念和应用、默认参数的定义和使用等内容。同时介绍了高阶函数和lambda表达式的概念,并给出了一些实例代码进行演示。对于想要进一步提升python编程能力的读者来说,本文将是一个不错的学习资料。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • 用Vue实现的Demo商品管理效果图及实现代码
    本文介绍了一个使用Vue实现的Demo商品管理的效果图及实现代码。 ... [详细]
  • express工程中的json调用方法
    本文介绍了在express工程中如何调用json数据,包括建立app.js文件、创建数据接口以及获取全部数据和typeid为1的数据的方法。 ... [详细]
  • php缓存ri,浅析ThinkPHP缓存之快速缓存(F方法)和动态缓存(S方法)(日常整理)
    thinkPHP的F方法只能用于缓存简单数据类型,不支持有效期和缓存对象。S()缓存方法支持有效期,又称动态缓存方法。本文是小编日常整理有关thinkp ... [详细]
  • Python中的PyInputPlus模块原文:https ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文讨论了Kotlin中扩展函数的一些惯用用法以及其合理性。作者认为在某些情况下,定义扩展函数没有意义,但官方的编码约定支持这种方式。文章还介绍了在类之外定义扩展函数的具体用法,并讨论了避免使用扩展函数的边缘情况。作者提出了对于扩展函数的合理性的质疑,并给出了自己的反驳。最后,文章强调了在编写Kotlin代码时可以自由地使用扩展函数的重要性。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记
    本文介绍了大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记,包括outputFormat接口实现类、自定义outputFormat步骤和案例。案例中将包含nty的日志输出到nty.log文件,其他日志输出到other.log文件。同时提供了一些相关网址供参考。 ... [详细]
  • 本文讨论了在shiro java配置中加入Shiro listener后启动失败的问题。作者引入了一系列jar包,并在web.xml中配置了相关内容,但启动后却无法正常运行。文章提供了具体引入的jar包和web.xml的配置内容,并指出可能的错误原因。该问题可能与jar包版本不兼容、web.xml配置错误等有关。 ... [详细]
  • 本文介绍了如何在Jquery中通过元素的样式值获取元素,并将其赋值给一个变量。提供了5种解决方案供参考。 ... [详细]
  • 花瓣|目标值_Compose 动画边学边做夏日彩虹
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Compose动画边学边做-夏日彩虹相关的知识,希望对你有一定的参考价值。引言Comp ... [详细]
author-avatar
mobiledu2502931467
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有