/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media.projection;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.projection.IMediaProjection;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.ArrayMap;
import android.util.Log;

import java.util.Map;

Manages the retrieval of certain types of MediaProjection tokens.
/** * Manages the retrieval of certain types of {@link MediaProjection} tokens. */
@SystemService(Context.MEDIA_PROJECTION_SERVICE) public final class MediaProjectionManager { private static final String TAG = "MediaProjectionManager";
@hide
/** @hide */
public static final String EXTRA_APP_TOKEN = "android.media.projection.extra.EXTRA_APP_TOKEN";
@hide
/** @hide */
public static final String EXTRA_MEDIA_PROJECTION = "android.media.projection.extra.EXTRA_MEDIA_PROJECTION";
@hide
/** @hide */
public static final int TYPE_SCREEN_CAPTURE = 0;
@hide
/** @hide */
public static final int TYPE_MIRRORING = 1;
@hide
/** @hide */
public static final int TYPE_PRESENTATION = 2; private Context mContext; private Map<Callback, CallbackDelegate> mCallbacks; private IMediaProjectionManager mService;
@hide
/** @hide */
public MediaProjectionManager(Context context) { mContext = context; IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE); mService = IMediaProjectionManager.Stub.asInterface(b); mCallbacks = new ArrayMap<>(); }
Returns an Intent that must be passed to startActivityForResult() in order to start screen capture. The activity will prompt the user whether to allow screen capture. The result of this activity should be passed to getMediaProjection.
/** * Returns an Intent that <b>must</b> be passed to startActivityForResult() * in order to start screen capture. The activity will prompt * the user whether to allow screen capture. The result of this * activity should be passed to getMediaProjection. */
public Intent createScreenCaptureIntent() { Intent i = new Intent(); final ComponentName mediaProjectionPermissionDialogComponent = ComponentName.unflattenFromString(mContext.getResources().getString( com.android.internal.R.string .config_mediaProjectionPermissionDialogComponent)); i.setComponent(mediaProjectionPermissionDialogComponent); return i; }
Retrieve the MediaProjection obtained from a succesful screen capture request. Will be null if the result from the startActivityForResult() is anything other than RESULT_OK.
Params:
/** * Retrieve the MediaProjection obtained from a succesful screen * capture request. Will be null if the result from the * startActivityForResult() is anything other than RESULT_OK. * * @param resultCode The result code from {@link android.app.Activity#onActivityResult(int, * int, android.content.Intent)} * @param resultData The resulting data from {@link android.app.Activity#onActivityResult(int, * int, android.content.Intent)} */
public MediaProjection getMediaProjection(int resultCode, @NonNull Intent resultData) { if (resultCode != Activity.RESULT_OK || resultData == null) { return null; } IBinder projection = resultData.getIBinderExtra(EXTRA_MEDIA_PROJECTION); if (projection == null) { return null; } return new MediaProjection(mContext, IMediaProjection.Stub.asInterface(projection)); }
Get the MediaProjectionInfo for the active MediaProjection.
@hide
/** * Get the {@link MediaProjectionInfo} for the active {@link MediaProjection}. * @hide */
public MediaProjectionInfo getActiveProjectionInfo() { try { return mService.getActiveProjectionInfo(); } catch (RemoteException e) { Log.e(TAG, "Unable to get the active projection info", e); } return null; }
Stop the current projection if there is one.
@hide
/** * Stop the current projection if there is one. * @hide */
public void stopActiveProjection() { try { mService.stopActiveProjection(); } catch (RemoteException e) { Log.e(TAG, "Unable to stop the currently active media projection", e); } }
Add a callback to monitor all of the MediaProjections activity. Not for use by regular applications, must have the MANAGE_MEDIA_PROJECTION permission.
@hide
/** * Add a callback to monitor all of the {@link MediaProjection}s activity. * Not for use by regular applications, must have the MANAGE_MEDIA_PROJECTION permission. * @hide */
public void addCallback(@NonNull Callback callback, @Nullable Handler handler) { if (callback == null) { throw new IllegalArgumentException("callback must not be null"); } CallbackDelegate delegate = new CallbackDelegate(callback, handler); mCallbacks.put(callback, delegate); try { mService.addCallback(delegate); } catch (RemoteException e) { Log.e(TAG, "Unable to add callbacks to MediaProjection service", e); } }
Remove a MediaProjection monitoring callback.
@hide
/** * Remove a MediaProjection monitoring callback. * @hide */
public void removeCallback(@NonNull Callback callback) { if (callback == null) { throw new IllegalArgumentException("callback must not be null"); } CallbackDelegate delegate = mCallbacks.remove(callback); try { if (delegate != null) { mService.removeCallback(delegate); } } catch (RemoteException e) { Log.e(TAG, "Unable to add callbacks to MediaProjection service", e); } }
@hide
/** @hide */
public static abstract class Callback { public abstract void onStart(MediaProjectionInfo info); public abstract void onStop(MediaProjectionInfo info); }
@hide
/** @hide */
private final static class CallbackDelegate extends IMediaProjectionWatcherCallback.Stub { private Callback mCallback; private Handler mHandler; public CallbackDelegate(Callback callback, Handler handler) { mCallback = callback; if (handler == null) { handler = new Handler(); } mHandler = handler; } @Override public void onStart(final MediaProjectionInfo info) { mHandler.post(new Runnable() { @Override public void run() { mCallback.onStart(info); } }); } @Override public void onStop(final MediaProjectionInfo info) { mHandler.post(new Runnable() { @Override public void run() { mCallback.onStop(info); } }); } } }