吃辣条的大妖怪
吃辣条的大妖怪
  • 发布:2019-03-13 17:19
  • 更新:2024-11-16 17:51
  • 阅读:23925

uniapp 实现 NFC标签读取 和 写入

分类:uni-app

参考文章链接:
NFC读取卡片ID
磊子文章

uniapp 开发,找了很久没找到相关的NFC读写的代码;解决相关问题也用了些时间,希望文章有用;

最开始没有找到uniapp中的,NFC贴上手机后对应的响应事件;
有发帖提问怎么解决;
链接:uniapp怎么监听h5+的event事件http://ask.dcloud.net.cn/question/66505
在uniapp中:封装在 onShow 和onHide

代码基本同之前磊子提供的一样,全部放在methods 里面;
listenNFCStatus()
在onLoad的时候调用;
读写是在onShow的时候调用;

下面这段

nfcAdapter.disableForegroundDispatch(main);

打算放在onHide但是出现三方脚本错误的报错;
没法解决;就没放 = =;

但是单独的读没有任何影响,这是我写了读出数据会有个消息弹框,响应NFC并读取数据的方法是在onShow里面的;

手机息屏重新打开,扔会出发onShow,自动又调用了一次读取数据,所以遇到bug就是NFC的响应事件和手机息屏事件冲突;

暂时加了个计数器 count ,第一次进入的时候不调用读取;并且在hide和show加了时间戳,通过onHide 和 onShow响应的时间差,来判断是否触发读取事件;

如果有小伙伴知道怎么弄求分享

uniapp支持 plus.globalEvent.addEventListener('newintent', e =>{}); 后,之前因为懒没有改,后来出现bug了,就抽空改了下,突然想起来修改这个;

我是加载onReady内的;

var that = this ;  
    plus.globalEvent.addEventListener('newintent', e =>{  
              console.log("newIntent");  

                  that.readData();  
            });

将之前在onShow 和onHide 全部删掉。当时设置的onShow 和 onHide 的时间差是400,这样搞会出问题,当数据或者长时间放置等其他时候,会造成无法调起nfc这个。还是需要用安卓的newIntent。

需要放在 应用层级,app.vue 下。后期写个完整的贴

附上整体js代码,部分自己的function已删除;

    var NfcAdapter;  
    var NdefRecord;  
    var NdefMessage;  
    var waiting  
    var readyRead = false;  
    var nfcAdapter,main , pendingIntent,intentFiltersArray,techListsArray, IntentFilter  

    export default {  
        data() {  
            return {  
                currentNFCInfo: [], //NFC 读取消息;  
                bannerShow: false,  
                remark:"",  
                message: "",  
                count:0,  
                timestampHide:"",  
                timestampShow:""  
            };  
        },  
        methods: {  
            listenNFCStatus() {  
                try {  
                    console.log('Init NFC...');  
                    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');  
                    IntentFilter = plus.android.importClass('android.content.IntentFilter');  
                    NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');  
                    nfcAdapter = NfcAdapter.getDefaultAdapter(main);  
                    var intent = new Intent(main, main.getClass());  
                    intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);  
                    pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);  
                    var ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");  
                    ndef.addDataType("*/*");  
                    intentFiltersArray = [ndef];  
                    techListsArray = [  
                        ["android.nfc.tech.IsoDep"],  
                        ["android.nfc.tech.NfcA"],  
                        ["android.nfc.tech.NfcB"],  
                        ["android.nfc.tech.NfcF"],  
                        ["android.nfc.tech.Ndef"],  
                        ["android.nfc.tech.NfcV"],  
                        ["android.nfc.tech.NdefFormatable"],  
                        ["android.nfc.tech.MifareClassic"],  
                        ["android.nfc.tech.MifareUltralight"]  
                    ];  

                } catch (e) {  
                    console.error(e);  
                }  
            },  
            handle_nfc_data() {  

                NdefRecord = plus.android.importClass("android.nfc.NdefRecord");  
                NdefMessage = plus.android.importClass("android.nfc.NdefMessage");  
                // main = plus.android.runtimeMainActivity();  
                var intent = main.getIntent();  

                console.log("action type:" + intent.getAction());  
                if ("android.nfc.action.TECH_DISCOVERED" == intent.getAction()) {  
                    if (readyRead) {  
                        this.__read(intent);  
                        readyRead = false;  
                    }  
                } else {  
                    // waiting.close();  
                    console.log("nfc读取失败")  
                }  
            },  
            __read(intent) {  
                try {  
                    var content = "";  
                    waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");  
                    waiting.setTitle('请勿移开标签\n正在读取数据...');  
                    var tag = plus.android.importClass("android.nfc.Tag");  
                    waiting.close();  
                    var Parcelable = plus.android.importClass("android.os.Parcelable");  
                    // var rawmsgs = intent.getParcelableArrayExtra("android.nfc.extra.NDEF_MESSAGES");  
                    var rawmsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);  

                    if (rawmsgs != null && rawmsgs.length > 0) {  
                        waiting.close();  
                        // console.log(JSON.stringify(rawmsgs[0]));  
                        var records = rawmsgs[0].getRecords();  
                        var result = records[0].getPayload();  
                        // console.log(result)  
                        if (result != null) {  
                            var s = plus.android.newObject("java.lang.String", result);  
                            console.log(s);  
                            this.currentNFCInfo = s;  
                        } else {  
                            this.currentNFCInfo = "";  
                        }  
                    } else {  
                        console.log("NFC获取失败");  
                        uni.showToast({  
                            title: "NFC获取失败.",  
                            icon: "none"  
                        });  
                    }  

                } catch (e) {  
                    console.log(e);  
                    console.log("NFC获取失败,丢出异常");  
                    waiting.close();  
                    uni.showToast({  
                        title: "NFC获取失败,丢出异常.",  
                        icon: "none"  
                    });  
                    //TODO handle the exception  
                }  
            },  
            readData() {  
                readyRead = true;  
            //  waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");  
                setTimeout(this.handle_nfc_data, 1000);  
            }  
        },  
        onLoad: function(option) {  
            this.listenNFCStatus()  
        },  
        onShow: function(){  
            console.log('page Show');  
            this.timestampShow = (new Date()).getTime();  
            console.log(this.timestampShow)  
            var TimeScale =  this.timestampShow - this.timestampHide;  
            console.log(TimeScale);  
                        nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);  
            if(this.count++ == 0){  
                // this.listenNFCStatus()  
                return false;  
            }else if(TimeScale > 400){  
                return false;  
            }else{  
                this.readData();  
            }  
        },  
        onHide:function(){  
            console.log("onHide");  
            this.timestampHide = (new Date()).getTime();  
            console.log(this.timestampHide);  
        }  
    }

写入分开写了,也是一样的写法

            __write(intent) {  
                try {  
                    waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");  
                    waiting.setTitle('请勿移开标签\n正在写入...');  
                    // var text = document.getElementById('text').value;  
                    console.log("text=" + this.writeCode);  
                    var textBytes = plus.android.invoke(this.writeCode, "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()) {  
                            console.log("tag不允许写入");  
                            waiting.close();  
                            uni.showToast({  
                                title: "tag不允许写入.",  
                                icon: "none"  
                            });  
                            return;  
                        }  
                        if (ndef.getMaxSize() < size) {  
                            console.log("文件大小超出容量");  
                            waiting.close();  
                            uni.showToast({  
                                title: "文件大小超出容量.",  
                                icon: "none"  
                            });  
                            return;  
                        }  
                        // console.log('写入数据:' + JSON.stringify(message) + ' __TYPE__: ' + JSON.stringify(message.__TYPE__));  
                        console.log("message:" + message)  
                        ndef.writeNdefMessage(message);  

                        waiting.close();  
                        console.log("写入数据成功.");  
                        uni.showToast({  
                            title: "写入数据成功.",  
                            icon: "none"  
                        });  
                        this.writeCode = "XJD:" + this.detailObj.code;  
                        this.updateCode(); //数据写入成功后,数据关联成功;  
                        return;  
                    } else {  
                        var format = NdefFormatable.get(tag);  
                        if (format != null) {  
                            try {  
                                format.connect();  
                                format.format(message);  
                                console.log("格式化tag并且写入message")  
                                waiting.close();  
                                return;  
                            } catch (e) {  
                                console.log("格式化tag失败.");  
                                waiting.close();  
                                uni.showToast({  
                                    title: "格式化tag失败.",  
                                    icon: "none"  
                                });  
                                return;  
                            }  
                        } else {  
                            console.log("Tag不支持NDEF");  
                            uni.showToast({  
                                title: "Tag不支持NDEF",  
                                icon: "none"  
                            });  
                            waiting.close();  
                            return;  
                        }  
                    }  
                } catch (e) {  
                    console.log("error=" + e);  
                    waiting.close();  
                    console.log('写入失败');  
                }  
            },  
            writeData() {  
                readyWriteData = true;  
                // waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");  
                setTimeout(this.handle_nfc_data, 1000);  
            },

最近新增了,可读写nfcv格式的标签
http://ask.dcloud.net.cn/article/36108

有其他小伙伴解决了或者有更好的方式可以多多交流

9 关注 分享
DCloud_heavensoft 全栈伟哥 y***@163.com 1***@qq.com 满眼都是你 8***@qq.com 码农朱哲 h***@gmail.com x***@163.com

要回复文章请先登录注册

9***@qq.com

9***@qq.com

回复 我瞅瞅 :
h5可以实现?我h5会报错: plus is not defined
2024-11-16 17:51
saoge

saoge

回复 董裕新 :
不同安卓版本导致的,我解决了,但是最后需求被砍了,就没继续做下去了
2024-10-24 18:01
2***@qq.com

2***@qq.com

回复 saoge :
// main = plus.android.runtimeMainActivity(); 把这个代码放开就行
2024-09-10 15:59
我瞅瞅

我瞅瞅

请问支持h5吗?我的业务代码是以h5嵌入APP里的。我在h5上使用类似的方式调用nfc读卡,可以正常检测是否开启nfc,但是识别的时候用的是手机的nfc识别,导致不走代码的逻辑,触发手机识别卡片打开了记事本展示识别的内容
2024-08-26 19:36
董裕新

董裕新

回复 saoge :
解决了吗?我这里也进不去
2024-08-26 14:45
saoge

saoge

if ("android.nfc.action.TECH_DISCOVERED" == intent.getAction()) 这里这个判断过不去请问是什么原因啊
2024-08-23 10:03
易软

易软

这个 高版本SDK 的问题 我已解决 大家如果有相同的问题 可以去看看
https://ask.dcloud.net.cn/article/40677
2023-08-11 15:06
易软

易软

这个 高版本SDK 的问题 我已解决 大家如果有相同的问题 可以去看看
https://ask.dcloud.net.cn/article/40677
2023-08-11 15:06
易软

易软

回复 易软 :
然后 PendingIntent.getActivity(main, 0, intent, 0) 这个是返回的null
2023-08-10 10:59
易软

易软

亲 我测试 了在基座上没有问题,为什么一打正式包 使用的时候 扫描NFC 顶部会天厨NFC服务,然后叫选应用,但是又检测不到我自己的应用呢
2023-08-09 09:41