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