看那APP
Go to file
2025-05-15 09:37:32 +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无法找到UnityLibrary 2025-05-15 09:37:32 +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 first commit 2025-05-14 17:04:13 +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集成unity 2025-05-14 18:24:12 +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