You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 09:52:44