I want to build an app where I have to use MediaProjectionManager in a Service. But I can not solve it as 'startActivityForResult' can't use in Service class.

- 19,824
- 17
- 99
- 186

- 526
- 1
- 6
- 21
-
2You would need to have an activity where the user can indicate that they want you to start recording screenshots or screencasts, and from there you can use `startActivityForResult()`. I am not aware of any means to request a `MediaProjection` that does not involve `startActivityForResult()`. – CommonsWare Sep 03 '15 at 17:04
-
I have to take screenshot for some specific apps. So i have to detect apps from a service and have to take screenshot using MediaProjection. Please give an example if you can. I am a beginner. Thanks – fahad_sust Sep 03 '15 at 17:17
-
1What you want is not really possible. The user has to be involved at the time of starting the recording. Also, Google has been progressively locking down the ability to detect what app is in the foreground. At this point (Android 6.0), it's safe to say that if one app can determine what other app is in the foreground, that there is a security flaw that needs to be fixed. – CommonsWare Sep 03 '15 at 17:22
-
Actually the user only has to be involved to say yes to granting the security token when Android prompts. If the user trusts the app "don't ask me again" will give the app the ability to get tokens at will. I have an app the does similar, and when the target app isn't in the foreground, it releases the token, then re requests it when the target app comes back in focus. I did it this way because if I was a user of the app, I would want to know it's only actively monitoring the screen when I want it too. – netsplit Sep 29 '15 at 15:58
3 Answers
I really want to do this from a service, which is how I found this question. This is the closest I've came up, so just throwing this out there, till a better answer comes along. Here's a way to do it from an activity that's almost like doing it from a service:
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();
}
}
}
Then in your service when ever you need permission call
private void openMainActivity() {
Intent mainIntent = new Intent(getContext(), MainActivity.class);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(mainIntent);
}
To make the activity invisible in your AndroidManifest.xml
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoDisplay"
android:excludeFromRecents="true"
android:screenOrientation="portrait">
</activity>
Caveats:
For a brief second the application you're screenshooting will lose focus.
For a brief second your app will be the foreground app, so don't trip over your own shoelaces

- 1,070
- 1
- 10
- 18
-
2To avoid the brief second problems, @netsplit 's other question/answer might work http://stackoverflow.com/questions/33398211/how-do-i-get-a-media-projection-manager-without-disturbing-the-current-foregroun – Eric Farng Nov 19 '16 at 12:38
I have used same approach as here https://medium.com/@debuggingisfun/android-10-audio-capture-77dd8e9070f9
in my 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);
}
Service itself is just some boilerplate, the notification is required if you want to run in foreground
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
}
}
I am not an android expert and I am using Flutter - apperantly you also need to create a notification channel first - here is my code for Flutter Application - it's probably similar with non-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)
}
}
}
If you use application, you should change it in manifest - in my case:
<application
android:name=".StreaminkApplication"

- 1,169
- 1
- 19
- 44
Ok, I have managed to do this its not the cleanest of ways but works:
- Local Bound Service: Make your Service a Local Bound Service, which means your service will pass a reference of itself to the the Main Activity.
- Pass an Instance of the Activity to the Service : Pass the reference of your activity to the service in the Service Connection-> onServiceConnected() in the Activity class
- Call the startActivityForResult: Use the Activity Instance in your service to Call the startActivityForResult function.
Note: Upon being called the startActivityForResult will be caught in the onActivityResult() in the Activity Class. You will need to override this function in the Activity and use the service reference to return back to the service class. Also you can unbind the Activity, from the service upon completion.
I hope this makes sense, sorry for not including any code. If you have any questions ill be glad to help you in further detail.

- 9
- 2
-
2that is only if the the activity is still running. a service can run even when there is no activity – Jack Smother Jan 10 '18 at 17:03