Unity C#安卓应用OTG连接Arduino串口通信权限问题求助
问题
Unity开发的Arduino串口通信游戏在Windows、Linux平台可正常运行,但在Android上报错:
Error Unity IOException: Permission denied
Error Unity Rethrow as UnauthorizedAccessException: Access to the path '/dev' is denied.
已尝试添加自定义AndroidManifest.xml并添加权限,但未解决问题:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" xmlns:tools="http://schemas.android.com/tools"> <!--ADDED THESE PERMISSIONS: START--> <uses-permission android:name="android.permission.MANAGE_USB" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-feature android:name="android.hardware.usb.host" android:required="true" /> <!--ADDED THESE PERMISSIONS: END--> <application> <activity android:name="com.unity3d.player.UnityPlayerActivity" android:theme="@style/UnityThemeSelector"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="unityplayer.UnityActivity" android:value="true" /> </activity> </application> </manifest> 现希望无需开发Java/Kotlin插件,找到最简的权限获取及串口通信解决方案。 # 最简解决方案 - **补充权限并动态申请** Android 6.0及以上版本需要动态申请危险权限,除Manifest中已添加的权限,需额外添加存储权限(部分设备访问/dev下串口依赖此权限): ```xml <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
同时在C#脚本中动态申请权限,并触发USB设备授权弹窗:
using UnityEngine; using UnityEngine.Android; public class USBPermissionHandler : MonoBehaviour { void Start() { // 申请存储权限 if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageRead)) Permission.RequestUserPermission(Permission.ExternalStorageRead); if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite)) Permission.RequestUserPermission(Permission.ExternalStorageWrite); // 请求USB设备权限 RequestArduinoUSBPermission(); } void RequestArduinoUSBPermission() { AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); AndroidJavaObject usbManager = currentActivity.Call<AndroidJavaObject>("getSystemService", "usb"); // 获取已连接的USB设备列表,筛选Arduino设备(需替换为对应VID/PID) AndroidJavaObject deviceList = usbManager.Call<AndroidJavaObject>("getDeviceList"); AndroidJavaObject iterator = deviceList.Call<AndroidJavaObject>("entrySet").Call<AndroidJavaObject>("iterator"); while (iterator.Call<bool>("hasNext")) { AndroidJavaObject entry = iterator.Call<AndroidJavaObject>("next"); AndroidJavaObject device = entry.Call<AndroidJavaObject>("getValue"); int vid = device.Call<int>("getVendorId"); int pid = device.Call<int>("getProductId"); // 匹配Arduino Uno的VID/PID,其他型号需修改对应值 if (vid == 0x2341 && pid == 0x0043) { AndroidJavaClass usbManagerClass = new AndroidJavaClass("android.hardware.usb.UsbManager"); string permissionIntentAction = usbManagerClass.GetStatic<string>("ACTION_USB_DEVICE_ATTACHED"); AndroidJavaObject permissionIntent = new AndroidJavaObject("android.content.Intent", permissionIntentAction); permissionIntent.Call<AndroidJavaObject>("putExtra", usbManagerClass.GetStatic<string>("EXTRA_DEVICE"), device); currentActivity.Call("startActivityForResult", permissionIntent, 1); break; } } } }
跳过/dev遍历,直接指定常见Arduino串口路径
Android下Arduino串口通常为/dev/ttyUSB0或/dev/ttyACM0,直接尝试连接这两个路径,避免因遍历/dev目录触发权限拒绝:using System.IO.Ports; public class ArduinoSerial : MonoBehaviour { void ConnectToArduino() { string[] targetPorts = { "/dev/ttyUSB0", "/dev/ttyACM0" }; SerialPort activePort = null; foreach (string port in targetPorts) { try { activePort = new SerialPort(port, 9600); activePort.Open(); Debug.Log($"Successfully connected to {port}"); break; } catch (System.Exception e) { Debug.Log($"Failed to open {port}: {e.Message}"); activePort = null; } } // 使用activePort进行后续通信 } }使用现成Unity串口插件
直接导入Unity Asset Store中的成熟串口插件(如Serial Port Utility for Android),这类插件已封装好权限申请、设备检测和通信逻辑,无需编写Java/Kotlin代码,调用插件API即可快速实现功能。
内容的提问来源于stack exchange,提问作者Aarat Satsangi
相关产品推荐
相关产品推荐

