1. 程式人生 > >Android錄屏功能的實現

Android錄屏功能的實現

       最近做一個Android開發的專案用到了錄屏的功能,開始查閱了一些資料和部落格,基本上都是在討論ROOT的。直到後來在github上看到一個比較新的程式碼,才恍然發現,Android 5.0時候開放了一個新的介面---android.media.projection,一下子讓這個問題變得簡單了。所以說查閱資料也該注意實時性,現在很多技術推陳出新速度很快,一些新的包,介面,方法會讓問題更好更快的解決。不過自己還是決定總結了下之前的一些想法,也算是一個學習吧。

       首先說下之前的幾種方法。一般最開始的 Android 截圖程式,都是來源於 Linux 的截圖方法,android 使用的 Linux 核心,那麼 Linux 下的截圖方法也就最先被 android 採用。Linux  使用了 framebuffer 管理顯示輸出,傳統的辦法就是讀取 framebuffer 的資料,然後得到整個螢幕的資料。此方法在 Android3.0 版本之前是也唯一可行的方法。 然而 linux 採用了嚴格的許可權控制 裝置檔案,framebuffer 也是其控制之一,在 Android 中只有 root, 和 graphic 組使用者才有許可權讀取,所以要採用讀取 framebuffer 的方式實現截圖,應用必須獲得 root 許可權。

       後來呢,大家都知道ROOT許可權是件比較麻煩的事,給自己軟體加上ROOT許可權對於客戶來說也是一件挺有風險的事,於是後來常用的一種方法就是自定義view利用bitmap獲取view的形式獲取當前螢幕,核心程式碼是:

        View view = activity.getWindow().getDecorView(); //      Enables or disables the drawing cache         view.setDrawingCacheEnabled(true); //      will draw the view in a bitmap
        view.buildDrawingCache();         Bitmap bitmap = view.getDrawingCache();    然後將bitmap儲存即可。但是這樣的方法有個明顯的缺陷就是這樣截出來的圖無法獲取狀態列以及一些dialog。       此外比較常見的方法還有讀取 framebuffer 的方式,利用介面SurfaceFlinger的方式,通過 ddms截圖的方式等方法,但都有侷限性。       於是谷歌就是Android5.0版本時候發放了現在的這個介面android.media.projection.MediaProjection。使用該介面,第三方應用程式無需獲取系統root許可權也可以直接進行螢幕截圖操作了。查詢其官方api可知,該介面主要用來“螢幕截圖”操作和“音訊錄製”操作。好吧,直接上乾貨吧。
一、使用方法。 首先用引數MEDIA_-PROJECTION_SERVICE調 用Context.getSystemService(),得到MediaProjectionManager類別例項; 
其次,呼叫 createScreenCaptureIntent ()得到一個Intent;再次,使用startActivityForResult()啟動螢幕捕捉; 
最後,將結果返回到 getMediaProjection()上,獲取捕捉資料。
二、Demo案例。 1.匯入介面
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
2.例項化MediaProjectionManager
mMediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
3.利用MediaProjectionManager類例項的功能函式createScreenCaptureIntent()生成intent,為接下來的的抓取螢幕做準備
Intent captureIntent = mMediaProjectionManager.createScreenCaptureIntent();
startActivityForResult(captureIntent, REQUEST_CODE);
4.在onActivityResult()中獲取返回值
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    MediaProjection mediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
    if (mediaProjection == null) {
        Log.e("@@", "media projection is null");
        return;
}
5.例項化VirtualDisplay,這個類的主要作用是用來獲取螢幕資訊並儲存在裡。
private VirtualDisplay mVirtualDisplay;
mVirtualDisplay = mMediaProjection.createVirtualDisplay(TAG + "-display",
mWidth, mHeight, mDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,
mSurface, null, null);
6.儲存圖片。目前的圖片資訊保留在mSurface裡,建立一個Image獲取資訊儲存在BufferByte裡再儲存在一個bitmap裡即可。 如此一來,整個截圖就變得簡單多了。而且還可以使用Mediacodec編碼,MediaMuxer封裝轉為MP4等格式來進行錄屏,實在是簡單又好用了