diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml index 716fa86d8..3bec8f867 100644 --- a/samples/ApiDemos/AndroidManifest.xml +++ b/samples/ApiDemos/AndroidManifest.xml @@ -2971,6 +2971,14 @@ + + + + + + + diff --git a/samples/ApiDemos/res/layout/media_projection.xml b/samples/ApiDemos/res/layout/media_projection.xml new file mode 100644 index 000000000..412db4ce2 --- /dev/null +++ b/samples/ApiDemos/res/layout/media_projection.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml index 6a2df2e43..8d9bdc418 100644 --- a/samples/ApiDemos/res/values/strings.xml +++ b/samples/ApiDemos/res/values/strings.xml @@ -918,6 +918,7 @@ Play Streaming Video Play Audio from Local File Play Audio from Resources + Toggle screen sharing diff --git a/samples/ApiDemos/src/com/example/android/apis/media/projection/MediaProjectionDemo.java b/samples/ApiDemos/src/com/example/android/apis/media/projection/MediaProjectionDemo.java new file mode 100644 index 000000000..2abdd7f5f --- /dev/null +++ b/samples/ApiDemos/src/com/example/android/apis/media/projection/MediaProjectionDemo.java @@ -0,0 +1,222 @@ +/* + * 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 com.example.android.apis.media.projection; + +import com.example.android.apis.R; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.hardware.display.VirtualDisplay; +import android.media.projection.MediaProjection; +import android.media.projection.MediaProjectionManager; +import android.os.Bundle; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Spinner; +import android.widget.Toast; +import android.widget.ToggleButton; + +import java.util.ArrayList; +import java.util.List; + +public class MediaProjectionDemo extends Activity { + private static final String TAG = "MediaProjectionDemo"; + private static final int PERMISSION_CODE = 1; + private static final List RESOLUTIONS = new ArrayList() {{ + add(new Resolution(640,360)); + add(new Resolution(960,540)); + add(new Resolution(1366,768)); + add(new Resolution(1600,900)); + }}; + + private int mScreenDensity; + private MediaProjectionManager mProjectionManager; + + private int mDisplayWidth; + private int mDisplayHeight; + private boolean mScreenSharing; + + private MediaProjection mMediaProjection; + private VirtualDisplay mVirtualDisplay; + private Surface mSurface; + private SurfaceView mSurfaceView; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.media_projection); + + DisplayMetrics metrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(metrics); + mScreenDensity = metrics.densityDpi; + + mSurfaceView = (SurfaceView) findViewById(R.id.surface); + mSurface = mSurfaceView.getHolder().getSurface(); + mProjectionManager = + (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); + + ArrayAdapter arrayAdapter = new ArrayAdapter( + this, android.R.layout.simple_list_item_1, RESOLUTIONS); + Spinner s = (Spinner) findViewById(R.id.spinner); + s.setAdapter(arrayAdapter); + s.setOnItemSelectedListener(new ResolutionSelector()); + s.setSelection(0); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mMediaProjection != null) { + mMediaProjection.stop(); + mMediaProjection = null; + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode != PERMISSION_CODE) { + Log.e(TAG, "Unknown request code: " + requestCode); + return; + } + if (resultCode != RESULT_OK) { + Toast.makeText(this, + "User denied screen sharing permission", Toast.LENGTH_SHORT).show(); + return; + } + mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data); + mVirtualDisplay = createVirtualDisplay(); + } + + public void onToggleScreenShare(View view) { + if (((ToggleButton) view).isChecked()) { + shareScreen(); + } else { + stopScreenSharing(); + } + } + + private void shareScreen() { + mScreenSharing = true; + if (mSurface == null) { + return; + } + if (mMediaProjection == null) { + startActivityForResult(mProjectionManager.getScreenCaptureIntent(), PERMISSION_CODE); + return; + } + mVirtualDisplay = createVirtualDisplay(); + } + + private void stopScreenSharing() { + mScreenSharing = false; + if (mVirtualDisplay == null) { + return; + } + mVirtualDisplay.release(); + } + + private VirtualDisplay createVirtualDisplay() { + return mMediaProjection.createVirtualDisplay("ScreenSharingDemo", + mDisplayWidth, mDisplayHeight, mScreenDensity, + false /*isSecure*/, mSurface, null /*Callbacks*/, null /*Handler*/); + } + + private void resizeVirtualDisplay() { + if (mVirtualDisplay == null) { + return; + } + mVirtualDisplay.resize(mDisplayWidth, mDisplayHeight, mScreenDensity); + } + + private class ResolutionSelector implements Spinner.OnItemSelectedListener { + @Override + public void onItemSelected(AdapterView parent, View v, int pos, long id) { + Resolution r = (Resolution) parent.getItemAtPosition(pos); + ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams(); + if (getResources().getConfiguration().orientation + == Configuration.ORIENTATION_LANDSCAPE) { + mDisplayHeight = r.y; + mDisplayWidth = r.x; + } else { + mDisplayHeight = r.x; + mDisplayWidth = r.y; + } + lp.height = mDisplayHeight; + lp.width = mDisplayWidth; + mSurfaceView.setLayoutParams(lp); + } + + @Override + public void onNothingSelected(AdapterView parent) { /* Ignore */ } + } + + private class MediaProjectionCallback extends MediaProjection.Callback { + @Override + public void onStop() { + mMediaProjection = null; + stopScreenSharing(); + } + } + + private class SurfaceCallbacks implements SurfaceHolder.Callback { + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + mDisplayWidth = width; + mDisplayHeight = height; + resizeVirtualDisplay(); + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + mSurface = holder.getSurface(); + if (mScreenSharing) { + shareScreen(); + } + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + if (!mScreenSharing) { + stopScreenSharing(); + } + } + } + + private static class Resolution { + int x; + int y; + + public Resolution(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public String toString() { + return x + "x" + y; + } + } +}