Android 服务中的 MediaProjectionManager
Android MediaProjectionManager in Service
我想构建一个必须在服务中使用 MediaProjectionManager 的应用程序。但我无法解决它,因为 'startActivityForResult' 无法在服务 class.
中使用
我真的很想通过服务来做这件事,这就是我发现这个问题的方式。这是我最接近的答案,所以把它扔在那里,直到出现更好的答案。这是一种从 activity 执行此操作的方法,几乎就像从服务中执行此操作一样:
import static your.package.YourClass.mediaProjectionManager;
public class MainActivity extends Activity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(null);
mediaProjectionManager = (MediaProjectionManager)getContext().getSystemService(MEDIA_PROJECTION_SERVICE);
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), 1);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if (resultCode == Activity.RESULT_OK) {
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
this.finish();
}
}
}
然后在您的服务中需要权限时调用
private void openMainActivity() {
Intent mainIntent = new Intent(getContext(), MainActivity.class);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(mainIntent);
}
使 activity 在您的 AndroidManifest.xml
中不可见
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoDisplay"
android:excludeFromRecents="true"
android:screenOrientation="portrait">
</activity>
注意事项:
您正在截屏的应用程序将在短时间内失去焦点。
您的应用将在短时间内成为前台应用,因此请不要被自己的鞋带绊倒
好的,我已经设法做到了这不是最干净的方法,但有效:
- 本地绑定服务:将您的服务设为 Local Bound Service,这意味着您的服务会将自身的引用传递给 Main Activity。
- Pass an Instance of the Activity to the Service : 将你的 activity 的引用传递给 Service Connection-> onServiceConnected( ) 在 Activity class
- Call the startActivityForResult: 使用服务中的Activity实例调用startActivityForResult函数。
注:
在被调用时,startActivityForResult 将在 Activity Class 中的 onActivityResult() 中被捕获。您将需要在 Activity 中覆盖此函数,并使用对 return 的服务引用返回到服务 class。您也可以在完成后从服务中解绑Activity。
我希望这是有道理的,很抱歉没有包含任何代码。如果您有任何问题,我们很乐意为您提供更详细的帮助。
我使用了与此处相同的方法https://medium.com/@debuggingisfun/android-10-audio-capture-77dd8e9070f9
在我的 activity 中:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, MediaProjectionService.class);
startForegroundService(intent);
mProjectionManager =
(MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(mProjectionManager.createScreenCaptureIntent(),
1);
}
服务本身只是一些样板,如果你想在前台运行
需要通知
class MediaProjectionService : Service() {
override fun onCreate() {
super.onCreate()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val builder = NotificationCompat.Builder(this, "messages")
.setContentText("streaming enabled")
.setContentTitle("Stream to e-ink")
startForeground(101, builder.build())
}
}
override fun onBind(intent: Intent): IBinder? {
return null
}
}
我不是 android 专家,我正在使用 Flutter - 显然你还需要先创建一个通知通道 - 这是我的 Flutter 应用程序代码 - 它可能与非 flutter 类似
class StreaminkApplication : FlutterApplication() {
override fun onCreate() {
super.onCreate()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel("messages", "Messages", NotificationManager.IMPORTANCE_LOW)
val manager = getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(channel)
}
}
}
如果您使用应用程序,您应该在清单中更改它 - 在我的例子中:
<application
android:name=".StreaminkApplication"
我想构建一个必须在服务中使用 MediaProjectionManager 的应用程序。但我无法解决它,因为 'startActivityForResult' 无法在服务 class.
中使用我真的很想通过服务来做这件事,这就是我发现这个问题的方式。这是我最接近的答案,所以把它扔在那里,直到出现更好的答案。这是一种从 activity 执行此操作的方法,几乎就像从服务中执行此操作一样:
import static your.package.YourClass.mediaProjectionManager;
public class MainActivity extends Activity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(null);
mediaProjectionManager = (MediaProjectionManager)getContext().getSystemService(MEDIA_PROJECTION_SERVICE);
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), 1);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if (resultCode == Activity.RESULT_OK) {
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
this.finish();
}
}
}
然后在您的服务中需要权限时调用
private void openMainActivity() {
Intent mainIntent = new Intent(getContext(), MainActivity.class);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(mainIntent);
}
使 activity 在您的 AndroidManifest.xml
中不可见 <activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoDisplay"
android:excludeFromRecents="true"
android:screenOrientation="portrait">
</activity>
注意事项:
您正在截屏的应用程序将在短时间内失去焦点。
您的应用将在短时间内成为前台应用,因此请不要被自己的鞋带绊倒
好的,我已经设法做到了这不是最干净的方法,但有效:
- 本地绑定服务:将您的服务设为 Local Bound Service,这意味着您的服务会将自身的引用传递给 Main Activity。
- Pass an Instance of the Activity to the Service : 将你的 activity 的引用传递给 Service Connection-> onServiceConnected( ) 在 Activity class
- Call the startActivityForResult: 使用服务中的Activity实例调用startActivityForResult函数。
注: 在被调用时,startActivityForResult 将在 Activity Class 中的 onActivityResult() 中被捕获。您将需要在 Activity 中覆盖此函数,并使用对 return 的服务引用返回到服务 class。您也可以在完成后从服务中解绑Activity。
我希望这是有道理的,很抱歉没有包含任何代码。如果您有任何问题,我们很乐意为您提供更详细的帮助。
我使用了与此处相同的方法https://medium.com/@debuggingisfun/android-10-audio-capture-77dd8e9070f9
在我的 activity 中:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, MediaProjectionService.class);
startForegroundService(intent);
mProjectionManager =
(MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(mProjectionManager.createScreenCaptureIntent(),
1);
}
服务本身只是一些样板,如果你想在前台运行
需要通知class MediaProjectionService : Service() {
override fun onCreate() {
super.onCreate()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val builder = NotificationCompat.Builder(this, "messages")
.setContentText("streaming enabled")
.setContentTitle("Stream to e-ink")
startForeground(101, builder.build())
}
}
override fun onBind(intent: Intent): IBinder? {
return null
}
}
我不是 android 专家,我正在使用 Flutter - 显然你还需要先创建一个通知通道 - 这是我的 Flutter 应用程序代码 - 它可能与非 flutter 类似
class StreaminkApplication : FlutterApplication() {
override fun onCreate() {
super.onCreate()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel("messages", "Messages", NotificationManager.IMPORTANCE_LOW)
val manager = getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(channel)
}
}
}
如果您使用应用程序,您应该在清单中更改它 - 在我的例子中:
<application
android:name=".StreaminkApplication"