看那APP
Go to file
2025-05-16 10:43:23 +08:00
.vscode first commit 2025-05-14 17:04:13 +08:00
android first commit 2025-05-14 17:04:13 +08:00
assets first commit 2025-05-14 17:04:13 +08:00
images first commit 2025-05-14 17:04:13 +08:00
ios ios配置 2025-05-16 10:43:23 +08:00
lib 添加iOS集成unity 2025-05-14 18:24:12 +08:00
linux first commit 2025-05-14 17:04:13 +08:00
macos ios配置 2025-05-16 10:43:23 +08:00
test first commit 2025-05-14 17:04:13 +08:00
unity/VRProject2 first commit 2025-05-14 17:04:13 +08:00
web first commit 2025-05-14 17:04:13 +08:00
windows first commit 2025-05-14 17:04:13 +08:00
.cursorrules first commit 2025-05-14 17:04:13 +08:00
.gitattributes first commit 2025-05-14 17:04:13 +08:00
.gitignore first commit 2025-05-14 17:04:13 +08:00
.metadata first commit 2025-05-14 17:04:13 +08:00
analysis_options.yaml first commit 2025-05-14 17:04:13 +08:00
pubspec.lock first commit 2025-05-14 17:04:13 +08:00
pubspec.yaml first commit 2025-05-14 17:04:13 +08:00
README.md 修改iOS无法找到UnityLibrary 2025-05-15 10:15:33 +08:00

ar_tourism_flutter_unity

1.文字渐变

                    ShaderMask(
                                shaderCallback: (Rect bounds) {
                                  return const LinearGradient(
                                    colors: [
                                      Color(0xFF80DAA4),
                                      Color(0xFF79DDED),
                                    ],
                                  ).createShader(bounds);
                                },
                                child: const Text('确定',
                                    style: TextStyle(
                                        color: Colors.white,
                                        fontSize: 18)),
                              ),

flutter 打包后的文件 build/app/outputs/flutter-apk/app-debug.apk

*不要忘记online_time_service 文件修改 ws 部署地址*

ndroid/app/src/main/res/xml 目录下创建 network_security_config.xml 文件:创建网络安全配置文件 82.156.153.112

flutter run --release 运行打包文件

flutter build apk --target-platform android-arm,android-arm64,android-x64 --split-per-abi 可以减小打包体积

flutter build apk

使用 flutter analyze 命令检查代码中的潜在问题,确保没有冗余的代码和依赖。

git 大文件上传报错 https://blog.csdn.net/qq_22903677/article/details/138123394

git lfs install git add . git commit -m ""

git push 报错

错误 batch response: LFS only supported repository in paid or trial enterpri rm .git/hooks/pre-push git push -u origin "master"

#接口调用 import '../../apis/app.dart'; userApi.getLoginCode(data).then((result) { if (result['code'] == 200) { print("发送成功"); Navigator.pushNamed(context, '/tabs'); } else { print("发送失败"); } });

formData 上传文件

// 构建实名认证信息对象 var infoMsg = { "user_name": _phoneController.text, "real_name": _nameController.text, "id_card": _idCardController.text }; // 将 infoMsg 转换为 JSON 字符串 var infoMsgJson = jsonEncode(infoMsg); // 获取文件对象 File frontFile = File(_frontImage!.path); print("frontFile: $frontFile"); File backFile = File(_backImage!.path); print("backFile: $backFile");

              // 创建 FormData
              FormData formData = FormData.fromMap({
                "cardFront": await MultipartFile.fromFile(frontFile.path,
                    filename: "card_front.png"),
                "cardBack": await MultipartFile.fromFile(backFile.path,
                    filename: "card_back.png"),
                "realNameAuthenticationDto": infoMsgJson, // 添加 JSON 字符串
              });



              print("请求数据: $formData");

              // 调用实名认证API
              userApi.getRealNameAuth(formData).then((result) {
                if (result['code'] == 200) {
                  print("实名认证成功");
                  // 跳转到认证成功页面
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => const AuthSuccessPage(),
                    ),
                  );
                }
              });

格式化时间

String _formatDateTime(String dateTimeString) { DateTime dateTime = DateTime.parse(dateTimeString).toLocal(); return '${dateTime.year}-${dateTime.month}-${dateTime.day} ${dateTime.hour}:${dateTime.minute}:${dateTime.second}'; // 格式化为 年月日 时分秒 }

跳转到底部导航页

Navigator.pushNamedAndRemoveUntil( context, '/tabs', (route) => false, arguments: {'initialIndex': 1}, // 传递参数,设置初始选中的 tab );

集成 unity

1.baseProjectTemplate.gradle 文件 classpath 'com.android.tools.build:gradle:7.3.0', classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0" 2.NDK 版本 21.3

#运行清除缓存 adb shell pm clear com.example.ar_tourism_flutter_unity

unityLibrary 文件夹

1.添加.so 文件 src/main/jniLibs/arm64-v8a/libEasyAR.so libc++_shared.so

每次从 unity 导入 flutter 时要检查:

1.unity--->Player Company Name: com.example Product Name: ar_tourism_flutter_unity 2.unity--> build Settings Export Project 勾选IL2CPP Code GenerationFastersmallerbuilds 3.unity--> Player -->otherSettings OpenGLES3 下都取消勾选 Auto Graphics API 勾选 4.unity--> Player -->otherSettings Package Namecom.example.ar_tourism_flutter_unity 5.unity--> Player -->Minimum APl LevelAndroid 5.1 'Lollipop'(APl level 22);Target APl Level:APllevel 34 6.unity--> Player -->Scripting Backend:IL2CPP 勾选 ARM64 7.unity-->Project Settings-->EasyAR/Sence EasyAR Sence License Key:URzW8VUPzu1NaWbUsPbv6VUBDY95e6AyZGz+imEu4NpVPubHYTPxii5/tJAnabCYJWWynSIdtJ4nc+bHeX+pink89txxL87NbRThii5sqYp4NObNei7g2zZn3tM2P/DGcDHg4XAup5JPAKmKYjz3wXUz8ds2Z96KdzLoxWEz7Nxtf9iENi3pyWA76tp5LqeST3/ywXo56t9nf6mKeTzmiklxp8V7OfDEcS6nkk9/9s16LuCGXTDkz3EJ98l3NuzGc3+pimc469txc8bEeyjh+nE+6s96NPHBezOnhDYu4MZnOKv6cT7q2nA06882cafbcTP2zToS58JxPvH8Zjzmw30z4oo4f/bNei7ghkco9851PuD8Zjzmw30z4oo4f/bNei7ghkct5NpnONbYdSnsyXgQ5Ng2cafbcTP2zToQ6tx9Muv8Zjzmw30z4oo4f/bNei7ghlA469txDvXJYDTkxFk89Yo4f/bNei7ghlccwfxmPObDfTPiiklxp81sLezacQnsxXEO8cl5LaeSeijpxDh/7NtYMubJeH+/znUx9s1pcf6KdijrzHg4zMxnf7/zNj7qxTo4/cl5LenNOjz392Ay8Np9Luj3cjHw3GA49/dhM+zcbX/YhDYr5Np9POvcZ3+/8zY+6sV5KOvBYCSn9Th/9cR1KePHZjD2ii4Gp8l6OffHfTmn9Th/6MdwKOnNZ3+/8zYu4MZnOKvheTzizUAv5Mt/NOvPNnGn23Ez9s06HunHYTnXzXcy4sZ9KezHen+pimc469txc9fNdzL3zH0z4oo4f/bNei7ghls/7813KdHadT7uwXo6p4Q2LuDGZzir+2Ev48l3ONHadT7uwXo6p4Q2LuDGZzir+2Q899txDvXJYDTkxFk89Yo4f/bNei7ghlky8cF7M9HadT7uwXo6p4Q2LuDGZzir7HEz9s1HLeTcfTzp5XUtp4Q2LuDGZzir61UZ0dp1Pu7Bejqn9Th/4NBkNPfNQDTozUcp5MVkf7/GYTHphDY09uR7PuTENmfjyXgu4NU4JqfKYTPhxHEU4ds2Z96KNgCpimI898F1M/HbNmfeincy6MVhM+zcbX/YhDYt6clgO+raeS6nkk9/7Mdnf9iENjDqzGEx4Ns2Z96KZzjr23FzzMV1OuD8Zjzmw30z4oo4f/bNei7ghlcx6t1wD+DLezrrwWA06sY2cafbcTP2zToP4Mt7L+HBejqnhDYu4MZnOKvndjfgy2AJ98l3NuzGc3+pimc469txc9bdZjvky3EJ98l3NuzGc3+pimc469txc9bYdS/2zUct5Nx9POnldS2nhDYu4MZnOKvleynsx3oJ98l3NuzGc3+pimc469txc8HNei7g+2Q88cF1McjJZH+pimc469txc8bpUAn3yXc27MZzf9iENjj92H0v4Px9MOD7YDzo2DZn6914MamKfS7Jx3c86YouO+TEZzj49WkSI2M48hCn8PXdlAW8gkVUod0xa+37dOiHJxzEZnb9Yo3mYzP6LHO7eF7u11thk3qJcxk7MRjQFuOc+9AjiOyoEoW+vErOoVFolgphuBc4A2Q05Nd1hEFpx/3xG0ZbuQS5+Uo0hNtfZAiKmM+1XFy9KD3wXluPLXmrZC916jAjwZgp2p0nbsiJEvj57xlXrA7F+IRuCMrgMMav+zdcrMuUAN/8ANbYqXlj6T86dgZqSmkI22nX6P1lYbGJTb0YkvMPDLYaBK5TPfzqnZkb6m647L82gb7nzVCPvLOucFjVAjMG0kwF2xBJ+aEIFbNUBsLN3Dq8YPT4n0I5+SwUXYWo (此 key 为 EasyAR 申请 名字和 key 要对应)

因购买 EASY AR 使用 unity 中的即可 无需替换

8.Player-->publishing Settings-->build 下的都勾选 9.MyCamera-->GPS 勾选

版本更新

1.修改 yaml 中的版本号 2.修改 Android/app/build.gradle 中的版本号 versionName versionCode 3.打包将 apk 文件拷贝到服务器上

Flutter 与 Unity 之间的交互说明

核心文件说明

FlutterMainActivity 专注处理 Flutter 相关的逻辑和生命周期 UnityMainActivity 专注处理 Unity 相关的渲染和交互 这种分离使得代码更清晰,维护更容易

1. FlutterMainActivity.kt

这是 Flutter 应用的主 Activity 文件,主要功能包括:

  • 负责 Flutter 和 Unity 之间的桥接通信
  • 管理 Unity 的初始化和启动
  • 处理权限请求和结果
  • 提供方法通道(MethodChannel)供 Flutter 调用原生方法
  • 管理位置服务的生命周期
  • 处理 Unity 活动的返回结果

主要方法:

  • configureFlutterEngine: 配置 Flutter 引擎和方法通道
  • startUnityActivity: 启动 Unity 活动
  • checkAndRequestPermissions: 检查和请求必要权限
  • cleanupLocationService: 清理位置服务资源

2. UnityMainActivity.kt

这是 Unity 应用的主 Activity 文件,主要功能包括:

  • 继承自 UnityPlayerActivity负责 Unity 内容的显示和控制
  • 管理 Unity 播放器的生命周期
  • 处理 Unity 和 Flutter 之间的数据传递
  • 提供 Unity 返回 Flutter 的机制
  • 处理 Unity 资源的清理和释放

主要方法:

  • onCreate: 初始化 Unity 环境和方法通道
  • setupMethodChannel: 设置与 Flutter 通信的方法通道
  • handleExitUnity: 处理 Unity 退出逻辑
  • onBackPressed: 处理返回按键事件

交互流程

  1. Flutter 通过 MethodChannel 调用 FlutterMainActivity 中的方法
  2. FlutterMainActivity 处理请求并启动 UnityMainActivity
  3. UnityMainActivity 加载 Unity 内容并处理 Unity 相关的操作
  4. Unity 操作完成后,通过 UnityMainActivity 返回结果给 FlutterMainActivity
  5. FlutterMainActivity 将结果通过 MethodChannel 传回 Flutter

注意事项

  • 两个 Activity 之间的通信需要严格管理生命周期
  • Unity 资源的加载和释放需要合理处理,避免内存泄漏
  • 权限请求和结果处理需要完整的错误处理机制
  • 位置服务的启动和停止需要在合适的时机进行
  • Activity 切换时需要确保资源的正确释放和重新初始化

iOS 与 Unity 集成指南

iOS 核心文件说明

与 Android 平台的 Activity 分离不同iOS 使用委托模式处理 Unity 与 Flutter 的集成。

1. AppDelegate.swift

这是 iOS 应用的主委托文件,相当于 Android 的 FlutterMainActivity功能包括

  • 应用程序入口点
  • 注册 Flutter 插件和 Unity 插件
  • 初始化 Unity 框架
  • 设置消息通道
  • 管理应用生命周期

主要方法:

  • application(_:didFinishLaunchingWithOptions:): 应用启动初始化
  • initUnityFramework: 初始化 Unity 框架
  • registerUnityViewFactory: 注册 Unity 视图工厂
  • setupUnityMessageHandlers: 设置 Unity 消息处理器

2. UnityPlugin.swift

作为 Flutter 和 Unity 之间的桥接器,相当于 Android 的 UnityMainActivity 的部分功能:

  • 处理来自 Flutter 的方法调用
  • 管理 Unity 框架的初始化与关闭
  • 处理 Unity 场景的加载
  • 发送消息到 Unity

主要方法:

  • handle(_:result:): 处理 Flutter 的方法调用
  • initializeUnity: 初始化 Unity
  • startUnity: 启动 Unity
  • loadUnityScene: 加载 Unity 场景
  • closeUnity: 关闭 Unity

3. UnityFrameworkLoader.swift

负责加载 Unity 框架的辅助类:

  • 查找和加载 UnityFramework
  • 初始化 Unity 运行环境

4. UnityViewFactory.swift

用于创建和管理 Unity 视图:

  • 创建 Flutter 平台视图
  • 管理 Unity 视图控制器
  • 处理视图的生命周期

5. AppDelegate+Unity.swift

AppDelegate 的扩展,处理 Unity 回调:

  • 接收 Unity 消息
  • 处理 Unity 返回按钮事件
  • 管理 Unity 关闭事件

iOS 与 Unity 集成配置

Podfile 配置

platform :ios, '12.0'
use_frameworks!  # 使用动态框架

target 'Runner' do
  # Flutter Pods
  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))

  # Unity集成
  pod 'UnityLibrary', :path => 'UnityLibrary'
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    # 框架设置
    target.build_configurations.each do |config|
      config.build_settings['ENABLE_BITCODE'] = 'NO'

      # Unity特定设置
      if target.name == 'UnityLibrary'
        config.build_settings['UNITY_RUNTIME_VERSION'] = '2021.3.33f1fc'
        config.build_settings['UNITY_IOS_EXPORT_PATH'] = '${SRCROOT}/UnityLibrary'
      end
    end
  end
end

Unity 导出设置iOS

  1. 在 Unity 中选择File > Build Settings > iOS
  2. 配置项:
    • 确保Export Project被勾选
    • 脚本后端选择IL2CPP
    • 勾选Development Build用于调试
    • 目标架构选择ARM64
    • Player Settings > Other Settings中:
      • 设置 Bundle Identifier: com.example.arTourismFlutterUnity
      • 最低 iOS 版本: 12.0
      • 设置必要的权限(Camera, Location 等)
  3. 导出项目后,将整个导出的 Unity-iPhone 项目复制到 Flutter 项目的ios/UnityLibrary目录

Info.plist 配置

确保 Info.plist 文件包含所有必要的权限描述:

<!-- 相机权限 -->
<key>NSCameraUsageDescription</key>
<string>此应用需要使用相机进行AR体验</string>

<!-- 相册权限 -->
<key>NSPhotoLibraryUsageDescription</key>
<string>需要相册权限用于保存和选择媒体</string>

<!-- 麦克风权限 -->
<key>NSMicrophoneUsageDescription</key>
<string>此应用需要访问您的麦克风以提供录像服务</string>

<!-- 定位权限 -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>此应用需要访问您的定位以提供导航服务</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>App需要您的同意,才能始终访问位置</string>

跨平台数据交互

Unity 与 Flutter 之间通过 MethodChannel 进行数据交互:

// 在Flutter中
static const platform = MethodChannel('com.example.ar_tourism_flutter_unity.unity');

// 调用Unity方法
await platform.invokeMethod('start_unity', {
  'token': userToken,
  'sceneName': 'Main',
  'returnToHome': true
});

// 接收Unity消息
platform.setMethodCallHandler((call) async {
  switch (call.method) {
    case 'onUnityMessage':
      // 处理来自Unity的消息
      break;
    case 'onUnityBackPressed':
      // 处理Unity返回事件
      break;
  }
});

iOS 打包流程

  1. 更新版本号:
    • pubspec.yaml中更新版本号
    • 在 Xcode 中更新版本号和构建号
  2. 配置签名和证书:
    • 在 Xcode 中配置正确的签名证书和配置文件
  3. 构建和归档:
    flutter build ios --release
    
    然后在 Xcode 中进行归档和上传到 App Store

注意事项

  1. 内存管理iOS 系统内存限制较严格,需确保 Unity 资源及时释放
  2. Framework 路径:确保 UnityFramework.framework 在正确的路径并被正确引用
  3. 权限处理:提前在 Info.plist 中配置所有必要权限
  4. Bitcode 禁用Unity 不支持 Bitcode需在项目配置中禁用
  5. 架构兼容:确保所有库使用兼容的架构(推荐仅使用 ARM64

iOS

包名com.example.arTourismFlutterUnity
打开 Xcode 项目: Apply to README.md Run 在 Xcode 中,右键点击项目导航器中的项目根目录 选择"Add Files to 'Runner'..." 导航到项目的 ios/UnityLibrary 目录 确保选中"Create folder references"(创建文件夹引用)选项 点击"Add"按钮