Home | History | Annotate | Download | only in projection
      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
     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
     95     protected void onStop() {
     96         stopScreenSharing();
     97         super.onStop();
     98     }
     99 
    100     @Override
    101     public void onDestroy() {
    102         super.onDestroy();
    103         if (mMediaProjection != null) {
    104             mMediaProjection.stop();
    105             mMediaProjection = null;
    106         }
    107     }
    108 
    109     @Override
    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 
    125     public void onToggleScreenShare(View view) {
    126         if (((ToggleButton) view).isChecked()) {
    127             shareScreen();
    128         } else {
    129             stopScreenSharing();
    130         }
    131     }
    132 
    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 
    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 
    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 
    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
    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
    191         public void onNothingSelected(AdapterView<?> parent) { /* Ignore */ }
    192     }
    193 
    194     private class MediaProjectionCallback extends MediaProjection.Callback {
    195         @Override
    196         public void onStop() {
    197             mMediaProjection = null;
    198             stopScreenSharing();
    199         }
    200     }
    201 
    202     private class SurfaceCallbacks implements SurfaceHolder.Callback {
    203         @Override
    204         public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    205             mDisplayWidth = width;
    206             mDisplayHeight = height;
    207             resizeVirtualDisplay();
    208         }
    209 
    210         @Override
    211         public void surfaceCreated(SurfaceHolder holder) {
    212             mSurface = holder.getSurface();
    213             if (mScreenSharing) {
    214                 shareScreen();
    215             }
    216         }
    217 
    218         @Override
    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 
    230         public Resolution(int x, int y) {
    231             this.x = x;
    232             this.y = y;
    233         }
    234 
    235         @Override
    236         public String toString() {
    237             return x + "x" + y;
    238         }
    239     }
    240 }
    241