Android Service中使用MediaProjection截图触发SecurityException错误的排查求助
Android Service中使用MediaProjection截图触发SecurityException错误的排查求助
各位大佬好,我最近在做一个Android截图功能,打算通过MediaProjection配合Service实现,同时还要做一个能悬浮在其他App之上的Composable组件。我已经在AndroidManifest.xml里把Service的类型设置成了mediaProjection,并且是在Service中调用的MediaProjection,但还是触发了SecurityException,具体错误日志如下:
FATAL EXCEPTION: main Process: com.example.misinfo, PID: 8668 java.lang.RuntimeException: Unable to start service com.example.misinfo.floatingWindow.FloatingWindowService@9122dd6 with Intent { cmp=com.example.misinfo/.floatingWindow.FloatingWindowService (has extras) }: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4703) at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2181) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7898) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936) Caused by: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION at android.os.Parcel.createExceptionOrNull(Parcel.java:3011) at android.os.Parcel.createException(Parcel.java:2995) at android.os.Parcel.readException(Parcel.java:2978) at android.os.Parcel.readException(Parcel.java:2920) at android.media.projection.IMediaProjection$Stub$Proxy.start(IMediaProjection.java:268) at android.media.projection.MediaProjection.<init>(MediaProjection.java:63) at android.media.projection.MediaProjectionManager.getMediaProjection(MediaProjectionManager.java:134) at com.example.misinfo.floatingWindow.FloatingWindowService.onStartCommand(FloatingWindowService.kt:28) at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4685) at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2181) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7898) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936) Caused by: android.os.RemoteException: Remote stack trace: at com.android.server.media.projection.MediaProjectionManagerService$MediaProjection.start(MediaProjectionManagerService.java:506) at android.media.projection.IMediaProjection$Stub.onTransact(IMediaProjection.java:163) at android.os.Binder.execTransactInternal(Binder.java:1280) at android.os.Binder.execTransact(Binder.java:1244)
相关代码
MainActivity.kt
class MainActivity : ComponentActivity() { private val TAG = "MainActivity" private val REQUEST_MEDIA_PROJECTION = 1 private val mediaProjectionManager: MediaProjectionManager by lazy { application.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MisInfoTheme { Column( Modifier .fillMaxSize() .padding(16.dp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Button(onClick = { startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION); }) { Text(text = "Floating Widget") } } } } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (requestCode != REQUEST_MEDIA_PROJECTION) { Log.e(TAG, "Unknown request code: $requestCode") return } if (resultCode == RESULT_OK) { startRecordingService(resultCode, data!!) } else { Toast.makeText(this, "Screen Cast Permission Denied", Toast.LENGTH_SHORT).show() return } super.onActivityResult(requestCode, resultCode, data) } private fun startRecordingService(resultCode: Int, data: Intent) { val intent: Intent = FloatingWindowService.newIntent(this, resultCode, data) startService(intent) } }
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MisInfo" tools:targetApi="31"> <service android:name=".floatingWindow.FloatingWindowService" android:enabled="true" android:foregroundServiceType="mediaProjection" android:exported="false"/> <activity android:name=".MainActivity" android:exported="true" android:supportsPictureInPicture="true" android:theme="@style/Theme.MisInfo"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="android.app.lib_name" android:value="" /> </activity> </application> </manifest>
FloatingWindowService.kt
class FloatingWindowService : Service() { private val TAG = "FloatingWindowService" private var resultCode = 0 private var data: Intent? = null override fun onBind(intent: Intent): IBinder? = null @RequiresApi(Build.VERSION_CODES.Q) override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { resultCode = intent!!.getIntExtra(EXTRA_RESULT_CODE, 1337); data = intent.getParcelableExtra(EXTRA_DATA); val mMediaProjectionManager = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager // 这里触发了错误! val mediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data!!) return super.onStartCommand(intent, flags, startId) } companion object { val EXTRA_RESULT_CODE = "resultcode" val EXTRA_DATA = "data" fun newIntent(context: Context, resultCode: Int, data: Intent): Intent { val intent = Intent(context, FloatingWindowService::class.java) intent.putExtra(EXTRA_RESULT_CODE, resultCode) intent.putExtra(EXTRA_DATA, data) return intent } } }
我的需求是实现一个能悬浮在其他App之上的Composable组件,同时通过这个Service获取MediaProjection来完成截图功能。为了方便大家复现问题,我只重点贴出了触发错误的Service相关代码,麻烦各位帮忙看看问题到底出在哪,怎么解决这个SecurityException?
备注:内容来源于stack exchange,提问作者masinnlos
相关产品推荐
相关产品推荐

