Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách chụp màn hình lập trình (Screenshot) trên Android

Giới thiệu

Android cho phép chụp màn hình (screenshot) của View bất kỳ bằng cách vẽ View lên Bitmap qua Canvas. Kỹ thuật này hữu ích cho: chia sẻ nội dung, báo lỗi, tutorial, lưu trạng thái UI.

Lưu ý: Từ Android 10 (API 29), có giới hạn bảo mật - không thể chụp màn hình của app khác hoặc màn hình secure (FLAG_SECURE).

Ví dụ minh họa

Bước 1: Tạo project

Android Studio → File → New Project.

Bước 2: Layout (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:id="@+id/parent"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:background="#33FFFF00"
    android:orientation="vertical">
    <ImageView
        android:id="@+id/screenShot"
        android:layout_width="300dp"
        android:layout_height="300dp" />
    <TextView
        android:id="@+id/text"
        android:textSize="18sp"
        android:layout_gravity="center"
        android:text="Click"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

Bước 3: Code (src/MainActivity.java)

package com.example.andy.myapplication;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    ImageView screenShot;
    TextView textView;

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

        final LinearLayout parent = findViewById(R.id.parent);
        screenShot = findViewById(R.id.screenShot);
        textView = findViewById(R.id.text);

        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView.setText("It is screen shot text");
                takeScreenShot(parent);
            }
        });
    }

    public void takeScreenShot(View view) {
        // Tạo bitmap cùng kích thước view
        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
            view.getHeight(), Bitmap.Config.ARGB_8888);
        
        // Vẽ view lên canvas
        Canvas canvas = new Canvas(bitmap);
        view.draw(canvas);
        
        // Hiển thị lên ImageView
        screenShot.setImageBitmap(bitmap);
        textView.setText("click");
    }
}

Giải thích code chụp màn hình

// 1. Tạo bitmap chứa pixel
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), 
    view.getHeight(), Bitmap.Config.ARGB_8888);

// 2. Tạo canvas vẽ lên bitmap
Canvas canvas = new Canvas(bitmap);

// 3. Yêu cầu view vẽ chính nó (và con) lên canvas
view.draw(canvas);

// 4. Sử dụng bitmap (hiển thị, lưu file, chia sẻ...)
imageView.setImageBitmap(bitmap);

Lưu screenshot vào file

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

    // Lưu vào external storage (cần quyền WRITE_EXTERNAL_STORAGE)
    File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), 
        "screenshot_" + System.currentTimeMillis() + ".png");
    
    try (FileOutputStream fos = new FileOutputStream(file)) {
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
        // Thông báo cho MediaScanner
        MediaScannerConnection.scanFile(this, 
            new String[]{file.getAbsolutePath()}, null, null);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Chụp toàn bộ Activity (kể cả status bar)

// Chỉ hoạt động nếu app không set FLAG_SECURE
View decorView = getWindow().getDecorView();
Bitmap bitmap = Bitmap.createBitmap(decorView.getWidth(),
    decorView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
decorView.draw(canvas);

MediaProjection API (Android 5.0+) - Chụp màn hình hệ thống

Để chụp màn hình của TOÀN BỘ HỆ THỐNG (ngoài app của bạn), cần MediaProjection:

// 1. Request permission
MediaProjectionManager mgr = (MediaProjectionManager) 
    getSystemService(Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(mgr.createScreenCaptureIntent(), REQUEST_CODE);

// 2. onActivityResult
MediaProjection projection = mgr.getMediaProjection(resultCode, data);

// 3. Tạo VirtualDisplay để capture
VirtualDisplay display = projection.createVirtualDisplay("ScreenCapture",
    width, height, density, flags, surface, null, null);

Lưu ý quan trọng

  • View phải đã layout (đã có width/height > 0)
  • Không chụp được View có FLAG_SECURE (banking, DRM)
  • Hardware acceleration có thể ảnh hưởng - thử view.setLayerType(View.LAYER_TYPE_SOFTWARE, null) nếu bị đen
  • Bitmap lớn gây OOM - cân nhắc scale down
  • API 29+ giới hạn chụp màn hình app khác

Xử lý View chưa layout

view.post(() -> {
    // View đã layout xong, an toàn chụp
    takeScreenShot(view);
});