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.ArrayList; 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 = new ArrayList<Resolution>() {{ 50 add(new Resolution(640,360)); 51 add(new Resolution(960,540)); 52 add(new Resolution(1366,768)); 53 add(new Resolution(1600,900)); 54 }}; 55 56 private int mScreenDensity; 57 private MediaProjectionManager mProjectionManager; 58 59 private int mDisplayWidth; 60 private int mDisplayHeight; 61 private boolean mScreenSharing; 62 63 private MediaProjection mMediaProjection; 64 private VirtualDisplay mVirtualDisplay; 65 private Surface mSurface; 66 private SurfaceView mSurfaceView; 67 private ToggleButton mToggle; 68 69 @Override onCreate(Bundle savedInstanceState)70 public void onCreate(Bundle savedInstanceState) { 71 super.onCreate(savedInstanceState); 72 setContentView(R.layout.media_projection); 73 74 DisplayMetrics metrics = new DisplayMetrics(); 75 getWindowManager().getDefaultDisplay().getMetrics(metrics); 76 mScreenDensity = metrics.densityDpi; 77 78 mSurfaceView = (SurfaceView) findViewById(R.id.surface); 79 mSurface = mSurfaceView.getHolder().getSurface(); 80 mProjectionManager = 81 (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); 82 83 ArrayAdapter<Resolution> arrayAdapter = new ArrayAdapter<Resolution>( 84 this, android.R.layout.simple_list_item_1, RESOLUTIONS); 85 Spinner s = (Spinner) findViewById(R.id.spinner); 86 s.setAdapter(arrayAdapter); 87 s.setOnItemSelectedListener(new ResolutionSelector()); 88 s.setSelection(0); 89 90 mToggle = (ToggleButton) findViewById(R.id.screen_sharing_toggle); 91 mToggle.setSaveEnabled(false); 92 } 93 94 @Override onStop()95 protected void onStop() { 96 stopScreenSharing(); 97 super.onStop(); 98 } 99 100 @Override onDestroy()101 public void onDestroy() { 102 super.onDestroy(); 103 if (mMediaProjection != null) { 104 mMediaProjection.stop(); 105 mMediaProjection = null; 106 } 107 } 108 109 @Override onActivityResult(int requestCode, int resultCode, Intent data)110 public void onActivityResult(int requestCode, int resultCode, Intent data) { 111 if (requestCode != PERMISSION_CODE) { 112 Log.e(TAG, "Unknown request code: " + requestCode); 113 return; 114 } 115 if (resultCode != RESULT_OK) { 116 Toast.makeText(this, 117 "User denied screen sharing permission", Toast.LENGTH_SHORT).show(); 118 return; 119 } 120 mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data); 121 mMediaProjection.registerCallback(new MediaProjectionCallback(), null); 122 mVirtualDisplay = createVirtualDisplay(); 123 } 124 onToggleScreenShare(View view)125 public void onToggleScreenShare(View view) { 126 if (((ToggleButton) view).isChecked()) { 127 shareScreen(); 128 } else { 129 stopScreenSharing(); 130 } 131 } 132 shareScreen()133 private void shareScreen() { 134 mScreenSharing = true; 135 if (mSurface == null) { 136 return; 137 } 138 if (mMediaProjection == null) { 139 startActivityForResult(mProjectionManager.createScreenCaptureIntent(), 140 PERMISSION_CODE); 141 return; 142 } 143 mVirtualDisplay = createVirtualDisplay(); 144 } 145 stopScreenSharing()146 private void stopScreenSharing() { 147 if (mToggle.isChecked()) { 148 mToggle.setChecked(false); 149 } 150 151 mScreenSharing = false; 152 if (mVirtualDisplay != null) { 153 mVirtualDisplay.release(); 154 mVirtualDisplay = null; 155 } 156 } 157 createVirtualDisplay()158 private VirtualDisplay createVirtualDisplay() { 159 return mMediaProjection.createVirtualDisplay("ScreenSharingDemo", 160 mDisplayWidth, mDisplayHeight, mScreenDensity, 161 DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, 162 mSurface, null /*Callbacks*/, null /*Handler*/); 163 } 164 resizeVirtualDisplay()165 private void resizeVirtualDisplay() { 166 if (mVirtualDisplay == null) { 167 return; 168 } 169 mVirtualDisplay.resize(mDisplayWidth, mDisplayHeight, mScreenDensity); 170 } 171 172 private class ResolutionSelector implements Spinner.OnItemSelectedListener { 173 @Override onItemSelected(AdapterView<?> parent, View v, int pos, long id)174 public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) { 175 Resolution r = (Resolution) parent.getItemAtPosition(pos); 176 ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams(); 177 if (getResources().getConfiguration().orientation 178 == Configuration.ORIENTATION_LANDSCAPE) { 179 mDisplayHeight = r.y; 180 mDisplayWidth = r.x; 181 } else { 182 mDisplayHeight = r.x; 183 mDisplayWidth = r.y; 184 } 185 lp.height = mDisplayHeight; 186 lp.width = mDisplayWidth; 187 mSurfaceView.setLayoutParams(lp); 188 } 189 190 @Override onNothingSelected(AdapterView<?> parent)191 public void onNothingSelected(AdapterView<?> parent) { /* Ignore */ } 192 } 193 194 private class MediaProjectionCallback extends MediaProjection.Callback { 195 @Override onStop()196 public void onStop() { 197 mMediaProjection = null; 198 stopScreenSharing(); 199 } 200 } 201 202 private class SurfaceCallbacks implements SurfaceHolder.Callback { 203 @Override surfaceChanged(SurfaceHolder holder, int format, int width, int height)204 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 205 mDisplayWidth = width; 206 mDisplayHeight = height; 207 resizeVirtualDisplay(); 208 } 209 210 @Override surfaceCreated(SurfaceHolder holder)211 public void surfaceCreated(SurfaceHolder holder) { 212 mSurface = holder.getSurface(); 213 if (mScreenSharing) { 214 shareScreen(); 215 } 216 } 217 218 @Override surfaceDestroyed(SurfaceHolder holder)219 public void surfaceDestroyed(SurfaceHolder holder) { 220 if (!mScreenSharing) { 221 stopScreenSharing(); 222 } 223 } 224 } 225 226 private static class Resolution { 227 int x; 228 int y; 229 Resolution(int x, int y)230 public Resolution(int x, int y) { 231 this.x = x; 232 this.y = y; 233 } 234 235 @Override toString()236 public String toString() { 237 return x + "x" + y; 238 } 239 } 240 } 241