プログラム的にAndroidでスクリーンショットを撮る方法は?


495

プログラムではなくコードから電話画面の選択した領域のスクリーンショットを撮るにはどうすればよいですか?


4
エミュレータからではありません。私は自分のプログラムの一部のスクリーンショットを作成する必要があり、同じプログラムでそれを使います。
korovaisdead 2010

1
もう1つの優れたリファレンス:stackoverflow.com/a/10296881/439171
Italo Borssatto

回答:


448

これが私のスクリーンショットをSDカードに保存し、後で必要に応じて使用できるようにするコードです。

まず、ファイルを保存するための適切な権限を追加する必要があります。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

そしてこれはコードです(アクティビティで実行されています):

private void takeScreenshot() {
    Date now = new Date();
    android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);

    try {
        // image naming and path  to include sd card  appending name you choose for file
        String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";

        // create bitmap screen capture
        View v1 = getWindow().getDecorView().getRootView();
        v1.setDrawingCacheEnabled(true);
        Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
        v1.setDrawingCacheEnabled(false);

        File imageFile = new File(mPath);

        FileOutputStream outputStream = new FileOutputStream(imageFile);
        int quality = 100;
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
        outputStream.flush();
        outputStream.close();

        openScreenshot(imageFile);
    } catch (Throwable e) {
        // Several error may come out with file handling or DOM
        e.printStackTrace();
    }
}

そして、これが最近生成された画像を開く方法です:

private void openScreenshot(File imageFile) {
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_VIEW);
    Uri uri = Uri.fromFile(imageFile);
    intent.setDataAndType(uri, "image/*");
    startActivity(intent);
}

これをフラグメントビューで使用する場合は、次のコマンドを使用します。

View v1 = getActivity().getWindow().getDecorView().getRootView();

の代わりに

View v1 = getWindow().getDecorView().getRootView();

takeScreenshot()関数

ダイアログにサーフェスビューが含まれている場合、このソリューションは機能しません。詳細については、次の質問に対する回答を確認してください。

Androidの表面ビューのスクリーンショットに黒い画面が表示される


23
こんにちは、mCurrentUrlMaskとは何ですか?私はこのコードを試しましたが、常にBitmap.createBitmap(v1.getDrawingCache())でNullPointerExceptionを引き起こしています。誰かが私が間違っていることを教えてもらえますか?どんな助けでもありがたいです。ありがとう。
Mitesh Sardhara 2013

4
@MiteshSardhara は、メソッドを持つAndroid APIの一意のクラスでmCurrentUrlMaskあるViewため、でなければなりませんgetRootView()。おそらくUIのビューです。
gipi 2013年

6
mCurrentUrlMaskとは何ですか。
Jayeshkumar Sojitra 2013年

37
View v1 = mCurrentUrlMask.getRootView();私が使用View v1 = getWindow().getDecorView().getRootView();したことを意図し、それは私のために動作します。
enadun 2014年

9
この回答は、質問で尋ねられた「電話画面」ではなく、アプリのみのスクリーンショットを撮っています。または、何か間違っているのですか。
AlikElzin-kilaka

126

このメソッドを呼び出して、スクリーンショットが必要な最も外側のViewGroupを渡します。

public Bitmap screenShot(View view) {
    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
            view.getHeight(), Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    view.draw(canvas);
    return bitmap;
}

9
これは受け入れられた答えよりもきれいなコードのようです。それも機能しますか?
jophde 2014年

2
私はいくつかの異なるアプリでしばらく使用しており、問題はありませんでした。
JustinMorris 14

3
アプリがバックグラウンドにある電話のスクリーンショットを取得したい場合は、何を渡しviewますか? `
AlikElzin-kilaka

2
getWindow().getDecorView().getRootView()ビューとして渡すと、画面ではなくアプリのみのスクリーンショットが撮られます。
AlikElzin-kilaka

この回答は、質問で尋ねられた「電話画面」ではなく、アプリのみのスクリーンショットを撮っています。または、何か間違っているのですか。
AlikElzin-kilaka

42

注:根ざした電話でのみ機能します

プログラム的には、adb shell /system/bin/screencap -p /sdcard/img.png以下のように実行できます

Process sh = Runtime.getRuntime().exec("su", null,null);
OutputStream os = sh.getOutputStream();
os.write(("/system/bin/screencap -p " + "/sdcard/img.png").getBytes("ASCII"));
os.flush();
os.close();
sh.waitFor();    

それから読んでimg.pngBitmapあなたの願いとして使ってください。


rootアクセスが必要ですか?
2014年

3
はい、ルートアクセスが必要です。見出しの注記を確認してください
Viswanath Lekshmanan

こんにちは、System.err : java.io.IOException: Error running exec(). Command: [su] Working Directory: null Environment: null 私のデバイスはandroid 5.0です
Eddy

@エディそれはあなたのデバイスに依存します
デミアン

結果をファイルに保存せずに直接読み取る方法はありますか?stackoverflow.com/questions/43914035
Yazan W Yusuf

35

編集:反対投票に慈悲を持ちます。私が質問に答えたとき、それは2010年に事実でした。

スクリーンショットを許可するすべてのプログラムは、根ざした電話でのみ機能します。


最近、Tegraベースのチップセットを搭載したAndroidで可能であるようです
GDR

4.0.3-それはおそらくこれらの新しい学校のテグラタブレットの1つです
GDR

AFAIKは、デバイスにスクリーンショットをキャプチャするストックアプリがある場合、フレームバッファ(画面ピクセルを含むバッファ)をキャプチャできる特別な署名権限を持つアプリです。つまり、ROMにそのようなアプリがある場合、ルート権限を取得する必要はありませんが、キャプチャを作成できるのはそのアプリだけであり、あなたのアプリではありません。
Rui Marques

2
厳密に言えば、ルートADBの「シェル」ユーザーアカウントは、意図された使用例であるため、常にこれを実行する権限を持っています。歴史的に利用できなかったのは(時々のビルドの間違いを除いて)、アプリケーションのユーザーID がそうする方法でした。
Chris Stratton、

26

この方法ではroot権限大きなコーディングは必要ありません


以下のコマンドを使用してadbシェルでスクリーンショットを撮ることができます。

input keyevent 120

このコマンドはルート権限を必要としないため、AndroidアプリケーションのJavaコードからも実行できます。

Process process;
process = Runtime.getRuntime().exec("input keyevent 120");

Androidのキーイベントコードの詳細については、http: //developer.android.com/reference/android/view/KeyEvent.htmlをご覧ください。

ここでは使用しました。 KEYCODE_SYSRQの値は120で、システム要求/画面印刷キーに使用されます。


CJBSが言ったように、出力画像は/ sdcard / Pictures / Screenshotsに保存されます


出力画像はここに保存されます:/sdcard/Pictures/Screenshots
CJBS '29

root権限が必要ですか?
Taranmeet Singh 2015

1
マシュマロに効きますか?またはサービスのバックグラウンドで動作します@JeegarPatel
karanatwal.github.io

2
プログラムでは機能しませんが、シェルからは機能します。ヌガーで試してみました。
mehmet6parmak 2017年

1
su -c "input keyevent 120"大丈夫です!
ipcjs 2017

17

Mualigの回答は非常に良いですが、Ewoksが説明しているのと同じ問題がありました。したがって、十分な場合もあれば、黒の背景に黒のテキストが表示される場合もあります(テーマによって異なります)。

このソリューションは、MualigコードとRobotiumで見つけたコードに大きく基づいています。drawメソッドを直接呼び出すことで、描画キャッシュの使用を破棄しています。その前に、現在のアクティビティから背景ドローアブルを取得して、最初にそれを描画しようとします。

// Some constants
final static String SCREENSHOTS_LOCATIONS = Environment.getExternalStorageDirectory().toString() + "/screenshots/";

// Get device dimmensions
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);

// Get root view
View view = mCurrentUrlMask.getRootView();

// Create the bitmap to use to draw the screenshot
final Bitmap bitmap = Bitmap.createBitmap(size.x, size.y, Bitmap.Config.ARGB_4444);
final Canvas canvas = new Canvas(bitmap);

// Get current theme to know which background to use
final Activity activity = getCurrentActivity();
final Theme theme = activity.getTheme();
final TypedArray ta = theme
    .obtainStyledAttributes(new int[] { android.R.attr.windowBackground });
final int res = ta.getResourceId(0, 0);
final Drawable background = activity.getResources().getDrawable(res);

// Draw background
background.draw(canvas);

// Draw views
view.draw(canvas);

// Save the screenshot to the file system
FileOutputStream fos = null;
try {
    final File sddir = new File(SCREENSHOTS_LOCATIONS);
    if (!sddir.exists()) {
        sddir.mkdirs();
    }
    fos = new FileOutputStream(SCREENSHOTS_LOCATIONS
            + System.currentTimeMillis() + ".jpg");
    if (fos != null) {
        if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos)) {
            Log.d(LOGTAG, "Compress/Write failed");
        }
        fos.flush();
        fos.close();
    }

} catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

私のアクティビティにandroid:cacheColorHint = "#00000000"のリストビューがあり、このコードを使用してスクリーンショットを作成しましたが、テーマから取得した背景が黒であることがわかったため、黒の背景が表示されます。リストビュー?
Wangchao0721 2012

アクティビティactivity = getCurrentActivityは、Eroorに未定義のメソッドを提供します。
Shabbir Dhangot 2014

17
private void captureScreen() {
    View v = getWindow().getDecorView().getRootView();
    v.setDrawingCacheEnabled(true);
    Bitmap bmp = Bitmap.createBitmap(v.getDrawingCache());
    v.setDrawingCacheEnabled(false);
    try {
        FileOutputStream fos = new FileOutputStream(new File(Environment
                .getExternalStorageDirectory().toString(), "SCREEN"
                + System.currentTimeMillis() + ".png"));
        bmp.compress(CompressFormat.PNG, 100, fos);
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

マニフェストに権限を追加する

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

マシュマロ以上のバージョンをサポートするには、以下のコードをアクティビティのonCreateメソッドに追加してください

ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},00);

必要:<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
AndroidGuy

4
この回答は、質問で尋ねられた「電話画面」ではなく、アプリのみのスクリーンショットを撮っていますか、それとも何か問題がありますか?
AlikElzin-kilaka

リストビューのアイテムのスクリーンショットが必要な場合はどうなりますか?
Anshul Tyagi 2016

アダプターからキャプチャーしたいのですが、どのようにすればよいですか?
ディープデイブ

16

参考までに、(アプリのアクティビティだけでなく)画面をキャプチャする1つの方法は、フレームバッファ(デバイス/ dev / graphics / fb0)をキャプチャすることです。これを行うには、root権限を持っているか、アプリが署名権限を持つアプリである必要があります(「リクエストしているアプリケーションが、権限を宣言したアプリケーションと同じ証明書で署名されている場合にのみシステムが付与する権限」)-これは独自のROMをコンパイルしない限り、ほとんどありません。

私がテストしたいくつかのデバイスからの各フレームバッファキャプチャには、正確に 1つのスクリーンショットが含まれていました。人々はそれをもっと多く含むと報告しました、それはフレーム/ディスプレイサイズに依存すると思います。

フレームバッファを継続的に読み取ろうとしましたが、一定量のバイトが読み取られたために戻ってきたようです。私の場合、これは(3 410 432)バイトで、854 * 480 RGBA(3 279 360バイト)の表示フレームを格納するのに十分です。はい、fb0から出力されるバイナリのフレームは、私のデバイスではRGBAです。これは、デバイスによって異なります。これはデコードするために重要です=)

私のデバイスでは、/ dev / graphics / fb0権限は、rootとグループグラフィックスのユーザーのみがfb0を読み取ることができるようになっています。

グラフィックは制限されたグループであるため、おそらくsuコマンドを使用してroot化された電話でのみfb0にアクセスします。

Androidアプリには、ユーザーID(uid)= app _ ##およびグループID(guid)= app _ ##があります。

adbシェルにuid = shellguid = shellがあり、アプリよりもはるかに多くの権限があります。これらの権限は/system/permissions/platform.xmlで実際に確認できます

つまり、rootなしでadbシェルでfb0を読み取ることはできますが、rootなしではアプリ内でそれを読み取ることはできません。

また、AndroidManifest.xmlにREAD_FRAME_BUFFERやACCESS_SURFACE_FLINGER権限を付与しても、通常のアプリでは何も行われません。これは、これらのアプリが「署名」アプリでのみ機能するためです。

詳細については、この閉じたスレッドも確認してください。


2
これは一部の電話で機能します(動作しましたか?)。ただし、GPUベースの電話は必ずしもアプリケーションプロセッサにリニアフレームバッファーを提供するとは限らないことに注意してください。
Chris Stratton

15

私の解決策は:

public static Bitmap loadBitmapFromView(Context context, View v) {
    DisplayMetrics dm = context.getResources().getDisplayMetrics(); 
    v.measure(MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.EXACTLY),
            MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.EXACTLY));
    v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
    Bitmap returnedBitmap = Bitmap.createBitmap(v.getMeasuredWidth(),
            v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(returnedBitmap);
    v.draw(c);

    return returnedBitmap;
}

そして

public void takeScreen() {
    Bitmap bitmap = ImageUtils.loadBitmapFromView(this, view); //get Bitmap from the view
    String mPath = Environment.getExternalStorageDirectory() + File.separator + "screen_" + System.currentTimeMillis() + ".jpeg";
    File imageFile = new File(mPath);
    OutputStream fout = null;
    try {
        fout = new FileOutputStream(imageFile);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
        fout.flush();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        fout.close();
    }
}

画像は外部ストレージフォルダに保存されます。


1
finallyブロックでFileOutputStreamを閉じる必要があります。例外が発生した場合、ストリームは閉じられません。
Wotuu 2014年

viewあなたは何を渡していImageUtils.loadBitmapFromView(this, view)ますか?
AlikElzin-kilaka

1
なぜv.layout(0、0、v.getMeasuredWidth()、v.getMeasuredHeight());を使用するのですか??それは見方を変えませんか(v)?
serj

11

次のライブラリを試すことができます。http//code.google.com/p/android-screenshot-library/ Androidスクリーンショットライブラリ(ASL)を使用すると、ルートアクセス権限がなくても、プログラムでAndroidデバイスからスクリーンショットをキャプチャできます。代わりに、ASLはバックグラウンドで実行されているネイティブサービスを利用し、デバイスの起動ごとにAndroid Debug Bridge(ADB)を介して開始されます。


1
私はこれを試しましたが、実行中のアプリのみのスクリーンショットが撮られます。ホームスクリーンのスクリーンショットを撮りたいのなら、それは役に立ちません。そのコードでホーム画面のスクリーンショットを撮る方法を教えてください。
Jana

1
@ Janardhanan.S:これは質問が求めているものです。別の質問をする代わりに、新しい答えで詳しく説明できますか。
trgraglia

3
私と同じ問題..「ネイティブサービスが実行されていません!!」
Yogesh Maheshwari 2012

1
私と同じ "Native Service Not Running !!" ....誰かがここにヘルプテキストを追加できますか?
Pankaj Kumar

1
こっちも一緒!「ネイティブサービスが実行されていません!!」また、最新バージョン1.2では、SocketなどのAPI LEVEL 19クラスを使用しています。
user347187 14

10

上記の@JustinMorrisとここの@NiravDangiの回答に基づいて、https: //stackoverflow.com/a/8504958/2232148 ビューの背景と前景を取得し、次のように組み立てる必要があります。

public static Bitmap takeScreenshot(View view, Bitmap.Config quality) {
    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), quality);
    Canvas canvas = new Canvas(bitmap);

    Drawable backgroundDrawable = view.getBackground();
    if (backgroundDrawable != null) {
        backgroundDrawable.draw(canvas);
    } else {
        canvas.drawColor(Color.WHITE);
    }
    view.draw(canvas);

    return bitmap;
}

品質パラメーターは、Bitmap.Configの定数を受け取ります。通常はBitmap.Config.RGB_565またはBitmap.Config.ARGB_8888です。


背景がnullの場合に白い色でキャンバスを描くと、私にとってはうまくいきました。オリバーに感謝
Shaleen

8
public class ScreenShotActivity extends Activity{

private RelativeLayout relativeLayout;
private Bitmap myBitmap;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    relativeLayout = (RelativeLayout)findViewById(R.id.relative1);
    relativeLayout.post(new Runnable() {
        public void run() {

            //take screenshot
            myBitmap = captureScreen(relativeLayout);

            Toast.makeText(getApplicationContext(), "Screenshot captured..!", Toast.LENGTH_LONG).show();

            try {
                if(myBitmap!=null){
                    //save image to SD card
                    saveImage(myBitmap);
                }
                Toast.makeText(getApplicationContext(), "Screenshot saved..!", Toast.LENGTH_LONG).show();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    });

}

public static Bitmap captureScreen(View v) {

    Bitmap screenshot = null;
    try {

        if(v!=null) {

            screenshot = Bitmap.createBitmap(v.getMeasuredWidth(),v.getMeasuredHeight(), Config.ARGB_8888);
            Canvas canvas = new Canvas(screenshot);
            v.draw(canvas);
        }

    }catch (Exception e){
        Log.d("ScreenShotActivity", "Failed to capture screenshot because:" + e.getMessage());
    }

    return screenshot;
}

public static void saveImage(Bitmap bitmap) throws IOException{

    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 40, bytes);
    File f = new File(Environment.getExternalStorageDirectory() + File.separator + "test.png");
    f.createNewFile();
    FileOutputStream fo = new FileOutputStream(f);
    fo.write(bytes.toByteArray());
    fo.close();
}

}

権限を追加

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

この回答は、質問で尋ねられた「電話画面」ではなく、アプリのみのスクリーンショットを撮っていますか、それとも何か問題がありますか?
AlikElzin-kilaka

7

このようなことを試すことができます

レイアウトやビューからビットマップキャッシュを取得するには、まずsetDrawingCacheEnabledレイアウト(linearlayoutまたはrelativelayout、またはビュー)に行かなければなりません。

その後

Bitmap bm = layout.getDrawingCache()

次に、ビットマップで好きなことを行います。画像ファイルに変換するか、ビットマップのURIを別の場所に送信します。


1
ビットマップに書き込むのがアプリの場合、これが最適な方法です。また、リストビューのNotify ...()のように、キャッシュを取得する前に遅延があるメソッドにも注意してください。
trgraglia

それだけではありません。最初にレイアウトを画面に表示する必要があります。結局のところ、これが「キャッシュ」です。ビューを隠し、バックグラウンドでスクリーンショットを撮ることを試みましたが(理論的には)機能しませんでした。
Kevin Tan

他のソリューションよりもはるかに効率的
sivi 2015

6

GLSurfaceViewをキャプチャしたい場合、getDrawingCacheまたはdrawing to canvasメソッドは機能しません。

フレームがレンダリングされた後、OpenGLフレームバッファーの内容を読み取る必要があります。ここに良い答えがあります


6

からスクリーンショットを取りView、Bitmapオブジェクトを提供するか、任意のパスに直接保存する単純なライブラリを作成しました

https://github.com/abdallahalaraby/Blink


根ざした電話が必要ですか?
Nilesh Agrawal、2015

1
応援は必要ありません:)
Abdallah Alaraby '10

使用法Screenshot.takeScreenshot(view, mPath); imageView.setImageBitmap(Screenshot.getBitmapScreenshot(view, mPath)); では、現在のアクティビティのビューを取得する方法について説明しました。XMLのIDを使用したくありません。
Nilesh Agrawal、2015

takeScreenshotForScreen()代わりに使用してください。
Abdallah Alaraby 2017年

6

短い道は

FrameLayout layDraw = (FrameLayout) findViewById(R.id.layDraw); /*Your root view to be part of screenshot*/
layDraw.buildDrawingCache();
Bitmap bmp = layDraw.getDrawingCache();

5

タラロカの答えを拡張するだけです。機能させるには、次の行を追加する必要があります。画像名を静的にしました。動的な画像名が必要な場合は、taralocaのタイムスタンプ変数を使用してください。

    // Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};

private void verifyStoragePermissions() {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
    }else{
        takeScreenshot();
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        if (requestCode == REQUEST_EXTERNAL_STORAGE) {
            takeScreenshot();
        }
    }
}

また、AndroidManifest.xmlファイルでは、次のエントリが必須です。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

4

fragment 以下からスクリーンショットを撮りたい場合:

  1. オーバーライド onCreateView()

             @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                     Bundle savedInstanceState) {
                // Inflate the layout for this fragment
                View view = inflater.inflate(R.layout.fragment_one, container, false);
                mView = view;
            }
  2. スクリーンショットを撮るロジック:

     button.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
         View view =  mView.findViewById(R.id.scrollView1);
          shareScreenShotM(view, (NestedScrollView) view); 
     }
  3. 方法shareScreenShotM)()

    public void shareScreenShotM(View view, NestedScrollView scrollView){
    
         bm = takeScreenShot(view,scrollView);  //method to take screenshot
        File file = savePic(bm);  // method to save screenshot in phone.
        }
  4. メソッドtakeScreenShot():

             public Bitmap takeScreenShot(View u, NestedScrollView z){
    
                u.setDrawingCacheEnabled(true);
                int totalHeight = z.getChildAt(0).getHeight();
                int totalWidth = z.getChildAt(0).getWidth();
    
                Log.d("yoheight",""+ totalHeight);
                Log.d("yowidth",""+ totalWidth);
                u.layout(0, 0, totalWidth, totalHeight);
                u.buildDrawingCache();
                Bitmap b = Bitmap.createBitmap(u.getDrawingCache());
                u.setDrawingCacheEnabled(false);
                u.destroyDrawingCache();
                 return b;
            }
  5. メソッドsavePic():

     public static File savePic(Bitmap bm){
    
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            bm.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
             File sdCardDirectory =  new File(Environment.getExternalStorageDirectory() + "/Foldername");
    
           if (!sdCardDirectory.exists()) {
                sdCardDirectory.mkdirs();
          }
           //  File file = new File(dir, fileName);
          try {
             file = new File(sdCardDirectory, Calendar.getInstance()
                .getTimeInMillis() + ".jpg");
            file.createNewFile();
            new FileOutputStream(file).write(bytes.toByteArray());
            Log.d("Fabsolute", "File Saved::--->" + file.getAbsolutePath());
             Log.d("Sabsolute", "File Saved::--->" + sdCardDirectory.getAbsolutePath());
         } catch (IOException e) {
              e.printStackTrace();
          }
         return file;
       }

アクティビティでは、View v1 = getWindow().getDecorView().getRootView();代わりに単に使用できますmView


3

この質問に対する回答のほとんどは、Canvas描画メソッドまたは描画キャッシュメソッドを使用しています。ただし、このView.setDrawingCache()メソッドはAPI 28では非推奨です。現在、スクリーンショットを作成するために推奨されるAPIは、PixelCopyAPI 24から利用できるクラスです(ただし、Windowパラメーターを受け入れるメソッドはAPI 26 == Android 8.0 Oreoから利用できます)。を取得するためのサンプルKotlinコードを次に示しますBitmap

@RequiresApi(Build.VERSION_CODES.O)
fun saveScreenshot(view: View) {
    val window = (view.context as Activity).window
    if (window != null) {
        val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
        val locationOfViewInWindow = IntArray(2)
        view.getLocationInWindow(locationOfViewInWindow)
        try {
            PixelCopy.request(window, Rect(locationOfViewInWindow[0], locationOfViewInWindow[1], locationOfViewInWindow[0] + view.width, locationOfViewInWindow[1] + view.height), bitmap, { copyResult ->
                if (copyResult == PixelCopy.SUCCESS) {
                    saveBitmap(bitmap)
                }
                // possible to handle other result codes ...
            }, Handler())
        } catch (e: IllegalArgumentException) {
            // PixelCopy may throw IllegalArgumentException, make sure to handle it
        }
    }
}

drawingCacheソリューションに対するPixelCopyの問題は、可視ピクセルのみをキャプチャするように見えることです。残りは私にとって黒です。そのため、スクロール可能でフレームの外にあるものを共有することはできません。これに対する解決策はありますか?
ヘニング

あなたが正しいです。同様に、スクリーンショットを作成したいビューの上に別のビューが表示されている場合(ドロワーが開いているときなど)、問題が発生する可能性があります。これらのケースでは、私はちょうど古いキャンバス方法:(使用
ミロシュČernilovský

1
PixelCopyを使用して、実行中のアプリのスクリーンショットを撮ることはできますか?
アミールRezaei

2

システムアプリケーションのみ!

Process process;
process = Runtime.getRuntime().exec("screencap -p " + outputPath);
process.waitFor();

注:システムアプリケーションは、このコマンドを実行するために「su」を実行する必要はありません。


2

パラメータビューはルートレイアウトオブジェクトです。

public static Bitmap screenShot(View view) {
                    Bitmap bitmap = null;
                    if (view.getWidth() > 0 && view.getHeight() > 0) {
                        bitmap = Bitmap.createBitmap(view.getWidth(),
                                view.getHeight(), Bitmap.Config.ARGB_8888);
                        Canvas canvas = new Canvas(bitmap);
                        view.draw(canvas);
                    }
                    return bitmap;
                }

2

全ページスクロールのスクリーンショット

完全なビューのスクリーンショット(スクロールビューなどを含む)をキャプチャする場合は、このライブラリで確認してください

https://github.com/peter1492/LongScreenshot

Gradelをインポートして、BigScreenshotのオブジェクトを作成するだけです。

BigScreenshot longScreenshot = new BigScreenshot(this, x, y);

コールバックは、スクリーンビューグループを自動的にスクロールし、最後に組み立てられたスクリーンショットのビットマップを使用して受信されます。

@Override public void getScreenshot(Bitmap bitmap) {}

ギャラリーに保存できるもの、または後で必要な用途に使用できるもの


1

Androidでビューのスクリーンショットを撮ります。

public static Bitmap getViewBitmap(View v) {
    v.clearFocus();
    v.setPressed(false);

    boolean willNotCache = v.willNotCacheDrawing();
    v.setWillNotCacheDrawing(false);

    int color = v.getDrawingCacheBackgroundColor();
    v.setDrawingCacheBackgroundColor(0);

    if (color != 0) {
        v.destroyDrawingCache();
    }
    v.buildDrawingCache();
    Bitmap cacheBitmap = v.getDrawingCache();
    if (cacheBitmap == null) {
        return null;
    }

    Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);

    v.destroyDrawingCache();
    v.setWillNotCacheDrawing(willNotCache);
    v.setDrawingCacheBackgroundColor(color);

    return bitmap;
}

-1

RelativeLayoutやLinearLayoutなどのビューまたはレイアウトをキャプチャする場合は、次のコードを使用します。

LinearLayout llMain = (LinearLayout) findViewById(R.id.linearlayoutMain);
Bitmap bm = loadBitmapFromView(llMain);

これで、このビットマップをデバイスストレージに保存できます。

FileOutputStream outStream = null;
File f=new File(Environment.getExternalStorageDirectory()+"/Screen Shots/");
f.mkdir();
String extStorageDirectory = f.toString();
File file = new File(extStorageDirectory, "my new screen shot");
pathOfImage = file.getAbsolutePath();
try {
    outStream = new FileOutputStream(file);
    bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
    Toast.makeText(getApplicationContext(), "Saved at "+f.getAbsolutePath(), Toast.LENGTH_LONG).show();
    addImageGallery(file);
    //mail.setEnabled(true);
    flag=true;
} catch (FileNotFoundException e) {e.printStackTrace();}
try {
    outStream.flush();
    outStream.close();
} catch (IOException e) {e.printStackTrace();}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.