Failed resolution of: Landroid/support/v4/content/ContextCompat;
崩溃RTC SDK 对 support/v4
有依赖,是较早的版本,早于 Android X。如果你的工程通过 android.useAndroidX=true
配置,标记 APP 强制使用 AndroidX,那么,可能会导致编译不通过,并有以上报错。
解决方案:在项目根目录的 gradle.properties
文件中添加 android.enableJetifier=true
。
自较早的版本开始,RTC SDK 中都在根目录下,包含名为 proguard-rules.pro
的混淆配置文件。你的 App 集成 RTC SDK 打包时,会自动将此混淆配置加入 App 的混淆配置中。你无需为 RTC SDK 的混淆配置专门添加规则。
对于更早的版本(3.30 及以前),RTC 强烈建议你升级到最新版本。如果您需要混淆配置方面的详细信息,请咨询技术支持。
如果你的应用以 Android 11(API 级别 30)或更高版本为目标平台,且希望在应用退到后台时仍能进行音视频采集,则需启动一个前台服务。
以下说明以麦克风权限为例,摄像头权限同理,具体字段参看前台服务类型。
在 AndroidManifest.xml
文件中声明前台服务类型。
<service android:name="<service dir>.<service file name>" android:foregroundServiceType="microphone" tools:node="merge" />
android.permission.POST_NOTIFICATION
权限。<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
FOREGROUND_SERVICE_MICROPHONE
权限。<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE"/>
继承系统服务,并重载相关的函数,实现服务的启动和停止。
package com.ss.demo.service; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.content.pm.ServiceInfo; import android.os.Build; import android.os.IBinder; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; import com.ss.video.rtc.demo.ui.chat.ChatActivity; public class RoomKeepLifeService extends Service { public static final String CHANNEL_ID = "RoomKeepLifeServiceChannel"; private static final String COMMAND = "command"; private static final String COMMAND_START = "start"; private static final String COMMAND_STOP = "stop"; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); startAsForeground(new Intent()); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if(intent != null){ switch (intent.getStringExtra(COMMAND)){ case COMMAND_START: startAsForeground(intent); break; case COMMAND_STOP: stopInternal(); break; default: break; } } return super.onStartCommand(intent, flags, startId); } public void stopInternal() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { stopForeground(true); stopSelf(); } } private void startAsForeground(Intent intent) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { createNotificationChannel(); Intent notificationIntent = new Intent(this, ChatActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE); Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("房间正在进行中...") .setSmallIcon(com.ss.video.rtc.common.R.drawable.icon_default_avatar) .setContentIntent(pendingIntent) .setShowWhen(false) .build(); startForeground(110, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE); } } private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { NotificationChannel serviceChannel = new NotificationChannel( CHANNEL_ID, "Foreground Service Channel", NotificationManager.IMPORTANCE_DEFAULT ); NotificationManager manager = getSystemService(NotificationManager.class); if (manager != null) { manager.createNotificationChannel(serviceChannel); } } } }
在适当的位置调用服务启动和停止。以进房启动,退房停止为例:
public void joinRoom() { // -- 启动服务 -- // startRoomKeepLifeService(); // -- 进房相关操作 -- // // ... } public void leaveRoom() { // -- 退房相关操作 -- // // ... // -- 停止服务 -- // stopRoomKeepLifeService(); } private void startRoomKeepLifeService() { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){ Intent serviceIntent = new Intent(EnvUtilities.getAppContext(), RoomKeepLifeService.class); serviceIntent.putExtra("command", "start"); ContextCompat.startForegroundService(EnvUtilities.getAppContext(), serviceIntent); } } private void stopRoomKeepLifeService(){ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { Intent serviceIntent = new Intent(EnvUtilities.getAppContext(), RoomKeepLifeService.class); serviceIntent.putExtra("command", "stop"); ContextCompat.startForegroundService(EnvUtilities.getAppContext(), serviceIntent); } }
targetSDKVersion
>= 31 时如何配置蓝牙权限?在 AndroidManifest.xml
文件中配置应用所需的权限。
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
在 Activity 中动态申请 BLUETOOTH_CONNECT 权限。参考以下代码进行申请:
private static final int PERMISSION_REQ_ID_RECORD_AUDIO = 22;// 可以任意值 private static final int PERMISSION_REQ_ID_CAMERA = PERMISSION_REQ_ID_RECORD_AUDIO + 1; private static final int PERMISSION_REQ_ID_BLUETOOTH_CONNECT = PERMISSION_REQ_ID_CAMERA + 1; // Check necessary permissions granted and // if the permissions are not granted, use the built-in Android feature to request them. private boolean checkSelfPermissions() { return checkSelfPermission(Manifest.permission.RECORD_AUDIO, PERMISSION_REQ_ID_RECORD_AUDIO) && checkSelfPermission(Manifest.permission.CAMERA, PERMISSION_REQ_ID_CAMERA) && // If targetSDKVersion >= 31 and want to use bluetooth headset, need request permission. checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT, PERMISSION_REQ_ID_BLUETOOTH_CONNECT); } public boolean checkSelfPermission(String permission, int requestCode) { if (PermissionChecker.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{permission}, requestCode); return false; } return true; }
说明
在项目根目录的 settings.gradle
文件配置 Maven 仓库地址。
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { ... maven { url "https://developer.huawei.com/repo/" } } }
说明
如果你的 Android Gradle Plugin 版本低于 v7.1.0,则应在项目根目录的 build.gradle
文件配置 Maven 仓库地址。
allprojects { repositories { ... maven { url "https://developer.huawei.com/repo/"} ... } }
在 App 的 build.gradle
文件中添加 audiokit 和 gson 依赖。
dependencies { ... implementation "com.huawei.multimedia:audiokit:1.0.3" ... }
推荐使用真机调试,模拟器出现花屏可能是摄像头设置有误或未开放当前设备的摄像头权限。
安卓平台上,RTC 视频超分、视频降噪、暗光增强等视频处理特性在 GPU 上的正常运行依赖厂商提供的 OpenCL 库。根据 Android 开发者指南对 Android 12 的行为变更说明,当应用升级目标平台为 Android 12(targetSdkVersion>=31) 及以上版本后,app 访问设备厂商提供的本地库时,必须使用应用清单 (AndroidManifest.xml) 中的 <uses-native-library>
标记指明其依赖,以免出现帧率下降、视频暗光增强功能无法开启等异常。你可以参考此文档进行适配操作。
升级 Android app 的Android Gradle Plugin 版本到 4.2.0+,确保构建工具链支持 <uses-native-library>
标记。
在应用 AndroidManifest.xml
文件的 <application>
标签下加入 <uses-native-library>
标记,声明以下 OpenCL 相关本地库的白名单(详情参考 Android 开发者指南):
<application> <uses-native-library android:name="libOpenCL.so" android:required="false"/> <uses-native-library android:name="libGLES_mali.so" android:required="false"/> <uses-native-library android:name="libmali.so" android:required="false"/> <uses-native-library android:name="libPVROCL.so" android:required="false"/> <uses-native-library android:name="libpocl.so" android:required="false"/> </application>