Unity插件AAR文件报AndroidJavaException:ContextCompat类未找到
可能导致蓝牙权限请求失败的配置问题排查
针对你遇到的适配Unity的安卓蓝牙插件权限请求失败问题,结合你的配置和操作,从以下几个方向排查:
1. 权限声明不完整或不符合Android 12+规则
你的插件minSdk和targetSdk都是31+(Android 12+),蓝牙权限体系已更新,必须在AndroidManifest.xml中声明对应权限,否则权限请求会直接失败:
<!-- Android 12+ 核心蓝牙权限 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- 若需扫描未配对设备,必须添加位置权限 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- 兼容Android 11及以下版本 --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" /> <!-- 声明蓝牙硬件依赖 --> <uses-feature android:name="android.hardware.bluetooth" android:required="true" />
注意:如果扫描不需要关联位置信息,可给BLUETOOTH_SCAN添加android:usesPermissionFlags="neverForLocation"属性,避免请求位置权限。
2. AndroidX依赖未正确打包进插件
gson用本地jar解决了依赖问题,但AndroidX的core和appcompat是多模块依赖,手动引入单个jar会缺失关联类(比如权限请求必须的ActivityResultContracts类)。解决方法:
- 使用fat-aar插件将所有依赖打包进最终的aar:
- 在项目根目录的
build.gradle中添加插件依赖:buildscript { dependencies { classpath 'com.kezong:fat-aar:1.3.8' } } - 在插件模块的
build.gradle中应用插件,并将implementation改为embed:plugins { id 'com.android.library' id 'com.kezong.fat-aar' } dependencies { embed 'com.google.code.gson:gson:2.10.1' embed 'androidx.core:core:1.12.0' embed 'androidx.appcompat:appcompat:1.6.1' embed 'com.google.android.material:material:1.2.0' // 测试依赖保持不变 testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' }
- 在项目根目录的
3. 权限请求逻辑不符合Android 12+规范
Android 12+废弃了旧的requestPermissions方法,必须使用ActivityResultContracts来请求权限,否则请求流程会失效。示例代码:
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AppCompatActivity; import android.Manifest; import android.os.Build; import android.widget.Toast; import android.os.Bundle; public class BluetoothPlugin extends AppCompatActivity { private ActivityResultLauncher<String[]> permissionLauncher; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 初始化权限请求Launcher permissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> { boolean allGranted = true; for (Boolean granted : result.values()) { if (!granted) { allGranted = false; break; } } if (allGranted) { // 权限全部授予,初始化蓝牙功能 initBluetooth(); } else { Toast.makeText(this, "需要蓝牙权限才能使用功能", Toast.LENGTH_SHORT).show(); } }); } // 供Unity调用的权限请求方法 public void requestBluetoothPermissions() { String[] permissions; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { permissions = new String[]{ Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.ACCESS_FINE_LOCATION // 按需添加 }; } else { permissions = new String[]{ Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.ACCESS_FINE_LOCATION }; } permissionLauncher.launch(permissions); } private void initBluetooth() { // 初始化蓝牙逻辑 } }
4. Unity侧配置冲突
- 确保Unity的Player Settings中,
Minimum API Level和Target API Level与插件一致(31和33)。 - 勾选
Custom Main Manifest,将插件的权限声明复制到Unity生成的AndroidManifest.xml中,避免Unity覆盖权限配置。 - 检查Unity的gradle配置:在
Project Settings > Player > Android > Publishing Settings中勾选Custom Gradle Template,确认gradleTemplate.properties中android.useAndroidX=true和android.enableJetifier=true已开启。
5. 权限请求时机错误
避免在插件初始化阶段自动请求权限,因为Unity的Activity此时可能未完全初始化。正确做法是:在Unity中调用插件的requestBluetoothPermissions方法,触发权限请求,确保Activity处于活跃状态。
内容的提问来源于stack exchange,提问作者Dan Tonks
相关产品推荐
相关产品推荐

