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