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;
+ }
+ }
+}