ภาพรวม
ตัวอย่างนี้สาธิตวิธีถ่ายภาพหน้าจอ (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 สำหรับบันทึกไฟล์
วิธีทดสอบ
- รันแอปบนอุปกรณ์จริง
- คลิก TextView "Click"
- ข้อความเปลี่ยนเป็น "It is screen shot text" แล้วจับภาพ parent view
- ภาพจะแสดงใน 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);