20 July 2013

[Android Code] วิธีการบันทึกภาพ Layout ใน Android App ด้วยโค้ด


        หลังจากหายไปนานก็กลับมาเขียนบทความเรื่องแอนดรอยด์กันต่อ ซึ่งคราวนี้ก็จะเป็นเรื่องราวของการบัทึกภาพหน้าจอในแอปฯ เพราะในหลายๆแอปฯอาจจะต้องการบันทึกภาพ Layout ที่แสดงผลอยู่ ณ ตอนนั้น เช่น หน้าจอสรุปผลการทำงานบางอย่างที่ให้ผู้ใช้สามารถกดบันทึกเป็นภาพเก็บไว้ได้

         การบันทึกภาพหน้าจอโดยสั่งผ่านแอปฯนั้นไม่เหมือนกับการสั่งให้บันทึกภาพหน้าจอด้วยการกดปุ่ม Power + Volume Down หรือ Power + Home เพราะนั่นเป็นการสั่งบันทึกหน้าจอผ่าน Android System ซึ่งวิธีนี้ไม่สามารถสั่งงานผ่านแอปฯได้ (ในกรณีที่ไม่ได้รูทเครื่อง)

แล้วจะบันทึกภาพหน้าจอด้วยโค้ดได้ยังไง?

         ดังนั้นถ้าอยากจะบันทึกภาพหน้าจอ ก็จะทำได้แค่บันทึกจากภาพหน้าจอที่อยู่ในแอปฯของผู้ที่หลงเข้ามาอ่านเท่านั้น ซึ่งเป็นการสั่งให้ Layout ที่ต้องการทำการบันทึกภาพที่แสดงผลอยู่ให้กลายเป็น Bitmap

        ยกตัวอย่างเช่น เจ้าของบล็อกมี Layout ชุดหนึ่งที่ต้องการบันทึกภาพจาก LinearLayout ที่ชื่อว่า @+id/layout_profile


        เจ้าของบล็อกสามารถบันทึกภาพใน LinearLayout ที่ต้องการ โดยใช้คำสั่งดังนี้

LinearLayout layoutProfile = findViewById(R.id.layout_profile);
layoutProfile.setDrawingCacheEnabled(true);
Bitmap bm = Bitmap.createBitmap(layoutProfile.getDrawingCache());
layoutProfile.setDrawingCacheEnabled(false);

        คำสั่ง setDrawingCacheEnabled(boolean enabled) เป็นคำสั่งของคลาส View นั่นหมายความว่า View ทุกตัวไม่ว่าจะเป็น TextView, EditText, LinearLayout หรือ RelativeLayout ที่สืบทอดคลาสมาจาก View ก็จะใช้คำสั่งนี้ได้ทั้งหมด และเป็น Recursive ด้วย ดังนั้น View หรือ ViewGroup จะซ้อนกันกี่ชั้นก็ไม่ต้องห่วง

        ผลลัพธ์ที่ได้ก็จะออกมาเป็นแบบนี้


        ซึ่งคำสั่งดังกล่าวเป็นการ Cache ภาพที่แสดงอยู่บน View ตัวนั้นๆตลอดเวลา จากนั้นก็ดึง Cache มาเก็บลงในคลาส Bitmap โดยให้กำหนดเป็น True เพื่อทำการ Cache และกำหนดเป็น False เมื่อทำการดึงภาพจาก Cache มาเก็บไว้ใน Bitmap เสร็จ (ไม่ควรสั่ง Cache ทิ้งไว้ตลอดเวลา)

บันทึกภาพหน้าจอทั้งแอปฯ

        เนื่องจากการบันทึกหน้าจอด้วยโค้ดเป็นการใช้คำสั่งกับ View ที่ต้องการ ดังนั้นถ้าอยากจะสั่งทั้งหน้าจอก็ต้องไปสั่งที่ Root View ของ Layout ในหน้านั้นๆ ซึ่งมีคำสั่งง่ายๆในการเรียก Root View ดังนี้

View rootView = findViewById(android.R.id.content).getRootView();

        แล้วก็ใช้คำสั่ง setDrawingCacheEnabled(boolean enabled) กับ View ตัวนี้เพื่อบันทึกภาพทั้งหน้าจอได้เลย

เมื่อได้เป็น Bitmap แล้ว อยากจะเอาไปทำอะไรก็แล้วแต่เลยจ้าาาาาา

        สมมติว่าอยากจะเอา Bitmap ที่ได้ไปบันทึกลงใน External Storage ก็ใช้คำสั่งแบบนี้ได้เลย

public void saveBitmapToExternalStorage(Bitmap bitmap, String directory, String filename, String extension) {
    File dir = new File(Environment.getExternalStorageDirectory(), directory + filename + ".jpg");
    FileOutputStream out = new FileOutputStream(dir);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
    out.write(bos.toByteArray());
    out.close();
}

        อยากจะบันทึกลงที่ไหนใน External Storage ก็กำหนดเองตามใจชอบนะจ๊ะ

        อย่าลืม Permission สำหรับบันทึกข้อมูลลง External Storage ด้วย

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

        หมายเหตุ - เพื่อให้รองรับกับ Runtime Permission ที่เพิ่มมาใหม่ใน Android 6.0 Marshmallow ขึ้นไป ลองไปอ่านเพิ่มเติมได้ที่ สิ่งที่นักพัฒนาต้องรู้เกี่ยวกับระบบ Runtime Permission ใหม่ของแอนดรอยด์ รีบปรับโค้ดก่อนจะสายเกินไป




เหล่าพันธมิตรแอนดรอยด์

Devahoy Layer Net NuuNeoI The Cheese Factory Somkiat CC Mart Routine Artit-K Arnondora Kamonway Try to be android developer Oatrice Benz Nest Studios Kotchaphan@Medium Jirawatee@Medium Travispea@Medium