使用MediaProjection截取服务的屏幕截图。

huangapple go评论78阅读模式
英文:

Take a screenshot from a service using MediaProjection

问题

以下是您提供的代码的翻译部分:

  1. 我正在尝试使用MediaProjection从一个服务中获取屏幕截图。尽管在`AndroidManifest.xml`中将我的服务类型定义为mediaprojection,并在服务中运行mediaProjection,但我收到以下错误:
  2. FATAL EXCEPTION: main
  3. Process: com.example.misinfo, PID: 8668
  4. 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的前台服务
  5. android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4703)
  6. ...
  7. MainActivity.kt
  8. class MainActivity : ComponentActivity() {
  9. private val TAG = "MainActivity"
  10. private val REQUEST_MEDIA_PROJECTION = 1
  11. ...
  12. AndroidManifest.xml
  13. <?xml version="1.0" encoding="utf-8"?>
  14. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  15. xmlns:tools="http://schemas.android.com/tools">
  16. <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
  17. ...
  18. FloatingWindowService.kt
  19. class FloatingWindowService : Service() {
  20. private val TAG = "FloatingWindowService"
  21. ...

希望这有助于您理解代码的结构和问题。如果您有任何进一步的问题,请随时提出。

英文:

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:

  1. FATAL EXCEPTION: main
  2. Process: com.example.misinfo, PID: 8668
  3. 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
  4. at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4703)
  5. at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(Unknown Source:0)
  6. at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2181)
  7. at android.os.Handler.dispatchMessage(Handler.java:106)
  8. at android.os.Looper.loopOnce(Looper.java:201)
  9. at android.os.Looper.loop(Looper.java:288)
  10. at android.app.ActivityThread.main(ActivityThread.java:7898)
  11. at java.lang.reflect.Method.invoke(Native Method)
  12. at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
  13. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
  14. Caused by: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
  15. at android.os.Parcel.createExceptionOrNull(Parcel.java:3011)
  16. at android.os.Parcel.createException(Parcel.java:2995)
  17. at android.os.Parcel.readException(Parcel.java:2978)
  18. at android.os.Parcel.readException(Parcel.java:2920)
  19. at android.media.projection.IMediaProjection$Stub$Proxy.start(IMediaProjection.java:268)
  20. at android.media.projection.MediaProjection.&lt;init&gt;(MediaProjection.java:63)
  21. at android.media.projection.MediaProjectionManager.getMediaProjection(MediaProjectionManager.java:134)
  22. at com.example.misinfo.floatingWindow.FloatingWindowService.onStartCommand(FloatingWindowService.kt:28)
  23. at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4685)
  24. at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(Unknown Source:0)&#160;
  25. at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2181)&#160;
  26. at android.os.Handler.dispatchMessage(Handler.java:106)&#160;
  27. at android.os.Looper.loopOnce(Looper.java:201)&#160;
  28. at android.os.Looper.loop(Looper.java:288)&#160;
  29. at android.app.ActivityThread.main(ActivityThread.java:7898)&#160;
  30. at java.lang.reflect.Method.invoke(Native Method)&#160;
  31. at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)&#160;
  32. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)&#160;
  33. Caused by: android.os.RemoteException: Remote stack trace:
  34. at com.android.server.media.projection.MediaProjectionManagerService$MediaProjection.start(MediaProjectionManagerService.java:506)
  35. at android.media.projection.IMediaProjection$Stub.onTransact(IMediaProjection.java:163)
  36. at android.os.Binder.execTransactInternal(Binder.java:1280)
  37. at android.os.Binder.execTransact(Binder.java:1244)

MainActivity.kt

  1. class MainActivity : ComponentActivity() {
  2. private val TAG = &quot;MainActivity&quot;
  3. private val REQUEST_MEDIA_PROJECTION = 1
  4. private val mediaProjectionManager: MediaProjectionManager by lazy {
  5. application.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
  6. }
  7. override fun onCreate(savedInstanceState: Bundle?) {
  8. super.onCreate(savedInstanceState)
  9. setContent {
  10. MisInfoTheme {
  11. Column(
  12. Modifier
  13. .fillMaxSize()
  14. .padding(16.dp),
  15. verticalArrangement = Arrangement.Center,
  16. horizontalAlignment = Alignment.CenterHorizontally
  17. ) {
  18. Button(onClick = {
  19. startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
  20. }) {
  21. Text(text = &quot;Floating Widget&quot;)
  22. }
  23. }
  24. }
  25. }
  26. }
  27. override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
  28. if (requestCode != REQUEST_MEDIA_PROJECTION) {
  29. Log.e(TAG, &quot;Unknown request code: $requestCode&quot;)
  30. return
  31. }
  32. if (resultCode == RESULT_OK) {
  33. startRecordingService(resultCode, data!!)
  34. } else {
  35. Toast.makeText(this, &quot;Screen Cast Permission Denied&quot;, Toast.LENGTH_SHORT).show()
  36. return
  37. }
  38. super.onActivityResult(requestCode, resultCode, data)
  39. }
  40. private fun startRecordingService(resultCode: Int, data: Intent) {
  41. val intent: Intent = FloatingWindowService.newIntent(this, resultCode, data)
  42. startService(intent)
  43. }
  44. }

AndroidManifest.xml

  1. &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  2. &lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
  3. xmlns:tools=&quot;http://schemas.android.com/tools&quot;&gt;
  4. &lt;uses-permission android:name=&quot;android.permission.SYSTEM_ALERT_WINDOW&quot;/&gt;
  5. &lt;uses-permission android:name=&quot;android.permission.MANAGE_EXTERNAL_STORAGE&quot;
  6. tools:ignore=&quot;ScopedStorage&quot; /&gt;
  7. &lt;uses-permission android:name=&quot;android.permission.FOREGROUND_SERVICE&quot; /&gt;
  8. &lt;application
  9. android:allowBackup=&quot;true&quot;
  10. android:dataExtractionRules=&quot;@xml/data_extraction_rules&quot;
  11. android:fullBackupContent=&quot;@xml/backup_rules&quot;
  12. android:icon=&quot;@mipmap/ic_launcher&quot;
  13. android:label=&quot;@string/app_name&quot;
  14. android:roundIcon=&quot;@mipmap/ic_launcher_round&quot;
  15. android:supportsRtl=&quot;true&quot;
  16. android:theme=&quot;@style/Theme.MisInfo&quot;
  17. tools:targetApi=&quot;31&quot;&gt;
  18. &lt;service
  19. android:name=&quot;.floatingWindow.FloatingWindowService&quot;
  20. android:enabled=&quot;true&quot;
  21. android:foregroundServiceType=&quot;mediaProjection&quot;
  22. android:exported=&quot;false&quot;/&gt;
  23. &lt;activity
  24. android:name=&quot;.MainActivity&quot;
  25. android:exported=&quot;true&quot;
  26. android:supportsPictureInPicture=&quot;true&quot;
  27. android:theme=&quot;@style/Theme.MisInfo&quot;&gt;
  28. &lt;intent-filter&gt;
  29. &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
  30. &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;
  31. &lt;/intent-filter&gt;
  32. &lt;meta-data
  33. android:name=&quot;android.app.lib_name&quot;
  34. android:value=&quot;&quot; /&gt;
  35. &lt;/activity&gt;
  36. &lt;/application&gt;
  37. &lt;/manifest&gt;

FloatingWindowService.kt

  1. class FloatingWindowService : Service() {
  2. private val TAG = &quot;FloatingWindowService&quot;
  3. private var resultCode = 0
  4. private var data: Intent? = null
  5. override fun onBind(intent: Intent): IBinder? = null
  6. @RequiresApi(Build.VERSION_CODES.Q)
  7. override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
  8. resultCode = intent!!.getIntExtra(EXTRA_RESULT_CODE, 1337);
  9. data = intent.getParcelableExtra(EXTRA_DATA);
  10. val mMediaProjectionManager = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
  11. //here i get the error!
  12. val mediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data!!)
  13. return super.onStartCommand(intent, flags, startId)
  14. }
  15. companion object {
  16. val EXTRA_RESULT_CODE = &quot;resultcode&quot;
  17. val EXTRA_DATA = &quot;data&quot;
  18. fun newIntent(context: Context, resultCode: Int, data: Intent): Intent {
  19. val intent = Intent(context, FloatingWindowService::class.java)
  20. intent.putExtra(EXTRA_RESULT_CODE, resultCode)
  21. intent.putExtra(EXTRA_DATA, data)
  22. return intent
  23. }
  24. }
  25. }

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.

  1. private fun initRunningTipNotification() {
  2. val builder = Notification.Builder(this, "running")
  3. builder.setContentText("运行通知")
  4. .setSmallIcon(R.drawable.ic_launcher_foreground)
  5. notificationManager =
  6. getSystemService(NOTIFICATION_SERVICE) as NotificationManager
  7. val channel = NotificationChannel(
  8. "running",
  9. "运行通知",
  10. NotificationManager.IMPORTANCE_DEFAULT
  11. )
  12. notificationManager.createNotificationChannel(channel)
  13. builder.setChannelId("running")
  14. startForeground(100, builder.build())
  15. }
  16. @RequiresApi(Build.VERSION_CODES.S)
  17. override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
  18. resultCode = intent!!.getIntExtra(EXTRA_RESULT_CODE, 1);
  19. resultData = intent.getParcelableExtra(EXTRA_DATA);
  20. initRunningTipNotification()
  21. mediaProjection = getMediaProjection()!!
  22. window = FloatingWindow(this, this)
  23. window.drawFloatingWindow()
  24. return super.onStartCommand(intent, flags, startId)
  25. }
英文:

The solution was to add a foreground notification before create MediaProjection instance.

  1. private fun initRunningTipNotification() {
  2. val builder = Notification.Builder(this, &quot;running&quot;)
  3. builder.setContentText(&quot;running notification&quot;)
  4. .setSmallIcon(R.drawable.ic_launcher_foreground)
  5. notificationManager =
  6. getSystemService(NOTIFICATION_SERVICE) as NotificationManager
  7. val channel = NotificationChannel(
  8. &quot;running&quot;,
  9. &quot;running notification&quot;,
  10. NotificationManager.IMPORTANCE_DEFAULT
  11. )
  12. notificationManager.createNotificationChannel(channel)
  13. builder.setChannelId(&quot;running&quot;)
  14. startForeground(100, builder.build())
  15. }
  16. @RequiresApi(Build.VERSION_CODES.S)
  17. override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
  18. resultCode = intent!!.getIntExtra(EXTRA_RESULT_CODE, 1);
  19. resultData = intent.getParcelableExtra(EXTRA_DATA);
  20. initRunningTipNotification()
  21. mediaProjection = getMediaProjection()!!
  22. window = FloatingWindow(this, this)
  23. window.drawFloatingWindow()
  24. return super.onStartCommand(intent, flags, startId)
  25. }

答案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 :

  1. &lt;service android:name=&quot;.floatingWindow.FloatingWindowService&quot;
  2. android:foregroundServiceType=&quot;mediaProjection&quot; /&gt;

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 :

  1. &lt;service android:name=&quot;.floatingWindow.FloatingWindowService&quot;
  2. android:foregroundServiceType=&quot;mediaProjection&quot; /&gt;

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.

huangapple
  • 本文由 发表于 2023年3月20日 23:58:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75792576.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定