这个问题是 iOS 应用签名和配置相关的典型问题。当你通过数据线连接运行 flutter run 时,应用是以开发模式安装的,而拔掉数据线后应用无法打开,这通常是因为应用签名配置不正确。
问题原因
- 开发者证书问题:iOS 应用需要有正确的签名证书才能在设备上运行
- 应用信任设置:未被信任的开发者应用需要在设备上手动信任
- 配置文件过期:开发配置文件可能已过期或不正确
解决方案
1. 修改 Xcode 项目配置
首先,我们需要修改 Xcode 项目配置,确保应用可以在设备上独立运行:
cd ios && xcodebuild -showBuildSettings | grep DEVELOPMENT_TEAM
我们看到开发团队 ID 是 U493433K68,这是好的。现在,让我们检查 Runner.xcodeproj 的配置:
cd .. && flutter build ios --release
构建成功了,这很好。现在让我们修改 iOS 项目配置,确保应用可以在设备上独立运行:
// ... existing code ...
/* Begin XCBuildConfiguration section */
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
// ... existing code ...
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = U496534568;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Ma345x;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.ma353x.chair;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = U345468;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = MassaMax;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.ma6456x.chair;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
// ... existing code ...
2. 添加必要的应用权限和配置
让我们确保 Info.plist 文件中包含所有必要的权限和配置:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Ma6456ax</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Ma456ax</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>需要蓝牙权限来连接和控制按摩椅</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>需要蓝牙权限来连接和控制按摩椅</string>
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
</array>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
3. 创建 iOS 发布构建
现在让我们创建一个真正的发布版本,并使用正确的签名:
flutter clean && flutter pub get && flutter build ios --release
4. 使用 Xcode 安装应用
现在我们需要使用 Xcode 打开项目并进行最终配置:
cd ios && xcodebuild -workspace Runner.xcworkspace -scheme Runner -configuration Release -sdk iphoneos -archivePath build/Runner.xcarchive archive
现在我们已经成功创建了归档文件,接下来需要导出IPA文件以便安装到设备上:
cd ios && xcodebuild -exportArchive -archivePath build/Runner.xcarchive -exportPath build/ios/ipa -exportOptionsPlist exportOptions.plist || echo "需要先创建exportOptions.plist文件"
我们需要创建一个exportOptions.plist文件,然后再尝试导出IPA:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>development</string>
<key>teamID</key>
<string>U4962SLK68</string>
<key>compileBitcode</key>
<false/>
<key>provisioningProfiles</key>
<dict>
<key>com.ma53453max.chair</key>
<string>iOS Team Provisioning Profile: com.massamax.chair</string>
</dict>
</dict>
</plist>
现在让我们尝试导出IPA文件:
xcodebuild -exportArchive -archivePath build/Runner.xcarchive -exportPath build/ios/ipa -exportOptionsPlist exportOptions.plist
太好了!IPA文件已经成功导出。现在我们可以检查一下导出的文件:
ls -la build/ios/ipa
现在我们已经成功创建了IPA文件(MassaMax.ipa),接下来有几种方式可以将其安装到iOS设备上:
5. 安装应用到设备
方法一:使用Xcode直接安装
open -a Xcode
方法二:使用Apple Configurator 2安装
如果您有Apple Configurator 2应用,可以使用它来安装IPA文件:
cd /Users/peter/code_arvita && open -a "Apple Configurator 2" || echo "Apple Configurator 2可能未安装"
安装指南
现在我将为您提供详细的安装指南:
使用Xcode安装:
- 在Xcode中,点击顶部菜单栏中的"Window" > “Devices and Simulators”
- 将您的iOS设备通过USB连接到Mac电脑
- 在左侧面板中选择您的设备
- 在右侧面板中,点击"+"按钮(位于已安装应用列表下方)
- 浏览并选择我们刚刚创建的IPA文件(位于
/Users/peter/code_arvita/ios/build/ios/ipa/MassaMax.ipa) - 等待安装完成
使用Apple Configurator 2安装:
- 打开Apple Configurator 2
- 将iOS设备连接到Mac
- 在应用中选择您的设备
- 点击顶部菜单中的"Add" > “Apps”
- 选择"Choose from my Mac…"
- 浏览并选择我们刚刚创建的IPA文件
- 点击"Add"并等待安装完成
注意事项:
-
设备必须信任开发者证书:
- 首次安装后,在设备上前往"设置" > “通用” > “设备管理”
- 找到开发者证书(与您的Apple ID相关联)并点击"信任"
-
蓝牙功能测试:
- 安装完成后,打开应用
- 确保设备蓝牙已开启
- 尝试使用"扫描设备"按钮
- 检查应用是否能够正确检测蓝牙设备
-
如果遇到问题:
- 检查设备的蓝牙权限设置
- 确认Info.plist中的蓝牙权限配置正确
- 查看设备日志以获取更多信息
恭喜您!现在您已经成功构建并准备好了iOS应用的安装包,可以安装到实际设备上进行测试了。这应该能解决之前遇到的蓝牙扫描问题。
660

被折叠的 条评论
为什么被折叠?



