文章前景:目前公司主要的业务方向是sass平台,我们的admin系统是基于qiankun搭建的主基座和子模块,app是flutter+h5。我主要负责的是
1、qiankun基座的搭建
2、flutter基座和通信jsbridge的搭建
3、app内h5的书写
4、模块开发规范的书写
5、…
在完善通信jsbridge时,发现有模块需要是需要基于nfc实现的,所以我需要完善ios与android的nfc功能
在pub上看到nfc_manager 反馈还不错,调查了一下,基本需求可以达到。在此,总结一下几个关键点,希望可以帮助到更多的小伙伴。
一、加入插件
首先,我们需要在yaml文件加入该pub
dependencies:
nfc_manager: ^2.0.2
二、配置android权限
在android上我们需要在android/app/src/main/AndroidManifest.xml加入以下授权代码
<!--NFC读取权限配置-->
<uses-permission android:name="android.permission.NFC"/>
三、 配置ios环境
ios一言难尽,过程真的很坎坷,我配了很久。
首先你必须得有一个公司级的开发者账号,个人开发者是不允许使用的,因为你需要在xocde上配置signing的一些东西,然而这些东西个人开发者是不支持的,这个问题我找了很久
1、添加Identifiers并配置NFC Tag Reading
- 让公司的开发者账号添加你的ios账号
- iosDeveloper地址:https://developer.apple.com/account
- 开发者账号内添加一个Identifiers给我这个app使用,添加Identifiers时,记得勾选NFC Tag Reading权限
- 可以顺便给自己添加一个devices,供自己真机调试使用
2、配置Capablity
- 您需要在team内选择公司的开发者账号,否则您将无法进行以下操作
- 当您有权限后,您可以添加一个Capablity,将Near Field Communication Tag Reading加入您的Signing
3、配置info.list文件
因为xcode点来点去的麻烦,我选择直接在flutter的ios目录ios/Runner/Info.plist内添加上以下授权代码
<key>LSApplicationQueriesSchemes</key>
<array>
<string>sms</string>
<string>tel</string>
<string>wechat</string>
<string>weixin</string>
<string>weixinULAPI</string>
<string>comgooglemaps</string>
<string>baidumap</string>
<string>iosamap</string>
<string>waze</string>
<string>yandexmaps</string>
<string>yandexnavi</string>
<string>citymapper</string>
<string>mapswithme</string>
<string>osmandmaps</string>
<string>dgis</string>
<string>qqmap</string>
<string>here-location</string>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NFCReaderUsageDescription</key>
<string>是否允许使用NFC</string>
<key>NSAppTransportSecurity</key>
<key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
<array>
<string>8005</string>
<string>8008</string>
<string>0003</string>
<string>fe00</string>
<string>90b7</string>
<string>927a</string>
<string>86a7</string>
</array>
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
<string>NDEF</string>
<string>TAG</string>
</array>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
<string>A0000002471001</string>
<string>A000000003101001</string>
<string>A000000003101002</string>
<string>A0000000041010</string>
<string>A0000000042010</string>
<string>A0000000044010</string>
<string>44464D46412E44466172653234313031</string>
<string>D2760000850100</string>
<string>D2760000850101</string>
<string>00000000000000</string>
</array>
四、开发
以上配置都配好了情况下,您可以愉快的开发了,以下为官网的例子可以作为参考使用
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:nfc_manager/nfc_manager.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
ValueNotifier<dynamic> result = ValueNotifier(null);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('NfcManager Plugin Example')),
body: SafeArea(
child: FutureBuilder<bool>(
future: NfcManager.instance.isAvailable(),
builder: (context, ss) => ss.data != true
? Center(child: Text('NfcManager.isAvailable(): ${ss.data}'))
: Flex(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
direction: Axis.vertical,
children: [
Flexible(
flex: 2,
child: Container(
margin: EdgeInsets.all(4),
constraints: BoxConstraints.expand(),
decoration: BoxDecoration(border: Border.all()),
child: SingleChildScrollView(
child: ValueListenableBuilder<dynamic>(
valueListenable: result,
builder: (context, value, _) =>
Text('${value ?? ''}'),
),
),
),
),
Flexible(
flex: 3,
child: GridView.count(
padding: EdgeInsets.all(4),
crossAxisCount: 2,
childAspectRatio: 4,
crossAxisSpacing: 4,
mainAxisSpacing: 4,
children: [
ElevatedButton(
child: Text('Tag Read'), onPressed: _tagRead),
ElevatedButton(
child: Text('Ndef Write'),
onPressed: _ndefWrite),
ElevatedButton(
child: Text('Ndef Write Lock'),
onPressed: _ndefWriteLock),
],
),
),
],
),
),
),
),
);
}
void _tagRead() {
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
result.value = tag.data;
NfcManager.instance.stopSession();
});
}
void _ndefWrite() {
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
var ndef = Ndef.from(tag);
if (ndef == null || !ndef.isWritable) {
result.value = 'Tag is not ndef writable';
NfcManager.instance.stopSession(errorMessage: result.value);
return;
}
NdefMessage message = NdefMessage([
NdefRecord.createText('Hello World!'),
NdefRecord.createUri(Uri.parse('https://flutter.dev')),
NdefRecord.createMime(
'text/plain', Uint8List.fromList('Hello'.codeUnits)),
NdefRecord.createExternal(
'com.example', 'mytype', Uint8List.fromList('mydata'.codeUnits)),
]);
try {
await ndef.write(message);
result.value = 'Success to "Ndef Write"';
NfcManager.instance.stopSession();
} catch (e) {
result.value = e;
NfcManager.instance.stopSession(errorMessage: result.value.toString());
return;
}
});
}
void _ndefWriteLock() {
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
var ndef = Ndef.from(tag);
if (ndef == null) {
result.value = 'Tag is not ndef';
NfcManager.instance.stopSession(errorMessage: result.value.toString());
return;
}
try {
await ndef.writeLock();
result.value = 'Success to "Ndef Write Lock"';
NfcManager.instance.stopSession();
} catch (e) {
result.value = e;
NfcManager.instance.stopSession(errorMessage: result.value.toString());
return;
}
});
}
}