20 กรกฎาคม 2556

[Android Code] การเซฟภาพหน้าจอแบบทั้งหน้าหรือบางส่วนที่ต้องการ


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


        โดยเจ้าของบล็อกก็ได้ทำออกมาทั้งสองแบบด้วยกันเพื่อให้ผู้ที่หลงเข้ามาอ่านนำไปใช้งานตามต้องการ


        สำหรับการดึงภาพจากหน้าจอจะอ้างอิงจาก View ที่ต้องการ โดยกำหนด View ที่ต้องการแล้วดึงภาพบน View นั้นๆ เป็น Bitmap
View v = findViewById(R.id.xxxxxx); v.setDrawingCacheEnabled(true); Bitmap bm = Bitmap.createBitmap(v.getDrawingCache()); v.setDrawingCacheEnabled(false);
        จากตัวอย่างนี้ก็คือกำหนด View ที่ต้องการ โดยใช้คำสั่ง findViewById ระบุเป็น Resource ID (R.id.xxx) ที่ต้องการ แล้วเปิดการเก็บ Cache ของภาพ แล้วเก็บ Cache ดังกล่าวไว้ใน Bitmap จากนั้นก็หยุดการเก็บ Cache แล้วจะเอา Bitmap ไปทำอะไรก็ตามแต่ผู้ที่หลงเข้ามาอ่านเลย เซฟลงเครื่องหรือเอาไปทำประมวลต่อก็ได้ แต่บทความนี้จะเซฟลงเครื่อง

        โดยที่ View ดังกล่าวนั้น ถ้ามี Child อยู่ภายใน Child ก็จะติดอยู่ในภาพด้วย อย่างเช่น View ดังกล่าวเป็น Linear Layout ที่มี Button กับ Text View อยู่ ก็จะได้ภาพของ Linear Layout ที่มี Button กับ Text View อยู่ด้วยนั่นเอง

        สำหรับการถ่ายภาพหน้าจอทั้งแอปพลิเคชันก็จะดึง View ของจอด้วยคำสั่ง
View v = findViewById(android.R.id.content).getRootView();

        ดังนั้นก็จะได้เป็นดังนี้
View v = findViewById(android.R.id.content).getRootView(); v.setDrawingCacheEnabled(true); Bitmap bm = Bitmap.createBitmap(v.getDrawingCache()); v.setDrawingCacheEnabled(false);

        เมื่อได้เป็น Bitmap มาแล้วผู้ที่หลงเข้ามาอ่านอยากให้นำภาพไปทำอะไรก็ตามแต่เลย แต่ถ้าอยากจะบันทึกลงในเครื่องก็ดูตัวอย่างต่อไป โดยจะทำการบันทึกเป็นไฟล์ภาพด้วยคำสั่งดังนี้
File dir = new File(Environment.getExternalStorageDirectory() , directory + filename + ".jpg"); FileOutputStream out = new FileOutputStream(dir); ByteArrayOutputStream bos = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.JPEG, 100, bos); out.write(bos.toByteArray()); out.close();

        จะเป็นการบันทึก Bitmap ดังกล่าวเป็นไฟล์ JPG แล้วเก็บลงในเครื่อง โดยมีที่อยู่และชื่อไฟล์ตามที่กำหนด (directory กับ filename)

        ในการเขียนข้อมูลลง External Storage หรือ SD จะต้องขอ Permission ดังนี้
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


        สำหรับโค๊ดตัวอย่างในบทความนี้ก็จะมีทั้งหมดดังนี้

main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="true" android:focusableInTouchMode="true" > <requestFocus /> <LinearLayout android:id="@+id/layout" android:layout_width="300dp" android:layout_height="300dp" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:background="#99CCCCCC" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="10dp" > <ImageView android:id="@+id/imageView2" android:layout_width="100dp" android:layout_height="100dp" android:src="@drawable/profile" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="Type here" android:text="Sleeping For Less" /> <ImageView android:id="@+id/imageView1" android:layout_width="260dp" android:layout_height="70dp" android:layout_marginTop="10dp" android:src="@drawable/photo" /> </LinearLayout> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:text="Profile" android:textSize="30sp" /> <Button android:id="@+id/btnSaveAll" android:layout_width="100dp" android:layout_height="100dp" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:text="Save all screen" /> <Button android:id="@+id/btnSaveCard" android:layout_width="100dp" android:layout_height="100dp" android:layout_alignBaseline="@+id/btnSaveAll" android:layout_alignBottom="@+id/btnSaveAll" android:layout_toLeftOf="@+id/btnSaveAll" android:text="Save card only" /> </RelativeLayout>



Main.java
package app.akexorcist.screenshot; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Date; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.graphics.Bitmap; import android.text.format.DateFormat; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class Main extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button btnSaveAll = (Button)findViewById(R.id.btnSaveAll); btnSaveAll.setOnClickListener(new OnClickListener() { public void onClick(View v) { View view = findViewById(android.R.id.content).getRootView(); view.setDrawingCacheEnabled(true); Bitmap bm = Bitmap.createBitmap(view.getDrawingCache()); view.setDrawingCacheEnabled(false); try { Date d = new Date(); String filename = (String)DateFormat.format("kkmmss-MMddyyyy" , d.getTime()); File dir = new File(Environment.getExternalStorageDirectory() , "/Pictures/" + filename + ".jpg"); FileOutputStream out = new FileOutputStream(dir); ByteArrayOutputStream bos = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.JPEG, 100, bos); out.write(bos.toByteArray()); Toast.makeText(getApplicationContext(), "Save all!" , Toast.LENGTH_SHORT).show(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }); Button btnSaveCard = (Button)findViewById(R.id.btnSaveCard); btnSaveCard.setOnClickListener(new OnClickListener() { public void onClick(View v) { View view = findViewById(R.id.layout); view.setDrawingCacheEnabled(true); Bitmap bm = Bitmap.createBitmap(view.getDrawingCache()); view.setDrawingCacheEnabled(false); try { Date d = new Date(); String filename = (String)DateFormat.format("kkmmss-MMddyyyy" , d.getTime()); File dir = new File(Environment.getExternalStorageDirectory() , "/Pictures/" + filename + ".jpg"); FileOutputStream out = new FileOutputStream(dir); ByteArrayOutputStream bos = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.JPEG, 100, bos); out.write(bos.toByteArray()); Toast.makeText(getApplicationContext(), "Save card!" , Toast.LENGTH_SHORT).show(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }); } }

        สำหรับที่อยู่ไฟล์เจ้าของบล็อกจะเก็บไว้ที่โฟลเดอร์ Pictures โดยชื่อไฟล์จะให้อิงตามวันที่และเวลาที่บันทึกไฟล์


AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="app.akexorcist.screenshot" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="app.akexorcist.screenshot.Main" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>

        เมื่อเปิดแอปฯขึ้นมาก็ให้ลองกดปุ่ม Save card only กับ Save all screen  แล้วเปิดดูรูปที่บันทึก ก็จะเห็นว่าภาพสำหรับปุ่ม Save card only จะได้ดังนี้ ซึ่งเป็นภาพที่อิงจาก Linear Layout ที่ได้จัด Widget ต่างๆไว้ข้างใน



        และสำหรับ Save all screen ก็จะได้เป็นภาพหน้าแอปพลิเคชันทั้งหน้าเลย



        สำหรับผู้ที่หลงเข้ามาอ่านคนใดที่ต้องการตัวอย่างโปรเจคสามารถดาวน์โหลดได้จาก Screenshot [Google Drive]




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

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