1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.apis.media.projection; 18 19 import com.example.android.apis.R; 20 21 import android.app.Activity; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.res.Configuration; 25 import android.hardware.display.DisplayManager; 26 import android.hardware.display.VirtualDisplay; 27 import android.media.projection.MediaProjection; 28 import android.media.projection.MediaProjectionManager; 29 import android.os.Bundle; 30 import android.util.DisplayMetrics; 31 import android.util.Log; 32 import android.view.Surface; 33 import android.view.SurfaceHolder; 34 import android.view.SurfaceView; 35 import android.view.View; 36 import android.view.ViewGroup; 37 import android.widget.AdapterView; 38 import android.widget.ArrayAdapter; 39 import android.widget.Spinner; 40 import android.widget.Toast; 41 import android.widget.ToggleButton; 42 43 import java.util.Arrays; 44 import java.util.List; 45 46 public class MediaProjectionDemo extends Activity { 47 private static final String TAG = "MediaProjectionDemo"; 48 private static final int PERMISSION_CODE = 1; 49 private static final List<Resolution> RESOLUTIONS = Arrays.asList( 50 new Resolution(640,360), 51 new Resolution(960,540), 52 new Resolution(1366,768), 53 new Resolution(1600,900)); 54 55 private int mScreenDensity; 56 private MediaProjectionManager mProjectionManager; 57 58 private int mDisplayWidth; 59 private int mDisplayHeight; 60 private boolean mScreenSharing; 61 62 private MediaProjection mMediaProjection; 63 private VirtualDisplay mVirtualDisplay; 64 private Surface mSurface; 65 private SurfaceView mSurfaceView; 66 private ToggleButton mToggle; 67 68 @Override onCreate(Bundle savedInstanceState)69 public void onCreate(Bundle savedInstanceState) { 70 super.onCreate(savedInstanceState); 71 setContentView(R.layout.media_projection); 72 73 DisplayMetrics metrics = new DisplayMetrics(); 74 getWindowManager().getDefaultDisplay().getMetrics(metrics); 75 mScreenDensity = metrics.densityDpi; 76 77 mSurfaceView = (SurfaceView) findViewById(R.id.surface); 78 mSurface = mSurfaceView.getHolder().getSurface(); 79 mProjectionManager = 80 (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); 81 82 ArrayAdapter<Resolution> arrayAdapter = new ArrayAdapter<Resolution>( 83 this, android.R.layout.simple_list_item_1, RESOLUTIONS); 84 Spinner s = (Spinner) findViewById(R.id.spinner); 85 s.setAdapter(arrayAdapter); 86 s.setOnItemSelectedListener(new ResolutionSelector()); 87 s.setSelection(0); 88 89 mToggle = (ToggleButton) findViewById(R.id.screen_sharing_toggle); 90 mToggle.setSaveEnabled(false); 91 } 92 93 @Override onStop()94 protected void onStop() { 95 stopScreenSharing(); 96 super.onStop(); 97 } 98 99 @Override onDestroy()100 public void onDestroy() { 101 super.onDestroy(); 102 if (mMediaProjection != null) { 103 mMediaProjection.stop(); 104 mMediaProjection = null; 105 } 106 } 107 108 @Override onActivityResult(int requestCode, int resultCode, Intent data)109 public void onActivityResult(int requestCode, int resultCode, Intent data) { 110 if (requestCode != PERMISSION_CODE) { 111 Log.e(TAG, "Unknown request code: " + requestCode); 112 return; 113 } 114 if (resultCode != RESULT_OK) { 115 Toast.makeText(this, 116 "User denied screen sharing permission", Toast.LENGTH_SHORT).show(); 117 return; 118 } 119 mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data); 120 mMediaProjection.registerCallback(new MediaProjectionCallback(), null); 121 mVirtualDisplay = createVirtualDisplay(); 122 } 123 onToggleScreenShare(View view)124 public void onToggleScreenShare(View view) { 125 if (((ToggleButton) view).isChecked()) { 126 shareScreen(); 127 } else { 128 stopScreenSharing(); 129 } 130 } 131 shareScreen()132 private void shareScreen() { 133 mScreenSharing = true; 134 if (mSurface == null) { 135 return; 136 } 137 if (mMediaProjection == null) { 138 startActivityForResult(mProjectionManager.createScreenCaptureIntent(), 139 PERMISSION_CODE); 140 return; 141 } 142 mVirtualDisplay = createVirtualDisplay(); 143 } 144 stopScreenSharing()145 private void stopScreenSharing() { 146 if (mToggle.isChecked()) { 147 mToggle.setChecked(false); 148 } 149 150 mScreenSharing = false; 151 if (mVirtualDisplay != null) { 152 mVirtualDisplay.release(); 153 mVirtualDisplay = null; 154 } 155 } 156 createVirtualDisplay()157 private VirtualDisplay createVirtualDisplay() { 158 return mMediaProjection.createVirtualDisplay("ScreenSharingDemo", 159 mDisplayWidth, mDisplayHeight, mScreenDensity, 160 DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, 161 mSurface, null /*Callbacks*/, null /*Handler*/); 162 } 163 resizeVirtualDisplay()164 private void resizeVirtualDisplay() { 165 if (mVirtualDisplay == null) { 166 return; 167 } 168 mVirtualDisplay.resize(mDisplayWidth, mDisplayHeight, mScreenDensity); 169 } 170 171 private class ResolutionSelector implements Spinner.OnItemSelectedListener { 172 @Override onItemSelected(AdapterView<?> parent, View v, int pos, long id)173 public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) { 174 Resolution r = (Resolution) parent.getItemAtPosition(pos); 175 ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams(); 176 if (getResources().getConfiguration().orientation 177 == Configuration.ORIENTATION_LANDSCAPE) { 178 mDisplayHeight = r.y; 179 mDisplayWidth = r.x; 180 } else { 181 mDisplayHeight = r.x; 182 mDisplayWidth = r.y; 183 } 184 lp.height = mDisplayHeight; 185 lp.width = mDisplayWidth; 186 mSurfaceView.setLayoutParams(lp); 187 } 188 189 @Override onNothingSelected(AdapterView<?> parent)190 public void onNothingSelected(AdapterView<?> parent) { /* Ignore */ } 191 } 192 193 private class MediaProjectionCallback extends MediaProjection.Callback { 194 @Override onStop()195 public void onStop() { 196 mMediaProjection = null; 197 stopScreenSharing(); 198 } 199 } 200 201 private class SurfaceCallbacks implements SurfaceHolder.Callback { 202 @Override surfaceChanged(SurfaceHolder holder, int format, int width, int height)203 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 204 mDisplayWidth = width; 205 mDisplayHeight = height; 206 resizeVirtualDisplay(); 207 } 208 209 @Override surfaceCreated(SurfaceHolder holder)210 public void surfaceCreated(SurfaceHolder holder) { 211 mSurface = holder.getSurface(); 212 if (mScreenSharing) { 213 shareScreen(); 214 } 215 } 216 217 @Override surfaceDestroyed(SurfaceHolder holder)218 public void surfaceDestroyed(SurfaceHolder holder) { 219 if (!mScreenSharing) { 220 stopScreenSharing(); 221 } 222 } 223 } 224 225 private static class Resolution { 226 int x; 227 int y; 228 Resolution(int x, int y)229 public Resolution(int x, int y) { 230 this.x = x; 231 this.y = y; 232 } 233 234 @Override toString()235 public String toString() { 236 return x + "x" + y; 237 } 238 } 239 } 240