英文:
Take a screenshot from a service using MediaProjection
问题
以下是您提供的代码的翻译部分:
我正在尝试使用MediaProjection从一个服务中获取屏幕截图。尽管在`AndroidManifest.xml`中将我的服务类型定义为mediaprojection,并在服务中运行mediaProjection,但我收到以下错误:
FATAL EXCEPTION: main
Process: com.example.misinfo, PID: 8668
java.lang.RuntimeException: 无法启动服务com.example.misinfo.floatingWindow.FloatingWindowService@9122dd6,使用Intent { cmp=com.example.misinfo/.floatingWindow.FloatingWindowService(有附加信息)}:java.lang.SecurityException:媒体投影需要类型为ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION的前台服务
在android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4703)
...
MainActivity.kt
class MainActivity : ComponentActivity() {
private val TAG = "MainActivity"
private val REQUEST_MEDIA_PROJECTION = 1
...
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"/>
...
FloatingWindowService.kt
class FloatingWindowService : Service() {
private val TAG = "FloatingWindowService"
...
希望这有助于您理解代码的结构和问题。如果您有任何进一步的问题,请随时提出。
英文:
I'm trying to take a screenshot from a service using MediaProjection. Despite defining the type of my service as mediaprojection in AndroidManifest.xml
and running mediaProjection in a service I get the following error:
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
//here i get the error!
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
}
}
}
My plan is to have a composable floating over other apps and using the service to getMediaProjection and take a screenshot, to give a reproducable example, I only mention here the service because here I get the error.
答案1
得分: 1
The solution was to add a foreground notification before creating a MediaProjection instance.
private fun initRunningTipNotification() {
val builder = Notification.Builder(this, "running")
builder.setContentText("运行通知")
.setSmallIcon(R.drawable.ic_launcher_foreground)
notificationManager =
getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val channel = NotificationChannel(
"running",
"运行通知",
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel)
builder.setChannelId("running")
startForeground(100, builder.build())
}
@RequiresApi(Build.VERSION_CODES.S)
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
resultCode = intent!!.getIntExtra(EXTRA_RESULT_CODE, 1);
resultData = intent.getParcelableExtra(EXTRA_DATA);
initRunningTipNotification()
mediaProjection = getMediaProjection()!!
window = FloatingWindow(this, this)
window.drawFloatingWindow()
return super.onStartCommand(intent, flags, startId)
}
英文:
The solution was to add a foreground notification before create MediaProjection instance.
private fun initRunningTipNotification() {
val builder = Notification.Builder(this, "running")
builder.setContentText("running notification")
.setSmallIcon(R.drawable.ic_launcher_foreground)
notificationManager =
getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val channel = NotificationChannel(
"running",
"running notification",
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel)
builder.setChannelId("running")
startForeground(100, builder.build())
}
@RequiresApi(Build.VERSION_CODES.S)
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
resultCode = intent!!.getIntExtra(EXTRA_RESULT_CODE, 1);
resultData = intent.getParcelableExtra(EXTRA_DATA);
initRunningTipNotification()
mediaProjection = getMediaProjection()!!
window = FloatingWindow(this, this)
window.drawFloatingWindow()
return super.onStartCommand(intent, flags, startId)
}
答案2
得分: 0
The error indicates the declaration of ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
to use MediaProjection API.
Add the code to your AndroidManifest.xml
:
<service android:name=".floatingWindow.FloatingWindowService"
android:foregroundServiceType="mediaProjection" />
The code is not passing the Context
object to the getSystemService()
. We're passing the null
. The argument gets a Callback
object to receive a status. The null
is the argument.
英文:
The error indicates the declaration of ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
to use MediaProjection API.
Add the code to your AndroidManifest.xml
:
<service android:name=".floatingWindow.FloatingWindowService"
android:foregroundServiceType="mediaProjection" />
The code is not passing the Context
object to the getSystemService()
. We're passing the null
. The argument gets a Callback
object to receive a status. The null
is the argument.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论