├── static
└── logo.png
├── README.en.md
├── main.js
├── README.md
├── App.vue
├── pages.json
├── pages
└── index
│ └── index.vue
├── LICENSE
├── uni.scss
├── manifest.json
└── utils
└── hexiii-nfc.js
/static/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cssmini/uniapp-hexiii-nfc-plugin/HEAD/static/logo.png
--------------------------------------------------------------------------------
/README.en.md:
--------------------------------------------------------------------------------
1 | # uniapp-hexiii-nfc-plugin
2 |
3 | #### Description
4 | uniapp NFC 插件,代码个人整理自 uni-app 论坛及网络。
5 |
6 | 使用插件时,建议先查阅安卓 NFC api 相关文档。
7 |
8 | 如代码或注释有误,欢迎联系作者进行反馈。
9 |
10 | 如代码对你有帮助,欢迎 Star
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App'
3 |
4 | Vue.config.productionTip = false
5 |
6 | App.mpType = 'app'
7 |
8 | const app = new Vue({
9 | ...App
10 | })
11 | app.$mount()
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # uniapp-hexiii-nfc-plugin
2 |
3 | #### 介绍
4 | uniapp NFC 插件,代码个人整理自 uni-app 论坛及网络。
5 |
6 | 使用插件时,建议先查阅安卓 NFC api 相关文档。
7 |
8 | 如代码或注释有误,欢迎联系我进行反馈。
9 |
10 | 如代码对你有帮助,欢迎 Star,这是对我的鼓励。
11 |
12 | 论坛消息、留言做不到及时回复,可邮件或QQ找到我。
13 | ```
14 | 邮箱(base64): Y3NzbWluaUBxcS5jb20=
15 | 企鹅号(base64):MjQxNTIzMTQ5Nw==
16 | ```
--------------------------------------------------------------------------------
/App.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
18 |
--------------------------------------------------------------------------------
/pages.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
3 | {
4 | "path": "pages/index/index",
5 | "style": {
6 | "navigationBarTitleText": "uni-app"
7 | }
8 | }
9 | ],
10 | "globalStyle": {
11 | "navigationBarTextStyle": "black",
12 | "navigationBarTitleText": "uni-app",
13 | "navigationBarBackgroundColor": "#F8F8F8",
14 | "backgroundColor": "#F8F8F8"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/pages/index/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
38 |
39 |
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 乘风
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/uni.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * 这里是uni-app内置的常用样式变量
3 | *
4 | * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
5 | * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
6 | *
7 | */
8 |
9 | /**
10 | * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
11 | *
12 | * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
13 | */
14 |
15 | /* 颜色变量 */
16 |
17 | /* 行为相关颜色 */
18 | $uni-color-primary: #007aff;
19 | $uni-color-success: #4cd964;
20 | $uni-color-warning: #f0ad4e;
21 | $uni-color-error: #dd524d;
22 |
23 | /* 文字基本颜色 */
24 | $uni-text-color:#333;//基本色
25 | $uni-text-color-inverse:#fff;//反色
26 | $uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
27 | $uni-text-color-placeholder: #808080;
28 | $uni-text-color-disable:#c0c0c0;
29 |
30 | /* 背景颜色 */
31 | $uni-bg-color:#ffffff;
32 | $uni-bg-color-grey:#f8f8f8;
33 | $uni-bg-color-hover:#f1f1f1;//点击状态颜色
34 | $uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
35 |
36 | /* 边框颜色 */
37 | $uni-border-color:#c8c7cc;
38 |
39 | /* 尺寸变量 */
40 |
41 | /* 文字尺寸 */
42 | $uni-font-size-sm:24upx;
43 | $uni-font-size-base:28upx;
44 | $uni-font-size-lg:32upx;
45 |
46 | /* 图片尺寸 */
47 | $uni-img-size-sm:40upx;
48 | $uni-img-size-base:52upx;
49 | $uni-img-size-lg:80upx;
50 |
51 | /* Border Radius */
52 | $uni-border-radius-sm: 4upx;
53 | $uni-border-radius-base: 6upx;
54 | $uni-border-radius-lg: 12upx;
55 | $uni-border-radius-circle: 50%;
56 |
57 | /* 水平间距 */
58 | $uni-spacing-row-sm: 10px;
59 | $uni-spacing-row-base: 20upx;
60 | $uni-spacing-row-lg: 30upx;
61 |
62 | /* 垂直间距 */
63 | $uni-spacing-col-sm: 8upx;
64 | $uni-spacing-col-base: 16upx;
65 | $uni-spacing-col-lg: 24upx;
66 |
67 | /* 透明度 */
68 | $uni-opacity-disabled: 0.3; // 组件禁用态的透明度
69 |
70 | /* 文章场景相关 */
71 | $uni-color-title: #2C405A; // 文章标题颜色
72 | $uni-font-size-title:40upx;
73 | $uni-color-subtitle: #555555; // 二级标题颜色
74 | $uni-font-size-subtitle:36upx;
75 | $uni-color-paragraph: #3F536E; // 文章段落颜色
76 | $uni-font-size-paragraph:30upx;
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name" : "NFC_DEMO",
3 | "appid" : "__UNI__3A733D9",
4 | "description": "",
5 | "versionName": "1.0.0",
6 | "versionCode": "100",
7 | "transformPx": false,
8 | /* 5+App特有相关 */
9 | "app-plus": {
10 | "usingComponents": true,
11 | "nvueCompiler": "uni-app",
12 | "splashscreen": {
13 | "alwaysShowBeforeRender": true,
14 | "waiting": true,
15 | "autoclose": true,
16 | "delay": 0
17 | },
18 | /* 模块配置 */
19 | "modules": {
20 |
21 | },
22 | /* 应用发布信息 */
23 | "distribute": {
24 | /* android打包配置 */
25 | "android": {
26 | "permissions": ["",
27 | "",
28 | "",
29 | "",
30 | "",
31 | "",
32 | "",
33 | "",
34 | "",
35 | "",
36 | "",
37 | "",
38 | "",
39 | "",
40 | "",
41 | "",
42 | "",
43 | "",
44 | "",
45 | "",
46 | "",
47 | ""
48 | ]
49 | },
50 | /* ios打包配置 */
51 | "ios": {
52 |
53 | },
54 | /* SDK配置 */
55 | "sdkConfigs": {
56 |
57 | }
58 | }
59 | },
60 | /* 快应用特有相关 */
61 | "quickapp": {
62 |
63 | },
64 | /* 小程序特有相关 */
65 | "mp-weixin": {
66 | "appid": "",
67 | "setting": {
68 | "urlCheck": false
69 | },
70 | "usingComponents": true
71 | },
72 | "mp-alipay" : {
73 | "usingComponents" : true
74 | },
75 | "mp-baidu" : {
76 | "usingComponents" : true
77 | },
78 | "mp-toutiao" : {
79 | "usingComponents" : true
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/utils/hexiii-nfc.js:
--------------------------------------------------------------------------------
1 | // 包路径
2 | const package_NdefRecord = 'android.nfc.NdefRecord';
3 | const package_NdefMessage = 'android.nfc.NdefMessage';
4 | const package_TECH_DISCOVERED = 'android.nfc.action.TECH_DISCOVERED';
5 | const package_Intent = 'android.content.Intent';
6 | const package_Activity = 'android.app.Activity';
7 | const package_PendingIntent = 'android.app.PendingIntent';
8 | const package_IntentFilter = 'android.content.IntentFilter';
9 | const package_NfcAdapter = 'android.nfc.NfcAdapter';
10 | const package_Ndef = 'android.nfc.tech.Ndef';
11 | const package_NdefFormatable = 'android.nfc.tech.NdefFormatable';
12 | const package_Parcelable = 'android.os.Parcelable';
13 | const package_String = 'java.lang.String';
14 |
15 | let NfcAdapter;
16 | let NdefRecord;
17 | let NdefMessage;
18 | let readyWriteData = false;
19 | let readyRead = false;
20 | let noNFC = false;
21 | let techListsArray = [
22 | ['android.nfc.tech.IsoDep'],
23 | ['android.nfc.tech.NfcA'],
24 | ['android.nfc.tech.NfcB'],
25 | ['android.nfc.tech.NfcF'],
26 | ['android.nfc.tech.Nfcf'],
27 | ['android.nfc.tech.NfcV'],
28 | ['android.nfc.tech.NdefFormatable'],
29 | ['android.nfc.tech.MifareClassi'],
30 | ['android.nfc.tech.MifareUltralight']
31 | ];
32 | // 要写入的数据
33 | let text = '{id:123,name:nfc,stie:cssmini.com}';
34 | let readResult = '';
35 |
36 | export default {
37 | listenNFCStatus: function () {
38 | let that = this;
39 | try {
40 | let main = plus.android.runtimeMainActivity();
41 | let Intent = plus.android.importClass('android.content.Intent');
42 | let Activity = plus.android.importClass('android.app.Activity');
43 | let PendingIntent = plus.android.importClass('android.app.PendingIntent');
44 | let IntentFilter = plus.android.importClass('android.content.IntentFilter');
45 | NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');
46 | let nfcAdapter = NfcAdapter.getDefaultAdapter(main);
47 |
48 | if(nfcAdapter == null){
49 | uni.showToast({
50 | title: '设备不支持NFC!',
51 | icon: 'none'
52 | })
53 | noNFC = true;
54 | return;
55 | }
56 |
57 | if (!nfcAdapter.isEnabled()) {
58 | uni.showToast({
59 | title: '请在系统设置中先启用NFC功能!',
60 | icon: 'none'
61 | });
62 | noNFC = true;
63 | return;
64 | }else{
65 | noNFC = false;
66 | }
67 |
68 | let intent = new Intent(main, main.getClass());
69 | intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
70 | let pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);
71 | let ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");
72 | ndef.addDataType("*/*");
73 | let intentFiltersArray = [ndef];
74 |
75 | plus.globalEvent.addEventListener('newintent',function() {
76 | console.log('newintent running');
77 | // 监听 NFC
78 | setTimeout(that.nfcRuning(), 1000);
79 | });
80 | plus.globalEvent.addEventListener('pause',function(e) {
81 | console.log('pause running');
82 | if (nfcAdapter) {
83 | //关闭前台调度系统
84 | //恢复默认状态
85 | nfcAdapter.disableForegroundDispatch(main);
86 | }
87 | });
88 | plus.globalEvent.addEventListener('resume',function(e) {
89 | console.log('resume running');
90 | if (nfcAdapter) {
91 | //开启前台调度系统
92 | nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
93 | }
94 | });
95 | nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
96 | } catch (e) {
97 | console.error(e);
98 | }
99 | },
100 | nfcRuning: function () {
101 | NdefRecord = plus.android.importClass("android.nfc.NdefRecord");
102 | NdefMessage = plus.android.importClass("android.nfc.NdefMessage");
103 | let main = plus.android.runtimeMainActivity();
104 | let intent = main.getIntent();
105 | let that = this;
106 |
107 | console.log("action type:" + intent.getAction());
108 |
109 | if (package_TECH_DISCOVERED == intent.getAction()) {
110 | if (readyWriteData) {
111 | that.write(intent);
112 | readyWriteData = false;
113 | } else if (readyRead) {
114 | that.read(intent);
115 | readyRead = false;
116 | }
117 | }
118 | },
119 | write(intent) {
120 | try {
121 | toast('请勿移开标签 正在写入...');
122 | console.log("text=" + text);
123 |
124 | let textBytes = plus.android.invoke(text, "getBytes");
125 | // image/jpeg text/plain
126 | let textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
127 | plus.android.invoke("text/plain", "getBytes"),
128 | plus.android.invoke("", "getBytes"), textBytes);
129 | let message = new NdefMessage([textRecord]);
130 | let Ndef = plus.android.importClass('android.nfc.tech.Ndef');
131 | let NdefFormatable = plus.android.importClass('android.nfc.tech.NdefFormatable');
132 | let tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
133 | let ndef = Ndef.get(tag);
134 | if (ndef != null) {
135 | // 待写入的数据长度
136 | let size = message.toByteArray().length;
137 | ndef.connect();
138 | if (!ndef.isWritable()) {
139 | toast('tag不允许写入!');
140 | return;
141 | }
142 | if (ndef.getMaxSize() < size) {
143 | toast('文件大小超出容量!');
144 | return;
145 | }
146 | ndef.writeNdefMessage(message);
147 | toast('写入数据成功!');
148 | return;
149 | } else {
150 | let format = NdefFormatable.get(tag);
151 | if (format != null) {
152 | try {
153 | format.connect();
154 | format.format(message);
155 | toast('格式化tag并且写入message');
156 | return;
157 | } catch (e) {
158 | toast('格式化tag失败.');
159 | return;
160 | }
161 | } else {
162 | toast('Tag不支持NDEF');
163 | return;
164 | }
165 | }
166 | } catch (e) {
167 | toast('写入失败');
168 | console.log("error=" + e);
169 | }
170 |
171 | },
172 | read(intent) {
173 | toast('请勿移开标签正在读取数据');
174 | let that = this;
175 | // NFC id
176 | let bytesId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
177 | let nfc_id = that.byteArrayToHexString(bytesId);
178 | console.log('nfc_id:', nfc_id);
179 | let Parcelable = plus.android.importClass("android.os.Parcelable");
180 | let rawmsgs = intent.getParcelableArrayExtra("android.nfc.extra.NDEF_MESSAGES");
181 | //let rawmsgs = intent.getParcelableArrayExtra();
182 |
183 | if(rawmsgs != null && rawmsgs.length > 0) {
184 | let records = rawmsgs[0].getRecords();
185 | let result = records[0].getPayload();
186 | let data = plus.android.newObject("java.lang.String", result);
187 | toast('NFC 数据:' + data);
188 | console.log('NFC 数据:',data);
189 | readResult = data;
190 | }else{
191 | toast('没有读取到数据');
192 | }
193 | },
194 | byteArrayToHexString: function (inarray) { // converts byte arrays to string
195 | let i, j, inn;
196 | let hex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
197 | let out = "";
198 |
199 | for(j = 0; j < inarray.length; ++j) {
200 | inn = inarray[j] & 0xff;
201 | i = (inn >>> 4) & 0x0f;
202 | out += hex[i];
203 | i = inn & 0x0f;
204 | out += hex[i];
205 | }
206 | return out;
207 | },
208 | writeData: function () {
209 | if(noNFC){
210 | toast('请检查设备是否支持并开启 NFC 功能!');
211 | return;
212 | }
213 | // 监听事件,触发条件
214 | readyWriteData = true;
215 | toast('请将NFC标签靠近!');
216 | },
217 | readData: function () {
218 | if(noNFC){
219 | toast('请检查设备是否支持并开启 NFC 功能!');
220 | return;
221 | }
222 | // 监听事件,触发条件
223 | readyRead = true;
224 | toast('请将NFC标签靠近!');
225 | }
226 | }
227 | function toast(content){
228 | uni.showToast({
229 | title: content,
230 | icon: 'none'
231 | })
232 | }
--------------------------------------------------------------------------------