Bagaimana cara mengambil screenshot di Android?

495

Bagaimana saya bisa mengambil tangkapan layar dari area tertentu pada layar ponsel bukan oleh program apa pun tetapi dari kode?

korovaisdead
sumber
4
Bukan dari emulator. Saya perlu membuat tangkapan layar bagian dari program saya, dan melakukannya dengan program yang sama.
korovaisdead
1
Referensi bagus lainnya: stackoverflow.com/a/10296881/439171
Italo Borssatto

Jawaban:

448

Berikut adalah kode yang memungkinkan tangkapan layar saya disimpan di kartu SD dan digunakan nanti untuk apa pun kebutuhan Anda:

Pertama, Anda perlu menambahkan izin yang tepat untuk menyimpan file:

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

Dan ini adalah kode (berjalan dalam suatu Aktivitas):

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();
    }
}

Dan ini adalah bagaimana Anda dapat membuka gambar yang baru saja dibuat:

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);
}

Jika Anda ingin menggunakan ini pada tampilan fragmen kemudian gunakan:

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

dari pada

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

pada fungsi takeScreenshot ()

Catatan :

Solusi ini tidak berfungsi jika dialog Anda berisi tampilan permukaan. Untuk perincian, silakan periksa jawaban untuk pertanyaan berikut:

Android Ambil Screenshot dari Surface View Menunjukkan Black Screen

taraloca
sumber
23
Hai, Bisakah Anda jelaskan apa itu mCurrentUrlMask? Saya telah mencoba kode ini tetapi selalu memberi saya NullPointerException di Bitmap.createBitmap (v1.getDrawingCache ()), adakah yang bisa mengatakan apa yang saya lakukan salah.? Bantuan apa pun dihargai. Terima kasih.
Mitesh Sardhara
4
@MiteshSardhara mCurrentUrlMaskharus Viewmerupakan kelas unik di Android API yang memiliki getRootView()metode. Mungkin tampilan di UI.
gipi
6
Bisakah Anda memberi tahu saya apa itu, mCurrentUrlMask?
Jayeshkumar Sojitra
37
Insted dari View v1 = mCurrentUrlMask.getRootView();saya telah menggunakan View v1 = getWindow().getDecorView().getRootView();dan berfungsi untuk saya.
enadun
9
Jawaban ini mengambil tangkapan layar hanya dari aplikasi - bukan "layar ponsel" seperti yang ditanyakan dalam pertanyaan - atau apakah saya melakukan sesuatu yang salah.
AlikElzin-kilaka
126

Panggil metode ini, melewati paling luar ViewGroup yang Anda inginkan tangkapan layar:

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;
}
JustinMorris
sumber
9
Ini sepertinya kode yang lebih bersih daripada jawaban yang diterima. Apakah itu berkinerja baik?
Jophde
2
Saya telah menggunakannya untuk sementara waktu di beberapa aplikasi yang berbeda dan belum memiliki masalah.
JustinMorris
3
Jika Anda ingin mendapatkan tangkapan layar ponsel, di mana aplikasi Anda berada di latar belakang, apa yang Anda lewati sebagai view? `
AlikElzin-kilaka
2
Lewat getWindow().getDecorView().getRootView()sebagai hasil tampilan dalam mengambil tangkapan layar hanya aplikasi - bukan layar.
AlikElzin-kilaka
Jawaban ini mengambil tangkapan layar hanya dari aplikasi - bukan "layar ponsel" seperti yang ditanyakan dalam pertanyaan - atau apakah saya melakukan sesuatu yang salah.
AlikElzin-kilaka
42

Catatan: hanya berfungsi untuk telepon yang di-rooting

Secara pemrograman, Anda dapat menjalankan adb shell /system/bin/screencap -p /sdcard/img.pngseperti di bawah ini

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();    

kemudian baca img.pngsebagai Bitmapdan gunakan sesuai keinginan Anda.

Viswanath Lekshmanan
sumber
Apakah perlu akses root?
zoom
3
Ya, Anda memerlukan akses root. Silakan periksa Catatan di pos
Viswanath Lekshmanan
Hai, saya punya System.err : java.io.IOException: Error running exec(). Command: [su] Working Directory: null Environment: null , perangkat saya android 5.0
Eddy
@ Eddy Itu tergantung pada perangkat Anda
Demian
Apakah ada cara untuk membaca output secara langsung tanpa menyimpan hasilnya ke dalam file kemudian membacanya lagi? stackoverflow.com/questions/43914035
Yazan W Yusuf
35

EDIT: berbelas kasihan dengan downvotes. Memang benar pada tahun 2010 ketika saya menjawab pertanyaan itu.

Semua program yang memungkinkan tangkapan layar hanya berfungsi pada telepon yang di-rooting.

GDR
sumber
Tampaknya hari ini dimungkinkan pada Android dengan chipset berbasis Tegra
GDR
4.0.3 - maka itu mungkin salah satu tablet tegra sekolah baru ini
GDR
AFAIK ketika perangkat memiliki aplikasi stok untuk mengambil tangkapan layar, itu adalah aplikasi dengan hak istimewa tanda tangan khusus yang memungkinkannya untuk menangkap framebuffer (buffer dengan berisi piksel layar). Jadi memang benar, jika ROM Anda memiliki aplikasi seperti itu, Anda tidak perlu di-root, tetapi hanya aplikasi yang dapat menangkap, bukan milik Anda.
Rui Marques
2
Sebenarnya, bersama dengan root akun pengguna "shell" ADB selalu memiliki izin untuk melakukan hal ini karena itu adalah kasus penggunaan yang dimaksud. Apa yang tidak tersedia secara historis (kecuali pada bangunan sesekali sebagai kesalahan) adalah cara bagi id pengguna aplikasi untuk melakukannya.
Chris Stratton
26

Tidak ada izin root atau tidak ada pengkodean besar yang diperlukan untuk metode ini.


Pada adb shell menggunakan perintah di bawah ini Anda dapat mengambil screenshot.

input keyevent 120

Perintah ini tidak memerlukan izin root apa pun sehingga Anda juga dapat melakukan dari kode java aplikasi android.

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

Lebih lanjut tentang kode keyevent di android lihat http://developer.android.com/reference/android/view/KeyEvent.html

Di sini kita telah menggunakan. KEYCODE_SYSRQ nilainya 120 dan digunakan untuk kunci Permintaan Sistem / Layar Cetak.


Seperti yang dikatakan CJBS, Gambar output akan disimpan di / sdcard / Pictures / Screenshot

Jeegar Patel
sumber
Gambar output akan disimpan di sini:/sdcard/Pictures/Screenshots
CJBS
apakah itu memerlukan izin root ??
Taranmeet Singh
1
apakah ini akan bekerja di marshmallow? atau akankah ini berfungsi di latar belakang layanan @JeegarPatel
karanatwal.github.io
2
tidak bekerja secara pemrograman, tetapi bekerja dari shell. Mencoba dengan nougat.
mehmet6parmak
1
su -c "input keyevent 120"ok !!
ipcjs
17

Jawaban Mualig sangat bagus, tetapi saya memiliki masalah yang sama yang dijelaskan Ewoks, saya tidak mendapatkan latar belakang. Jadi kadang-kadang cukup baik dan kadang-kadang saya mendapatkan teks hitam di atas latar belakang hitam (tergantung pada temanya).

Solusi ini sangat berbasis pada kode Mualig dan kode yang saya temukan di Robotium. Saya membuang penggunaan draw cache dengan menelepon langsung ke metode draw. Sebelum itu saya akan mencoba untuk mendapatkan latar belakang yang dapat digambar dari aktivitas saat ini untuk menggambarnya terlebih dahulu.

// 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();
}
xamar
sumber
Saya memiliki listview dengan android: cacheColorHint = "# 00000000" di aktivitas saya, dan saya menggunakan kode ini untuk tangkapan layar, saya masih memiliki latar belakang hitam, karena saya menemukan bahwa latar belakang yang didapat dari tema berwarna hitam, bagaimana saya bisa menangani ini listview?
Wangchao0721
Aktivitas aktivitas = getCurrentActivity memberikan metode terdefinisi Eroor.
Shabbir Dhangot
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();
    }
}

Tambahkan izin di manifes

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

Untuk Mendukung Marshmallow atau versi di atas, silakan tambahkan kode di bawah ini dalam aktivitas metode onCreate

ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},00);
Coder gila
sumber
Membutuhkan: <menggunakan-izin android: name = "android.permission.WRITE_EXTERNAL_STORAGE" />
AndroidGuy
4
Jawaban ini mengambil tangkapan layar hanya dari aplikasi - bukan "layar ponsel" seperti yang ditanyakan dalam pertanyaan - atau apakah saya melakukan sesuatu yang salah?
AlikElzin-kilaka
Bagaimana dengan jika saya perlu tangkapan layar dari item tampilan daftar?
Anshul Tyagi
saya ingin menangkap dari adaptor tahu bagaimana saya bisa melakukannya?
Deep Dave
16

Sebagai referensi, salah satu cara untuk menangkap layar (dan bukan hanya aktivitas aplikasi Anda) adalah dengan menangkap framebuffer (perangkat / dev / graphics / fb0). Untuk melakukan ini, Anda harus memiliki hak akses root atau aplikasi Anda harus merupakan aplikasi dengan izin tanda tangan ("Izin yang diberikan sistem hanya jika aplikasi yang meminta ditandatangani dengan sertifikat yang sama dengan aplikasi yang menyatakan izin") - yang merupakan sangat tidak mungkin kecuali Anda mengkompilasi ROM Anda sendiri.

Setiap tangkapan framebuffer, dari beberapa perangkat yang telah saya uji, berisi persis satu tangkapan layar. Orang-orang telah melaporkannya mengandung lebih banyak, saya kira itu tergantung pada ukuran bingkai / tampilan.

Saya mencoba membaca framebuffer secara terus-menerus tetapi sepertinya mengembalikan sejumlah byte yang telah dibaca. Dalam kasus saya yaitu (3 410 432) byte, yang cukup untuk menyimpan bingkai tampilan 854 * 480 RGBA (3 279 360 byte). Ya, frame, dalam biner, yang dikeluarkan dari fb0 adalah RGBA di perangkat saya. Ini kemungkinan besar akan tergantung dari perangkat ke perangkat. Ini akan penting bagi Anda untuk memecahkan kode itu =)

Di perangkat saya / dev / graphics / fb0 izin sehingga hanya root dan pengguna dari grup grafik dapat membaca fb0.

grafis adalah grup terbatas sehingga Anda mungkin hanya akan mengakses fb0 dengan ponsel yang di-root menggunakan perintah su.

Aplikasi Android memiliki id pengguna (uid) = app _ ## dan id grup (guid) = app _ ## .

adb shell memiliki uid = shell dan guid = shell , yang memiliki lebih banyak izin daripada aplikasi. Anda sebenarnya dapat memeriksa izin tersebut di /system/permissions/platform.xml

Ini berarti Anda akan dapat membaca fb0 di adb shell tanpa root tetapi Anda tidak akan membacanya di dalam aplikasi tanpa root.

Juga, memberikan izin READ_FRAME_BUFFER dan / atau ACCESS_SURFACE_FLINGER di AndroidManifest.xml tidak akan melakukan apa pun untuk aplikasi reguler karena ini hanya akan berfungsi untuk aplikasi ' tanda tangan '.

Periksa juga utas tertutup ini untuk detail lebih lanjut.

Rui Marques
sumber
2
Ini berfungsi (berfungsi?) Pada beberapa ponsel, tetapi perhatikan bahwa ponsel berbasis GPU tidak selalu menyediakan framebuffer linier untuk prosesor aplikasi.
Chris Stratton
15

Solusi saya adalah:

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;
}

dan

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();
    }
}

Gambar disimpan dalam folder penyimpanan eksternal.

validcat
sumber
1
Anda harus menutup FileOutputStream di blok akhirnya. Jika Anda menemukan pengecualian sekarang aliran tidak akan ditutup.
Wotuu
Apa yang viewAnda sampaikan ImageUtils.loadBitmapFromView(this, view)?
AlikElzin-kilaka
1
mengapa Anda menggunakan v.layout (0, 0, v.getMeasuredWidth (), v.getMeasuredHeight ()); ? Bukankah itu mengubah tampilan (v)?
serj
11

Anda dapat mencoba perpustakaan berikut ini: http://code.google.com/p/android-screenshot-library/ Android Screenshot Library (ASL) memungkinkan untuk menangkap tangkapan layar dari perangkat Android secara terprogram tanpa persyaratan memiliki hak akses root. Sebaliknya, ASL menggunakan layanan asli yang berjalan di latar belakang, dimulai melalui Android Debug Bridge (ADB) satu kali per boot perangkat.

Kuba
sumber
1
Saya mencoba ini. Tapi itu membutuhkan tangkapan layar dari aplikasi yang berjalan saja. Tidak bisa membantu jika saya ingin mengambil tangkapan layar homescreen. bagaimana cara mengambil tangkapan layar homescreen dengan kode itu?
Jana
1
@ Janardhanan.S: Ini adalah pertanyaan yang ditanyakan. Bisakah Anda menguraikan jawaban baru alih-alih mengajukan pertanyaan terpisah.
trgraglia
3
Masalah yang sama dengan saya .. "Layanan Asli Tidak Berjalan !!"
Yogesh Maheshwari
1
Sama dengan saya "Layanan Asli Tidak Berjalan !!" .... bisakah ada yang menambahkan teks bantuan di sini?
Pankaj Kumar
1
sama disini! "Layanan Asli Tidak Berjalan !!" dan dalam versi terbaru 1.2 mereka menggunakan kelas API LEVEL 19, seperti Socket misalnya.
user347187
10

Berdasarkan jawaban @JustinMorris di atas dan @NiravDangi di sini https://stackoverflow.com/a/8504958/2232148 kita harus mengambil latar belakang dan latar depan tampilan dan mengumpulkannya seperti ini:

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;
}

Parameter kualitas mengambil konstanta Bitmap.Config, biasanya salah satu Bitmap.Config.RGB_565atau Bitmap.Config.ARGB_8888.

Oliver Hausler
sumber
menggambar kanvas dengan warna putih di latar belakang adalah nol melakukan trik untuk saya. Terima kasih Oliver
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();
}

}

TAMBAHKAN IZIN

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Vaishali Sutariya
sumber
Jawaban ini mengambil tangkapan layar hanya dari aplikasi - bukan "layar ponsel" seperti yang ditanyakan dalam pertanyaan - atau apakah saya melakukan sesuatu yang salah?
AlikElzin-kilaka
7

Anda dapat mencoba melakukan sesuatu seperti ini,

Mendapatkan cache bitmap dari tata letak atau tampilan dengan melakukan sesuatu seperti Pertama, Anda harus setDrawingCacheEnabledmenggunakan tata letak (linearlayout atau relativelayout, atau tampilan)

kemudian

Bitmap bm = layout.getDrawingCache()

Kemudian Anda melakukan apa pun yang Anda inginkan dengan bitmap. Baik mengubahnya menjadi file gambar, atau mengirim uri bitmap ke tempat lain.

Kevin Tan
sumber
1
Ini adalah metode terbaik jika Anda menulis ke bitmap. Berhati-hatilah dengan metode yang memiliki penundaan sebelum mengambil cache ... seperti Notify ... () untuk tampilan daftar.
trgraglia
Bukan hanya itu. Tata letak harus ditampilkan di layar terlebih dahulu. Itu adalah "cache" yang Anda dapatkan setelah semua. Mencoba menyembunyikan tampilan dan mengambil tangkapan layar di latar belakang (secara teori), tetapi tidak berhasil.
Kevin Tan
Jauh lebih efisien daripada solusi lain
sivi
6

Bagi mereka yang ingin menangkap GLSurfaceView, metode getDrawingCache atau menggambar ke kanvas tidak akan berfungsi.

Anda harus membaca konten framebuffer OpenGL setelah bingkai dibuat. Ada jawaban yang bagus di sini

rockeye
sumber
6

Saya telah membuat perpustakaan sederhana yang mengambil tangkapan layar dari Viewdan memberi Anda objek Bitmap atau menyimpannya langsung ke jalur apa pun yang Anda inginkan

https://github.com/abdallahalaraby/Blink

Abdallah Alaraby
sumber
Apakah ini memerlukan ponsel yang di-rooting?
Nilesh Agrawal
1
Tidak diperlukan rooting :)
Abdallah Alaraby
Dalam penggunaannya disebutkan Screenshot.takeScreenshot(view, mPath); imageView.setImageBitmap(Screenshot.getBitmapScreenshot(view, mPath)); bagaimana cara mendapatkan aktivitas saat ini. Saya tidak ingin menggunakan id xml.
Nilesh Agrawal
gunakan takeScreenshotForScreen()saja.
Abdallah Alaraby
6

Jalan pintas adalah

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

Hanya memperluas jawaban taraloca. Anda harus menambahkan baris berikut untuk membuatnya berfungsi. Saya telah membuat nama gambar statis. Pastikan Anda menggunakan variabel cap waktu taraloca jika Anda membutuhkan nama gambar dinamis.

    // 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();
        }
    }
}

Dan dalam file AndroidManifest.xml entri berikut harus:

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

Jika Anda ingin mengambil tangkapan layar dari fragment ikuti ini:

  1. Timpa 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. Logika untuk mengambil tangkapan layar:

     button.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
         View view =  mView.findViewById(R.id.scrollView1);
          shareScreenShotM(view, (NestedScrollView) view); 
     }
  3. metode 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. metode 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. metode 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;
       }

Untuk aktivitas, Anda cukup menggunakan View v1 = getWindow().getDecorView().getRootView();sajamView

Parsania Hardik
sumber
3

Sebagian besar jawaban untuk pertanyaan ini menggunakan Canvasmetode menggambar atau menggambar metode cache. Namun, View.setDrawingCache()metode ini tidak digunakan lagi dalam API 28 . Saat ini API yang direkomendasikan untuk membuat tangkapan layar adalah PixelCopykelas yang tersedia dari API 24 (tetapi metode yang menerima Windowparameter tersedia dari API 26 == Android 8.0 Oreo). Berikut ini contoh kode Kotlin untuk mengambil 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
        }
    }
}
Miloš Černilovský
sumber
Masalah dengan PixelCopy pada solusi drawingCache adalah, sepertinya hanya menangkap piksel yang terlihat. sisanya hitam untuk saya. Jadi tidak mungkin membagikan barang yang dapat digulir dan sebagian keluar dari bingkai. Apakah Anda punya solusi untuk ini?
Henning
Kamu benar. Demikian pula itu dapat menyebabkan masalah jika Tampilan lain ditampilkan di atas Lihat Saya ingin tangkapan layar (misalnya ketika laci dibuka). Dalam kasus ini saya hanya menggunakan metode Canvas lama :(
Miloš Černilovský
1
Apakah mungkin untuk mengambil tangkapan layar di aplikasi yang sedang berjalan menggunakan PixelCopy?
Amir Rezaei
2

Hanya untuk aplikasi sistem!

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

Catatan: Aplikasi sistem tidak perlu menjalankan "su" untuk menjalankan perintah ini.

GilCol
sumber
2

Tampilan parameter adalah objek tata letak root.

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;
                }
Anil Singhania
sumber
2

Untuk Screenshot Scrolling Halaman Penuh

Jika Anda ingin mengambil tangkapan layar Lihat penuh (Yang berisi scrollview atau lebih) maka periksa di perpustakaan ini

https://github.com/peter1492/LongScreenshot

Yang harus Anda lakukan adalah mengimpor Gradel, dan membuat objek BigScreenshot

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

Panggilan balik akan diterima dengan bitmap dari Screenshot yang diambil saat secara otomatis menggulir grup tampilan layar dan pada akhirnya dikumpulkan bersama.

@Override public void getScreenshot(Bitmap bitmap) {}

Yang dapat disimpan ke galeri atau penggunaan apa pun diperlukan setelah mereka

Peter
sumber
1

Ambil tangkapan layar tampilan di 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;
}
Mohit Singh
sumber
-1

jika Anda ingin menangkap tampilan atau tata letak seperti RelativeLayout atau LinearLayout dll. gunakan saja kode:

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

sekarang Anda dapat menyimpan bitmap ini di penyimpanan perangkat dengan:

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();}
Akshay Paliwal
sumber