24 กรกฎาคม 2557

[Android Code] ทำไมภาพถึงไม่ยอมแสดงใน Gallery


        เชื่อว่าผู้ที่หลงเข้ามาอ่านบทความนี้ก็เพราะชื่อบทความที่เจ้าของบล็อกตั้งดักไว้ XD ซึ่งบทความนี้ก็เป็นอีกเรื่องหนึ่งที่ผู้ที่หลงเข้ามาอ่านหลายๆคนประสบปัญหากัน เนื่องจากทำแอปพลิเคชันไม่ว่าจะถ่ายรูปหรือวาดรูปหรือโหลดภาพก็ตาม เมื่อบันทึกลงในเครื่องแล้วปรากฏว่าเปิดหาใน Gallery ของเครื่องไม่เจอซะงั้น



        ผู้ที่หลงเข้ามาอ่านก็เป็นหนึ่งในนั้นที่ประสบปัญหาหรือว่าเคยประสบปัญหาล่ะสิ เพราะงั้นอ่านบทความนี้ต่อได้เลย~


       ก่อนจะบอกวิธีแก้ปัญหานี้ก็ต้องมาทำความเข้าใจกันเสียก่อนว่าทำไมถึงเป็นเช่นนี้ (ไม่งั้นบทความเจ้าของบล็อกก็อ่านไม่เพลินน่ะสิ) เมื่อเข้าใจการทำงานแล้วก็จะสามารถเข้าใจการแก้ปัญหาได้ว่าทำไมต้องทำเช่นนั้น

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


        แล้วจะทำยังไงให้มันไวกว่าวิธีดังกล่าว?

        นั่นก็คือสแกนไฟล์เพียงแค่ครั้งแรกเท่านั้น (นั่นก็คือตอนเปิดเครื่อง) แล้วบันทึกเก็บตำแหน่งไฟล์ภาพทั้งหมดไว้ว่าอยู่ตำแหน่งใดในเครื่องบ้าง เจ้าสิ่งที่ทำหน้านี้ที่มีชื่อเรียกว่า Media Scanner นั่นเอง โดย Gallery ก็จะอิงตำแหน่งไฟล์ภาพทั้งหมดจาก Media Scanner  (เอา Path มาทำเป็นภาพ Thumbnail เพื่อแสดงผลอีกที) ดังนั้นหัวใจสำคัญจะอยู่ที่ Media Scanner



        ถ้าภาพมีการย้ายตำแหน่งล่ะ?

        ก็จะเกิดคำถามต่อว่าผู้ใช้ย้ายตำแหน่งภาพด้วยอะไรล่ะ? นั่นก็คือย้ายภาพด้วยแอปพลิเคชันนั่นเอง ซึ่งหัวใจสำคัญส่วนหนึ่งก็อยู่ที่แอปพลิเคชันนี่ล่ะ ที่จะบอกว่าภาพถูกย้ายไปที่ไหน ดังนั้นเมื่อภาพถูกย้ายด้วยแอปพลิเคชันใดๆ แอปพลิเคชันนั้นๆก็จะบอกกับ Media Scanner ด้วยว่าภาพย้ายไปไว้ที่ไหน ส่วนตำแหน่งเดิมไว้เวลาที่ Media Scanner ทำงานก็จะรู้เองว่าภาพไม่อยู่ที่ตำแหน่งนั้นแล้ว รวมไปถึงการย้ายภาพจาก MTP ด้วยเช่นกัน



        หัวใจสำคัญอยู่ที่แอปพลิเคชัน

        แอปพลิเคชันจะต้องเป็นตัวบอกกับ Media Scanner ดังนั้นจึงเป็นเหตุผลว่าทำไมผู้ที่หลงเข้ามาอ่านต้องเขียนโค๊ดเพิ่มเข้าไปว่าไฟล์ภาพดังกล่าวถูกสร้างขึ้นที่ไหนหรือถูกย้ายไปไว้ที่ไหนนั่นเอง เมื่อไม่ได้มีการแจ้งไปที่ Media Scanner ก็จะทำให้ Media Scanner ไม่รู้ว่ามีภาพเพิ่มเข้ามาที่ตำแหน่งนั้นๆ พอ Gallery เรียกไฟล์ภาพทั้งหมดที่มีจาก Media Scanner ก็ทำให้หาภาพดังกล่าวไม่เจอนั่นเอง

        ส่วนการสั่งงานดังกล่าวจะใช้ Intent เข้ามากำหนดไฟล์ที่ต้องการอัปเดตแล้วส่งค่าด้วยคำสั่ง sendBroadcast ดังตัวอย่างข้างล่างนี้
public void updateImage(String path) {
    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(path);
    intent.setData(Uri.fromFile(f));
    sendBroadcast(intent);
}

String filePath = .......
...
updateImage(filePath);
...

        จากตัวอย่างข้างบนคือฟังก์ชันที่เอาไว้อัปเดตไฟล์ให้กับ Media Scanner เพียงแค่กำหนด Path ของไฟล์ที่ต้องการอัปเดตก็ได้แล้ว ง่ายล่ะสิ!

        หรือถ้าใช้งานคลาส File อยู่แล้ว ก็ทำแบบนี้ได้เช่นกัน จะได้ไม่ต้องมาดึง String ให้เสียเวลา
public void updateImage(File f) {
    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    intent.setData(Uri.fromFile(f));
    sendBroadcast(intent);
}

File file = .......
...
updateImage(file);
...

        หรือใช้งานเป็นคลาส Uri ก็ใส่ uri ตรงไปตรงๆได้เช่นกัน ไม่ต้องแปลงเป็นคลาส File ให้เสียเวลา
public void updateImage(Uri uri) {
    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    intent.setData(uri);
    sendBroadcast(intent);
}

Uri uri = .......
...
updateImage(uri);
...

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


        บทความไม่ได้ยาว แต่หาเรื่องทำให้มันยาวมากขึ้น XD




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

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