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     }
     92 
     93     @Override
     94     public void onDestroy() {
     95         super.onDestroy();
     96         if (mMediaProjection != null) {
     97             mMediaProjection.stop();
     98             mMediaProjection = null;
     99         }
    100     }
    101 
    102     @Override
    103     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    104         if (requestCode != PERMISSION_CODE) {
    105             Log.e(TAG, "Unknown request code: " + requestCode);
    106             return;
    107         }
    108         if (resultCode != RESULT_OK) {
    109             Toast.makeText(this,
    110                     "User denied screen sharing permission", Toast.LENGTH_SHORT).show();
    111             return;
    112         }
    113         mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
    114         mMediaProjection.registerCallback(new MediaProjectionCallback(), null);
    115         mVirtualDisplay = createVirtualDisplay();
    116     }
    117 
    118     public void onToggleScreenShare(View view) {
    119         if (((ToggleButton) view).isChecked()) {
    120             shareScreen();
    121         } else {
    122             stopScreenSharing();
    123         }
    124     }
    125 
    126     private void shareScreen() {
    127         mScreenSharing = true;
    128         if (mSurface == null) {
    129             return;
    130         }
    131         if (mMediaProjection == null) {
    132             startActivityForResult(mProjectionManager.createScreenCaptureIntent(),
    133                     PERMISSION_CODE);
    134             return;
    135         }
    136         mVirtualDisplay = createVirtualDisplay();
    137     }
    138 
    139     private void stopScreenSharing() {
    140         if (mToggle.isChecked()) {
    141             mToggle.setChecked(false);
    142         }
    143         mScreenSharing = false;
    144         if (mVirtualDisplay != null) {
    145             mVirtualDisplay.release();
    146             mVirtualDisplay = null;
    147         }
    148     }
    149 
    150     private VirtualDisplay createVirtualDisplay() {
    151         return mMediaProjection.createVirtualDisplay("ScreenSharingDemo",
    152                 mDisplayWidth, mDisplayHeight, mScreenDensity,
    153                 DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
    154                 mSurface, null /*Callbacks*/, null /*Handler*/);
    155     }
    156 
    157     private void resizeVirtualDisplay() {
    158         if (mVirtualDisplay == null) {
    159             return;
    160         }
    161         mVirtualDisplay.resize(mDisplayWidth, mDisplayHeight, mScreenDensity);
    162     }
    163 
    164     private class ResolutionSelector implements Spinner.OnItemSelectedListener {
    165         @Override
    166         public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) {
    167             Resolution r = (Resolution) parent.getItemAtPosition(pos);
    168             ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
    169             if (getResources().getConfiguration().orientation
    170                     == Configuration.ORIENTATION_LANDSCAPE) {
    171                 mDisplayHeight = r.y;
    172                 mDisplayWidth = r.x;
    173             } else {
    174                 mDisplayHeight = r.x;
    175                 mDisplayWidth = r.y;
    176             }
    177             lp.height = mDisplayHeight;
    178             lp.width = mDisplayWidth;
    179             mSurfaceView.setLayoutParams(lp);
    180         }
    181 
    182         @Override
    183         public void onNothingSelected(AdapterView<?> parent) { /* Ignore */ }
    184     }
    185 
    186     private class MediaProjectionCallback extends MediaProjection.Callback {
    187         @Override
    188         public void onStop() {
    189             mMediaProjection = null;
    190             stopScreenSharing();
    191         }
    192     }
    193 
    194     private class SurfaceCallbacks implements SurfaceHolder.Callback {
    195         @Override
    196         public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    197             mDisplayWidth = width;
    198             mDisplayHeight = height;
    199             resizeVirtualDisplay();
    200         }
    201 
    202         @Override
    203         public void surfaceCreated(SurfaceHolder holder) {
    204             mSurface = holder.getSurface();
    205             if (mScreenSharing) {
    206                 shareScreen();
    207             }
    208         }
    209 
    210         @Override
    211         public void surfaceDestroyed(SurfaceHolder holder) {
    212             if (!mScreenSharing) {
    213                 stopScreenSharing();
    214             }
    215         }
    216     }
    217 
    218     private static class Resolution {
    219         int x;
    220         int y;
    221 
    222         public Resolution(int x, int y) {
    223             this.x = x;
    224             this.y = y;
    225         }
    226 
    227         @Override
    228         public String toString() {
    229             return x + "x" + y;
    230         }
    231     }
    232 }
    233