在使用TRTC SDK,将targetSdkVersion
设置为30,进行屏幕分享时会出现如下崩溃,这主要是因为谷歌隐私策略导致的,需要启动一个前台的service,并且android:foregroundServiceType="mediaProjection"
才可以解决,具体步骤如下
崩溃堆栈:
代码语言:txt复制 Caused by: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
at android.os.Parcel.createException(Parcel.java:2074)
at android.os.Parcel.readException(Parcel.java:2042)
at android.os.Parcel.readException(Parcel.java:1990)
at android.media.projection.IMediaProjection$Stub$Proxy.start(IMediaProjection.java:231)
at android.media.projection.MediaProjection.<init>(MediaProjection.java:58)
at android.media.projection.MediaProjectionManager.getMediaProjection(MediaProjectionManager.java:104)
at com.tencent.rtmp.video.TXScreenCapture$TXScreenCaptureAssistantActivity.onActivityResult(TXScreenCapture.java:45)
at android.app.Activity.dispatchActivityResult(Activity.java:8249)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4931)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4979)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2044)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7562)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: android.os.RemoteException: Remote stack trace:
at com.android.server.media.projection.MediaProjectionManagerService$MediaProjection.start(MediaProjectionManagerService.java:490)
at android.media.projection.IMediaProjection$Stub.onTransact(IMediaProjection.java:135)
at android.os.Binder.execTransactInternal(Binder.java:1021)
at android.os.Binder.execTransact(Binder.java:994)
解决步骤
第一步
创建一个service ,并绑定一个Notification
使其作为前台service
public class MediaService extends Service {
private final String NOTIFICATION_CHANNEL_ID="com.tencent.trtc.apiexample.MediaService";
private final String NOTIFICATION_CHANNEL_NAME="com.tencent.trtc.apiexample.channel_name";
private final String NOTIFICATION_CHANNEL_DESC="com.tencent.trtc.apiexample.channel_desc";
public MediaService() {
}
@Override
public void onCreate() {
super.onCreate();
startNotification();
}
public void startNotification() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//Call Start foreground with notification
Intent notificationIntent = new Intent(this, MediaService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground))
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Starting Service")
.setContentText("Starting monitoring service")
.setContentIntent(pendingIntent);
Notification notification = notificationBuilder.build();
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(NOTIFICATION_CHANNEL_DESC);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
startForeground(1, notification); //必须使用此方法显示通知,不能使用notificationManager.notify,否则还是会报上面的错误
}
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
}
###第二步
在AndroidManifest.xml中配置
1.加入以下权限
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
2.设置service的type为mediaProjection
<service
android:name=".MediaService"
android:enabled="true"
android:foregroundServiceType="mediaProjection"
android:exported="true"/>
最后一步
在录屏直播前启动service,这里我是在application中启动的,业务上,只需要在录屏前启动即可
代码语言:txt复制public class TRTCApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
startService(new Intent(this,MediaService.class));
}
}
其他
无需再service中做去启动录屏
相关demo:
http://image-duxin.test.upcdn.net/tencent/targetSdkVersion30录屏.zip