iOS 平台实现 (#2)
* 修复 UUID 创建失败的问题 * 移除 scanning 属性 * 临时提交 * CentralManager 开发 & 示例项目开发 * CentralManager 开发 & 示例项目开发 * android 插件生命周期监听 * 修改 API * 示例程序开发 * 修改字体,添加 API,解决后台问题 * Central#connect API * 蓝牙连接部分开发 * 蓝牙连接部分开发 * 解决一些问题 * 解决一些问题 * Connect API 优化 * 添加 API * example 开发 * API 基本完成 * 消息重命名 * API 修改,Android 实现 * 删除多余代码 * 删除多余文件 * 解决 descriptor 自动生成报错的问题 * 还原 Kotlin 版本,广播处理代码迁移至 dart 端 * Kotlin 版本升至 1.5.20 * 解决特征值通知没有在主线程触发的问题,优化代码 * 引入哈希值,避免对象销毁后继续使用 * 使用下拉刷新代替搜索按钮 * 解决由于热重载和蓝牙关闭产生的问题 * 更新插件信息 * 更新 README 和 CHANGELOG * 更新许可证 * 添加注释 * 添加注释,central 拆分 * dartfmt -w . * flutter build ios --no-codesign * API 重构 * 添加 connectable 属性 * Android 8.0 之前无法获取 connectable 属性 * 解决合并错误 * 解决连接时可能引发异常的一个问题,iOS 开发 * API 修改,TODO: iOS 哈希值为 64 位无法用 Int32 表示 * iOS 开发 * iOS 开发完成,使用 UUID 实现对象映射 * 更新版本记录和文档
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.5.20'
|
||||
ext.kotlin_version = '1.5.21'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
|
@ -1 +1,2 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
@ -1 +1,2 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
41
example/ios/Podfile
Normal file
41
example/ios/Podfile
Normal file
@ -0,0 +1,41 @@
|
||||
# Uncomment this line to define a global platform for your project
|
||||
platform :ios, '9.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
'Debug' => :debug,
|
||||
'Profile' => :release,
|
||||
'Release' => :release,
|
||||
}
|
||||
|
||||
def flutter_root
|
||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
||||
unless File.exist?(generated_xcode_build_settings_path)
|
||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
||||
end
|
||||
|
||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||
return matches[1].strip if matches
|
||||
end
|
||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
||||
end
|
||||
|
||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||
|
||||
flutter_ios_podfile_setup
|
||||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
use_modular_headers!
|
||||
|
||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_ios_build_settings(target)
|
||||
end
|
||||
end
|
29
example/ios/Podfile.lock
Normal file
29
example/ios/Podfile.lock
Normal file
@ -0,0 +1,29 @@
|
||||
PODS:
|
||||
- bluetooth_low_energy (0.0.1):
|
||||
- Flutter
|
||||
- SwiftProtobuf (~> 1.0)
|
||||
- Flutter (1.0.0)
|
||||
- SwiftProtobuf (1.17.0)
|
||||
|
||||
DEPENDENCIES:
|
||||
- bluetooth_low_energy (from `.symlinks/plugins/bluetooth_low_energy/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- SwiftProtobuf
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
bluetooth_low_energy:
|
||||
:path: ".symlinks/plugins/bluetooth_low_energy/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
bluetooth_low_energy: 9222b99f977897165e6ffaece386bd289ac8c1fb
|
||||
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
|
||||
SwiftProtobuf: 9c85136c6ba74b0a1b84279dbf0f6db8efb714e0
|
||||
|
||||
PODFILE CHECKSUM: a75497545d4391e2d394c3668e20cfb1c2bbd4aa
|
||||
|
||||
COCOAPODS: 1.10.1
|
@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
@ -13,6 +13,7 @@
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
EA280E36114EEC52A66510AF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F6363DB0F6B8F760A0B70E6 /* Pods_Runner.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
@ -29,8 +30,10 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1173070BE6CFE927D74C0736 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
2F6363DB0F6B8F760A0B70E6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
@ -42,6 +45,8 @@
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
9E8C4C982EC9200D28D9557C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
FA6DAFE6FDB9F8D1C4A8AEF3 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -49,6 +54,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
EA280E36114EEC52A66510AF /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -72,6 +78,8 @@
|
||||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
A19CF493038BEE74587FB0E8 /* Pods */,
|
||||
990CDB7BA621E0B7AFA0C6BE /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@ -98,6 +106,24 @@
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
990CDB7BA621E0B7AFA0C6BE /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2F6363DB0F6B8F760A0B70E6 /* Pods_Runner.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A19CF493038BEE74587FB0E8 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FA6DAFE6FDB9F8D1C4A8AEF3 /* Pods-Runner.debug.xcconfig */,
|
||||
1173070BE6CFE927D74C0736 /* Pods-Runner.release.xcconfig */,
|
||||
9E8C4C982EC9200D28D9557C /* Pods-Runner.profile.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@ -105,12 +131,14 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
4DEF012D22BCBC3AF731DE9C /* [CP] Check Pods Manifest.lock */,
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
EDB3731BEABF1E16CE6A52EB /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@ -183,6 +211,28 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||
};
|
||||
4DEF012D22BCBC3AF731DE9C /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -197,6 +247,23 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
EDB3731BEABF1E16CE6A52EB /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@ -288,9 +355,13 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = JJSB6LL9HD;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.yanshouwang.bluetoothLowEnergyExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@ -399,7 +470,8 @@
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
@ -412,9 +484,13 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = JJSB6LL9HD;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.yanshouwang.bluetoothLowEnergyExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@ -431,9 +507,13 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = JJSB6LL9HD;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.yanshouwang.bluetoothLowEnergyExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
|
@ -4,4 +4,7 @@
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
@ -22,6 +22,8 @@
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSBluetoothAlwaysUsageDescription</key>
|
||||
<string>We need to use your bluetooth to communicate with other BLE devices.</string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
|
@ -27,24 +27,33 @@ class HomeView extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _HomeViewState extends State<HomeView> with WidgetsBindingObserver {
|
||||
final ValueNotifier<bool> state;
|
||||
final ValueNotifier<bool> discovering;
|
||||
final ValueNotifier<Map<MAC, Discovery>> discoveries;
|
||||
late StreamSubscription<bool> stateSubscription;
|
||||
final ValueNotifier<Map<UUID, Discovery>> discoveries;
|
||||
late StreamSubscription<BluetoothState> stateSubscription;
|
||||
late StreamSubscription<Discovery> discoverySubscription;
|
||||
|
||||
_HomeViewState()
|
||||
: discovering = ValueNotifier(false),
|
||||
: state = ValueNotifier(false),
|
||||
discovering = ValueNotifier(false),
|
||||
discoveries = ValueNotifier({});
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance!.addObserver(this);
|
||||
setup();
|
||||
}
|
||||
|
||||
void setup() async {
|
||||
final state = await central.state;
|
||||
this.state.value = state == BluetoothState.poweredOn;
|
||||
stateSubscription = central.stateChanged.listen(
|
||||
(state) {
|
||||
this.state.value = state == BluetoothState.poweredOn;
|
||||
final invisible = !ModalRoute.of(context)!.isCurrent;
|
||||
if (invisible) return;
|
||||
if (state) {
|
||||
if (this.state.value) {
|
||||
startDiscovery();
|
||||
} else {
|
||||
discovering.value = false;
|
||||
@ -53,11 +62,13 @@ class _HomeViewState extends State<HomeView> with WidgetsBindingObserver {
|
||||
);
|
||||
discoverySubscription = central.discovered.listen(
|
||||
(discovery) {
|
||||
discoveries.value[discovery.address] = discovery;
|
||||
discoveries.value[discovery.uuid] = discovery;
|
||||
discoveries.value = {...discoveries.value};
|
||||
},
|
||||
);
|
||||
startDiscovery();
|
||||
if (this.state.value) {
|
||||
startDiscovery();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -88,13 +99,13 @@ class _HomeViewState extends State<HomeView> with WidgetsBindingObserver {
|
||||
}
|
||||
|
||||
void startDiscovery() async {
|
||||
if (discovering.value || !await central.state) return;
|
||||
if (discovering.value || !state.value) return;
|
||||
await central.startDiscovery();
|
||||
discovering.value = true;
|
||||
}
|
||||
|
||||
void stopDiscovery() async {
|
||||
if (!discovering.value || !await central.state) return;
|
||||
if (!discovering.value || !state.value) return;
|
||||
await central.stopDiscovery();
|
||||
discoveries.value = {};
|
||||
discovering.value = false;
|
||||
@ -113,7 +124,7 @@ class _HomeViewState extends State<HomeView> with WidgetsBindingObserver {
|
||||
stopDiscovery();
|
||||
await Navigator.of(context).pushNamed(
|
||||
'gatt',
|
||||
arguments: discovery.address,
|
||||
arguments: discovery.uuid,
|
||||
);
|
||||
startDiscovery();
|
||||
}
|
||||
@ -121,16 +132,10 @@ class _HomeViewState extends State<HomeView> with WidgetsBindingObserver {
|
||||
|
||||
extension on _HomeViewState {
|
||||
Widget get bodyView {
|
||||
return FutureBuilder<bool>(
|
||||
future: central.state,
|
||||
builder: (context, snapshot) => snapshot.hasData
|
||||
? StreamBuilder<bool>(
|
||||
stream: central.stateChanged,
|
||||
initialData: snapshot.data,
|
||||
builder: (context, snapshot) =>
|
||||
snapshot.data! ? discoveriesView : closedView,
|
||||
)
|
||||
: closedView,
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: state,
|
||||
builder: (context, bool state, child) =>
|
||||
state ? discoveriesView : closedView,
|
||||
);
|
||||
}
|
||||
|
||||
@ -145,14 +150,14 @@ extension on _HomeViewState {
|
||||
onRefresh: () async => discoveries.value = {},
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: discoveries,
|
||||
builder: (context, Map<MAC, Discovery> discoveries, child) {
|
||||
builder: (context, Map<UUID, Discovery> discoveries, child) {
|
||||
return ListView.builder(
|
||||
padding: EdgeInsets.all(6.0),
|
||||
itemCount: discoveries.length,
|
||||
itemBuilder: (context, i) {
|
||||
final discovery = discoveries.values.elementAt(i);
|
||||
return Card(
|
||||
color: Colors.amber,
|
||||
color: discovery.connectable ? Colors.amber : Colors.grey,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
shape: BeveledRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
@ -160,24 +165,39 @@ extension on _HomeViewState {
|
||||
bottomLeft: Radius.circular(12.0)),
|
||||
),
|
||||
margin: EdgeInsets.all(6.0),
|
||||
key: Key(discovery.address.name),
|
||||
key: Key(discovery.uuid.name),
|
||||
child: InkWell(
|
||||
splashColor: Colors.purple,
|
||||
onTap: () => showGattView(discovery),
|
||||
onTap: discovery.connectable
|
||||
? () => showGattView(discovery)
|
||||
: null,
|
||||
onLongPress: () => showAdvertisements(discovery),
|
||||
child: Container(
|
||||
height: 100.0,
|
||||
padding: EdgeInsets.all(12.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(discovery.name ?? 'NaN'),
|
||||
Text(discovery.address.name),
|
||||
],
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(discovery.name ?? 'NaN'),
|
||||
Text(
|
||||
discovery.uuid.name,
|
||||
softWrap: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
discovery.rssi.toString(),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Text(discovery.rssi.toString()),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -265,7 +285,7 @@ class _GattViewState extends State<GattView> {
|
||||
final ValueNotifier<Map<GattCharacteristic, StreamSubscription>> notifies;
|
||||
final ValueNotifier<List<String>> logs;
|
||||
|
||||
late MAC address;
|
||||
late UUID uuid;
|
||||
|
||||
_GattViewState()
|
||||
: state = ValueNotifier(ConnectionState.disconnected),
|
||||
@ -282,10 +302,10 @@ class _GattViewState extends State<GattView> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
address = ModalRoute.of(context)!.settings.arguments as MAC;
|
||||
uuid = ModalRoute.of(context)!.settings.arguments as UUID;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('$address'),
|
||||
title: Text(uuid.name),
|
||||
actions: [
|
||||
changeStateView,
|
||||
],
|
||||
@ -336,7 +356,7 @@ class _GattViewState extends State<GattView> {
|
||||
void connect() async {
|
||||
try {
|
||||
state.value = ConnectionState.connecting;
|
||||
gatt = await central.connect(address);
|
||||
gatt = await central.connect(uuid);
|
||||
state.value = ConnectionState.connected;
|
||||
connectionLostSubscription = gatt!.connectionLost.listen(
|
||||
(errorCode) async {
|
||||
@ -547,6 +567,7 @@ extension on _GattViewState {
|
||||
final controllerView = TextField(
|
||||
controller: writeController,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'MTU: ${gatt!.maximumWriteLength}',
|
||||
suffixIcon: IconButton(
|
||||
onPressed: canWrite
|
||||
? () {
|
||||
|
@ -5,7 +5,7 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.6.1"
|
||||
bluetooth_low_energy:
|
||||
@ -14,68 +14,68 @@ packages:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.2"
|
||||
version: "0.1.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
convert:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: convert
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
version: "3.0.1"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cupertino_icons
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
flutter:
|
||||
@ -87,7 +87,7 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_simple_treeview
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0-nullsafety.1"
|
||||
flutter_test:
|
||||
@ -99,35 +99,35 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.10"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
pedantic:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: pedantic
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.11.1"
|
||||
protobuf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: protobuf
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
sky_engine:
|
||||
@ -139,56 +139,56 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.flutter-io.cn"
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
sdks:
|
||||
|
Reference in New Issue
Block a user