Android の画面キャプチャを実現するいくつかの方法

Android のスクリーンショットは、ビュー スクリーンショット、WebView スクリーンショット、システム スクリーンショット、adb スクリーンショットの 4 つのタイプに分類されます。

画像.png

画像.png

1. スクリーンショットを表示する

View のスクリーンショットは、現在の View インターフェイスをキャプチャするためのものですが、ステータス バーや他のアプリケーションのインターフェイスなど、画面上の他の情報はキャプチャできません。

1.1 ナビゲーションバー以外の画面をキャプチャする

    // 开始截屏
    private static byte[] screenshotView() {

        // ⬇⬇⬇ 可直接放入点击事件中 ⬇⬇⬇
        View view = getWindow().getDecorView(); // view可以替换成你需要截图的控件,如父控件 RelativeLayout,LinearLayout
        // view.setDrawingCacheEnabled(true); // 设置缓存,可用于实时截图
        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        view.draw(canvas);
        // view.setDrawingCacheEnabled(false); // 清空缓存,可用于实时截图

        String bitmapString = getBitmapString(bitmap); // 位图转 Base64 String
        // byte[] drawByte = getBitmapByte(bitmap); // 位图转为 Byted

        Log.d("111111 合并>>", "bitmapString ====:" + bitmapString);
        matting_img02.setImageBitmap(bitmap); // ImageView控件直接图片展示截好的图片
        // ⬆⬆⬆ 可直接放入点击事件中 ⬆⬆⬆

        return drawByte;
    }

    // 位图转 Base64 String
    private static String getBitmapString(Bitmap bitmap) {
        String result = null;
        ByteArrayOutputStream out = null;
        try {
            if (bitmap != null) {
                out = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);

                out.flush();
                out.close();

                byte[] bitmapBytes = out.toByteArray();
                result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT); // Base64.DEFAULT会自动换行,传给前端会报错,所以要用Base64.NO_WRAP
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    // 位图转 Byte
    private static byte[] getBitmapByte(Bitmap bitmap) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // 参数1转换类型,参数2压缩质量,参数3字节流资源
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
        try {
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toByteArray();
    }



1.2 特定のコントロールまたはエリアを傍受する

// 方法1
private static byte[] screenshotView1() {
  View view = title;
  view.setDrawingCacheEnabled(true);
  view.buildDrawingCache();
  Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
  byte[] drawByte = getBitmapByte(bitmap);
  return drawByte;
}

// 方法2
private static byte[] screenshotView2() {
  View view = title;
  Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
  // 使用 Canvas,调用自定义 view 控件的 onDraw 方法,绘制图片
  Canvas canvas = new Canvas(bitmap);
  dView.draw(canvas);
  byte[] drawByte = getBitmapByte(bitmap);
  return drawByte;
}

2. WebView の画面キャプチャ

WebViewのスクリーンショットを撮るには4つの方法があります

2.1 CapturePicture() メソッドを使用します (非推奨)
private static byte[]screenshotWebView() { Picture picture = webview.capturePicture(); //ビットマップを作成しますBitmap bitmap = Bitmap.createBitmap(picture.getWidth(), picture.getHeight() ), Bitmap.Config.ARGB_8888); Canvas Canvas = new Canvas(bitmap); // Draw (グラフィックス描画を完了するためにネイティブ メソッドが呼び出されます) picture.draw(canvas); byte[]drawByte = getBitmapByte(bitmap) ;ドローバイトを返します ; }








2.2 getScale() メソッドを使用する (非推奨)

private static byte[]screenshotWebView() { floatscale = webView.getScale(); int webViewHeight = (int) (webView.getContentHeight()*scale+0.5); ビットマップ bitmap = Bitmap.createBitmap(webView.getWidth(),webViewHeight, Bitmap.Config.ARGB_8888); Canvas Canvas = 新しい Canvas(ビットマップ); webView.draw(キャンバス); byte[]drawByte = getBitmapByte(ビットマップ); ドローバイトを返します。}







2.3 getDrawingCache() メソッドの使用

private static byte[]screenshotWebView() { ビットマップ bitmap = webView.getDrawingCache(); byte[]drawByte = getBitmapByte(bmp); ドローバイトを返します。}



2.4draw()メソッドの使用

private static byte[]screenshotWebView() { // webView.setDrawingCacheEnabled(true); // 設置保存Bitmap bitmap = Bitmap.createBitmap(webView.getWidth(), webView.getHeight(), Bitmap.Config.ARGB_8888); Canvas Canvas = 新しい Canvas(ビットマップ); webView.draw(キャンバス); webView.destroyDrawingCache(); byte[]drawByte = getBitmapByte(ビットマップ); // webView.setDrawingCacheEnabled(false); // 清空缓存returndrawByte; }








2.5 スニペット画像の構成

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { WebView.enableSlowWholeDocumentDraw(); setContentView (R.layout.activity_webview);


ハードウェア アクセラレーションが有効になっており、AndroidManifest.xml で属性 android:hardwareAccelerated="false" を設定できるため、WebView スクリーンショットでは cavans 要素をキャプチャできない場合があります。

ハードウェア アクセラレーションをオフにすると、ページで予期しない動作が発生する可能性があります

3. システムのスクリーンショット

3.1 メディアプロジェクション

public static Final int REQUEST_MEDIA_PROJECTION = 10001;
// 申请截屏权制限
private void getScreenShotPower() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { MediaProjectionManager mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); if (mProjectionManager != null) { startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION); } } }






private MediaProjection mMediaProjection;
// コールバック
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_MEDIA_PROJECTION && data != null) { if (res ultCode == RESULT_OK) { MediaProjection mediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data); if (mediaProjection == null) { Toast.makeText(this,"プログラム エラーが発生しました: MediaProjection@1",Toast.LENGTH_SHORT).show( ); return; } // mediaProjection は現在の画面ストリームです} else if (resultCode == RESULT_CANCELED) { Log.d(TAG, "ユーザーがキャンセルされました"); } } }













3.2 Surface (root 権限が必要)

使用前に:

AndroidMenifest.xml に android:sharedUserId="android.uid.system" 属性を追加します。システム署名またはルート システムをプログラムに
追加する必要があります。Java リフレクション メカニズムを使用して、システム API を呼び出すスクリーンショット:

private void ScreenshotSystem() { Class<?> surfaceClass; メソッドメソッド = null; ビットマップ bitmap = null; 試してください { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) { surfaceClass = Class.forName("android.view.SurfaceControl"); } else { surfaceClass = Class.forName("android.view.Surface"); メソッド= surfaceClass.getDeclaredMethod("スクリーンショット", Integer.TYPE, Integer.TYPE); メソッド.setAccessible(true); bitmap = (ビットマップ)method.invoke((Object)null, webview.getWidth(), webview.getHeight()); byte[]drawByte = getBitmapByte(ビットマップ); catch (ClassNotFoundException e){ e.printStackTrace();















catch (NoSuchMethodException e){ e.printStackTrace(); } catch (IllegalAccessException e){ e.printStackTrace(); catch (InvocationTargetException e){ e.printStackTrace(); } }






3.3 ピクセルコピー

private void ScreenshotSystem() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { PixelCopy.request(getWindow(), bitmap, new PixelCopy.OnPixelCopyFinishedListener() { @Override public void onPixelCopyFinished(int copyResult){ if (PixelCopy.SUCCESS == copyResult) { byte[]drawByte = getBitmapByte(bitmap); } else { // onErrorCallback() } } }, new Handler()); } }












3.4 フレームバッファ (root 権限が必要)

文字列 DEVICE_NAME = "/dev/graphics/fb0";
ファイル deviceFile = 新しいファイル(DEVICE_NAME);
プロセス localProcess = Runtime.getRuntime().exec("supersu");
文字列 str = "cat " + deviceFile.getAbsolutePath() + "\n";
localProcess.getOutputStream().write(str.getBytes());
localProcess.getInputStream() を返します。

3.5 screencap コマンド (root 権限が必要)

private static String getScreenshot(){ プロセス process = null; 文字列ファイルパス = "mnt/sdcard/" + System.currentTimeMillis() + ".png"; try { process = Runtime.getRuntime().exec("su"); PrintStream 出力ストリーム = null; OutputStream = new PrintStream(new BufferedOutputStream(process.getOutputStream(), 8192)); OutputStream.println("screencap -p " + filePath); 出力ストリーム.flush(); 出力ストリーム.close(); process.waitFor(); } catch (例外 e) { e.printStackTrace(); 最後に { if(プロセス != null){ process.destroy(); ファイルパスを返します}


















4. adbのスクリーンショット

$ adb shell
shell@ $ screencap /sdcard/screen.png
shell@ $ exit
$ adb pull /sdcard/screen.png

おすすめ

転載: blog.csdn.net/jun_tong/article/details/129811578