質問

可能な重複:
どのようにprogramatically受画面にスケーラビリティの問題ですね。

どのように捉えるかというandroid端末の画面でコンテンツや画像ファイルのスナップショットデータはもらえますか?るAPIを使っていたかを見たいの関係です。

ちなみ:しないカメラのスナップショットがデバイスの画面

役に立ちましたか?

解決

によると このリンク, 、Android SDKのツールディレクトリでDDMSを使用して画面キャプチャを取得することができます。

アプリケーション内でこれを行う(開発中ではなく)、そうするためのアプリケーションもあります。しかし、 @zed_0xffが指摘しているように、それは確かにrootを必要とします。

他のヒント

次のコードを使用します。

Bitmap bitmap;
View v1 = MyView.getRootView();
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);

ここ MyView それは View 画面に含める必要があります。あなたも得ることができます DrawingCache 任意から View このように(なし getRootView()).


別の方法もあります。
私たちが持っているなら ScrollView ルートビューとして、次のコードを使用する方が良い、

LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
FrameLayout root = (FrameLayout) inflater.inflate(R.layout.activity_main, null); // activity_main is UI(xml) file we used in our Activity class. FrameLayout is root view of my UI(xml) file.
root.setDrawingCacheEnabled(true);
Bitmap bitmap = getBitmapFromView(this.getWindow().findViewById(R.id.frameLayout)); // here give id of our root layout (here its my FrameLayout's id)
root.setDrawingCacheEnabled(false);

これが次のとおりです getBitmapFromView() 方法

public static Bitmap getBitmapFromView(View view) {
        //Define a bitmap with the same size as the view
        Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888);
        //Bind a canvas to it
        Canvas canvas = new Canvas(returnedBitmap);
        //Get the view's background
        Drawable bgDrawable =view.getBackground();
        if (bgDrawable!=null) 
            //has background drawable, then draw it on the canvas
            bgDrawable.draw(canvas);
        else 
            //does not have background drawable, then draw white background on the canvas
            canvas.drawColor(Color.WHITE);
        // draw the view on the canvas
        view.draw(canvas);
        //return the bitmap
        return returnedBitmap;
    }

あなたの中に隠されたコンテンツを含む画面全体を表示します ScrollView


20-04-2016のように更新されました

スクリーンショットを撮るための別のより良い方法があります。
ここで私はスクリーンショットを撮りました WebView.

WebView w = new WebView(this);
    w.setWebViewClient(new WebViewClient()
    {
        public void onPageFinished(final WebView webView, String url) {

            new Handler().postDelayed(new Runnable(){
                @Override
                public void run() {
                    webView.measure(View.MeasureSpec.makeMeasureSpec(
                                    View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED),
                            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
                    webView.layout(0, 0, webView.getMeasuredWidth(),
                            webView.getMeasuredHeight());
                    webView.setDrawingCacheEnabled(true);
                    webView.buildDrawingCache();
                    Bitmap bitmap = Bitmap.createBitmap(webView.getMeasuredWidth(),
                            webView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);

                    Canvas canvas = new Canvas(bitmap);
                    Paint paint = new Paint();
                    int height = bitmap.getHeight();
                    canvas.drawBitmap(bitmap, 0, height, paint);
                    webView.draw(canvas);

                    if (bitmap != null) {
                        try {
                            String filePath = Environment.getExternalStorageDirectory()
                                    .toString();
                            OutputStream out = null;
                            File file = new File(filePath, "/webviewScreenShot.png");
                            out = new FileOutputStream(file);

                            bitmap.compress(Bitmap.CompressFormat.PNG, 50, out);
                            out.flush();
                            out.close();
                            bitmap.recycle();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }, 1000);
        }
    });

お役に立てれば..!

Afaik、Androidのスクリーンショットをキャプチャするすべての方法は、/dev/graphics/fb0 framebufferを使用しています。これにはDDMSが含まれます。このストリームから読み取るにはルートが必要です。 DDMSはADBDを使用して情報をリクエストするため、ADBには/dev/graphics/fb0からデータを要求するために必要な権限があるため、ルートは必要ありません。

フレームバッファには、RGB565画像の2+「フレーム」が含まれています。データを読み取ることができる場合は、画像を取得するために必要なバイトの数を知るために画面解像度を知る必要があります。各ピクセルは2バイトであるため、画面RESが480x800の場合、480x800 RGB565画像には384,000ピクセルがあるため、画像の768,000バイトを読む必要があります。

新しいAndroidプラットフォームの場合、システムユーティリティを実行できます screencap/system/bin ルートの許可なしにスクリーンショットを取得するには。あなたが試すことができます /system/bin/screencap -h ADBまたは任意のシェルの下でそれを使用する方法を確認します。

ちなみに、この方法はシングルスナップショットにのみ適していると思います。画面再生のために複数のフレームをキャプチャしたい場合は、遅すぎます。より高速な画面キャプチャのための他のアプローチが存在するかどうかはわかりません。

[Androidソースコード]

C++側SurfaceFlingerをcaptureScreen APIに含まれています。これは、バインダー IPCインタフェース、還元ではなく、新たなashmem地域が含まれる原料からのピクセルの画面になります。実際のスクリーンショットが変更されたことからOpenGL.

システムのC++用クライアントのインストールのインタフェースを通じて公開されたScreenshotClientクラスで定義され <surfaceflinger_client/SurfaceComposerClient.h> Android < 4.1;Android>4.1利用 <gui/SurfaceComposerClient.h>

前JBを高め、あらゆるレベルのスクリーンショットにはC++のプログラム、これは十分:

ScreenshotClient ssc;
ssc.update();

とJB、複数のディスプレイ、かなり複雑な:

ssc.update(
    android::SurfaceComposerClient::getBuiltInDisplay(
        android::ISurfaceComposer::eDisplayIdMain));

アクセスできます:

do_something_with_raw_bits(ssc.getPixels(), ssc.getSize(), ...);

のAndroidソースコードできるような作共有ライブラリへのアクセスするAPIと、そしてなによJNIをJava.作成画面ォアプリのアプリは、 READ_FRAME_BUFFER ます。そして、次のように作成できます画面のみからフラッシュメモリ技術、すなわちその署名と同じキーとしてのシステム。(この部分だなかなか理解し、造形、野暮ったすぎやしませんか身近なものAndroidアクセス権を得ました。

こちらのコードでは、JB4.1/4.2:

#include <utils/RefBase.h>
#include <binder/IBinder.h>
#include <binder/MemoryHeapBase.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>

static void do_save(const char *filename, const void *buf, size_t size) {
    int out = open(filename, O_RDWR|O_CREAT, 0666);
    int len = write(out, buf, size);
    printf("Wrote %d bytes to out.\n", len);
    close(out);
}

int main(int ac, char **av) {
    android::ScreenshotClient ssc;
    const void *pixels;
    size_t size;
    int buffer_index;

    if(ssc.update(
        android::SurfaceComposerClient::getBuiltInDisplay(
            android::ISurfaceComposer::eDisplayIdMain)) != NO_ERROR ){
        printf("Captured: w=%d, h=%d, format=%d\n");
        ssc.getWidth(), ssc.getHeight(), ssc.getFormat());
        size = ssc.getSize();
        do_save(av[1], pixels, size);
    }
    else
        printf(" screen shot client Captured Failed");
    return 0;
}

次のライブラリを試すことができます。 Androidスクリーンショットライブラリ(ASL) ルートアクセス権限を持つことを要求することなく、Androidデバイスからスクリーンショットをプログラム的にキャプチャすることができます。代わりに、ASLはバックグラウンドで実行されているネイティブサービスを使用し、デバイスブートごとにAndroidデバッグブリッジ(ADB)を介して開始されます。

FrameBufferのように見えますが、Ryan Conradが言及したような2+フレームが常に含まれているわけではありません。私の場合、1つだけが含まれていました。フレーム/ディスプレイサイズに依存すると思います。

フレームバッファーを継続的に読み込もうとしましたが、読み取られた一定量のバイトで戻ってくるようです。私の場合、それは(3 410 432)バイトで、854*480 RGBA(3 279 360バイト)のディスプレイフレームを保存するのに十分です。はい、 FB0から出力されたバイナリのフレームは私のデバイスのRGBAです. これは、おそらくデバイスからデバイスに依存する可能性があります. 。これはあなたがそれをデコードするために重要です=)

私のデバイス/dev/graphics/fb0許可には、 ルートのみ とユーザー グループグラフィックス できる 読む FB0。 グラフィックス 制限されたグループであるため、おそらくSUコマンドを使用してルート付き電話でFB0のみにアクセスできます。

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

ADBシェルにはあります uidシェルガイドシェル, 、アプリよりもはるかに多くの権限があります。実際にそれらのアクセス許可を確認できます /system/permissions/platform.xml

これは、ルートなしでADBシェルでFB0を読み取ることができることを意味しますが、ルートなしでアプリ内で読み取ることはできません。

また、AndroidManifest.xmlでread_frame_bufferおよび/またはaccess_surface_flingerの権限を与えることは、「署名」アプリでのみ機能するため、通常のアプリに対しては何もしません。

AndroidアプリAFAIKでJavaコードからスクリーンキャプチャを実行したい場合は、ルートプロビリッジが必要です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top