Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีถ่ายภาพหน้าจอ (Screenshot) โดยโปรแกรมใน Android

ภาพรวม

ตัวอย่างนี้สาธิตวิธีถ่ายภาพหน้าจอ (Screenshot) โดยโปรแกรมใน Android โดยการวาด View ลงบน Bitmap แล้วแสดงใน ImageView

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

สร้างโปรเจกต์ Android ใหม่ใน Android Studio

ขั้นตอนที่ 2: เพิ่ม Layout XML

ไฟล์ 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>

ใช้ LinearLayout เป็น parent container มี ImageView สำหรับแสดง截圖 และ TextView เป็นปุ่มกด

ขั้นตอนที่ 3: เพิ่มโค้ด Java

ไฟล์ 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");
                screenShot(parent);  // ถ่ายภาพ parent view
            }
        });
    }
    
    public void screenShot(View view) {
        // สร้าง Bitmap ขนาดเท่ากับ View
        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
            view.getHeight(), Bitmap.Config.ARGB_8888);
        
        // วาด View ลงบน Canvas
        Canvas canvas = new Canvas(bitmap);
        view.draw(canvas);
        
        // แสดงใน ImageView
        screenShot.setImageBitmap(bitmap);
        textView.setText("click");
    }
}

โค้ดหลักสำหรับถ่ายภาพหน้าจอ

Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
imageView.setImageBitmap(bitmap);

🔧 ปรับปรุงสำหรับ Production (Best Practices)

1. รองรับ View ที่ยังไม่ได้ Layout (pre-measure)

public Bitmap takeScreenshot(View view) {
    // บังคับ measure/layout หากยังไม่ได้ทำ
    if (view.getWidth() == 0 || view.getHeight() == 0) {
        view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
    }
    
    Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(),
        view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    view.draw(canvas);
    return bitmap;
}

2. ถ่ายภาพทั้งหน้าจอ (Root View)

public Bitmap takeFullScreenScreenshot(Activity activity) {
    View rootView = activity.getWindow().getDecorView().getRootView();
    return takeScreenshot(rootView);
}

3. บันทึกไฟล์ (ต้องการ Permission WRITE_EXTERNAL_STORAGE)

public void saveScreenshot(Bitmap bitmap, String fileName) {
    FileOutputStream fos = null;
    try {
        File file = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), fileName);
        fos = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (fos != null) {
            try { fos.close(); } catch (IOException ignored) {}
        }
    }
}

⚠️ ข้อจำกัดและข้อควรระวัง

  • Secure Flag: หาก Activity ตั้งค่า FLAG_SECURE (ป้องกัน screenshot) จะได้ Bitmap สีดำ/ว่าง
  • SurfaceView/TextureView: ไม่สามารถจับได้ด้วยวิธีนี้ (ต้องใช้ MediaProjection API)
  • Performance: การสร้าง Bitmap ขนาดใหญ่กินหน่วยความจำ ควร recycle() หลังใช้
  • Permission: Android 10+ ต้องใช้ MediaStore หรือ Scoped Storage สำหรับบันทึกไฟล์

วิธีทดสอบ

  1. รันแอปบนอุปกรณ์จริง
  2. คลิก TextView "Click"
  3. ข้อความเปลี่ยนเป็น "It is screen shot text" แล้วจับภาพ parent view
  4. ภาพจะแสดงใน ImageView ด้านบน

ทางเลือกสมัยใหม่: MediaProjection API (Android 5.0+)

สำหรับการจับภาพหน้าจอทั้งหมด รวมถึง SurfaceView และแอปอื่น:

// ต้องขอ permission จากผู้ใช้
MediaProjectionManager mgr = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
startActivityForResult(mgr.createScreenCaptureIntent(), REQUEST_CODE);

// ใน onActivityResult
MediaProjection projection = mgr.getMediaProjection(resultCode, data);
VirtualDisplay display = projection.createVirtualDisplay("screen-capture",
    width, height, density, flags, surface, null, null);