花了ㄧ些時間,不用root手機,要如何用android java程式抓取手機螢幕的畫面,最後找到android5.0以上版本,我們可以使用mediaProjectio這個API來截取螢幕或錄制螢幕,首先要實作onActivity這個method,要讓使用者決定是否要啟用,會出現對話框,使用者按確定後,取得ImageReader就可做後續處理,若使用者按Canselled就不能使用mediaProjection來截取螢幕,google開放這樣做法,就不會有隱私權的問題,上面影片我還使用windowmanager來達成抓取開啟任何app,都能截取畫面,一開使按確定,使用者開啟瀏覽器,按左上角play,點擊螢幕截取框框中畫面,加到左下角主頁面中的image view,按左上角離開,就會跳回主頁面看到截圖,目前整個程式,我還沒寫很完整,寫好在放上來,寫到這樣都是google上找的資料。
補充一下,這個VirtualDisplay,是在onActivityResult中初始化,才是正確的,不是在事件中去初始化,這樣程式app,只會產生一個VirtualDisplay,若是在事件中初始化,或放在執行緒,那就會產生太多的VirtualDisplay,會導致內存問題的.
補充一下,這個VirtualDisplay,是在onActivityResult中初始化,才是正確的,不是在事件中去初始化,這樣程式app,只會產生一個VirtualDisplay,若是在事件中初始化,或放在執行緒,那就會產生太多的VirtualDisplay,會導致內存問題的.
vp=mp.createVirtualDisplay(..........................);
就我的意識,這VirtualDisplay和機器螢幕是同步,獲取ImgaeReader就是即時的.
就我的意識,這VirtualDisplay和機器螢幕是同步,獲取ImgaeReader就是即時的.
A.實作onActivityResult讓使用者對話開始使用mediaProjection
MyActivity:
............
private MediaProjectionManager mpm;
private MediaProjection mp;
private ImageReader ir=null;
private VirtualDisplay vp;
private static final int REQUEST_NUMBER=1001;
.....................
mpm=(MediaProjectionManager)getSystemService(MEDIA_PROJECTION_SERVICE);
startActivityForResult(mpm.createScreenCaptureIntent(),REQUEST_NUMBER);
............
private MediaProjectionManager mpm;
private MediaProjection mp;
private ImageReader ir=null;
private VirtualDisplay vp;
private static final int REQUEST_NUMBER=1001;
.....................
mpm=(MediaProjectionManager)getSystemService(MEDIA_PROJECTION_SERVICE);
startActivityForResult(mpm.createScreenCaptureIntent(),REQUEST_NUMBER);
.....................
//讓使用者決定可以使用mediaProjection,跳出對話框,使用者按OK,便可使用ir抓取screen picture,否則return
@Override
public void onActivityResult(int requestCode,int resultCode,Intent data){
if(REQUEST_NUMBER==requestCode){
if(resultCode!=RESULT_OK){
Toast.makeText(this,"USER CANCELLED",Toast.LENGTH_LONG).show();
return;
}
DisplayMetrics ds=new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(ds);
int dpi=ds.densityDpi;
int dw=ds.widthPixels;
int dh=ds.heightPixels;
mp=mpm.getMediaProjection(resultCode,data);
ir=ImageReader.newInstance(dw,dh, PixelFormat.RGBA_8888,2);
//建立虛擬display
vp=mp.createVirtualDisplay("ScreenCapture",dw,dh,dpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,ir.getSurface(),null,null);
}
B.取得ImageReader後,做後續Bitmap處理
package com.example.yplin.myapplication11;
import android.graphics.Bitmap;
import android.media.ImageReader;
import android.media.Image;
import android.util.Log;
import java.nio.ByteBuffer;
/**
* Created by yplin on 2017/3/31.
* 截取螢幕畫面
* Activity必須決定可以使用mediaProjection
* 產生一個ImageReader來截取螢幕畫面
*/
public class capture_screen {
private MainActivity11 MainA=null;
private Bitmap bp=null;
public capture_screen(MainActivity11 ma){
MainA=ma;
if(ma.get_imagereader()!=null){
ImageReader ir=ma.get_imagereader(); //image reader
int dw=ma.get_screen_width(); //screen width
int dh=ma.get_screen_height(); //screen height
Image mimage = ir.acquireLatestImage();
Image.Plane[] planes = mimage.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
int ps = planes[0].getPixelStride();
int rs = planes[0].getRowStride();
int rp = rs - ps * dw;
bp = Bitmap.createBitmap(dw + rp / ps, dh, Bitmap.Config.ARGB_8888);
bp.copyPixelsFromBuffer(buffer); //full screen picture
mimage.close();
}else{
Log.d("USAGE:", "使用者必須決定可以使用mediaProjection");
}
}
//BUG x+w不能大於screen width y+h 不能大於screen height,x和y不能小於0
//Region Screem picture
public Bitmap get_bitmap(int x,int y,int w,int h){
MainA.add_image(bp.createBitmap(bp,x,y,w,h)); //把Region Screen 放置Activity的image view
return bp.createBitmap(bp,x,y,w,h); //Return Region Screen
}
public void clear_bitmap(){bp=null;}
沒有留言:
張貼留言