13 กรกฎาคม 2559

[Android Code] รู้กันหรือเปล่าว่าแอนดรอยด์มีสิ่งที่เรียกว่า Device Administrator อยู่นะ



        Device Administrator เป็นฟีเจอร์อย่างหนึ่งบนแอนดรอยด์ที่มีมานมนานแล้วล่ะ แต่น้อยคนที่จะรู้จักกัน พอดีมีงานหนึ่งที่เจ้าของบล็อกต้องใช้ Device Administrator อยู่ด้วย ก็เลยขอหยิบมาเล่าอยู่กันฟังนะครับ

        ถ้าว่ากันตามเนื้อๆเลย Device Administrator เป็น API ที่ทาง Google ยัดมาไว้ในแอนดรอยด์ตั้งแต่สมัย Android 2.2 Froyo แล้ว ซึ่งมีจุดประสงค์เพื่อใช้งานในแอพระดับ Enterprise Application นั่นเอง ถ้าผู้ใช้ทั่วไปจะเรียกฟีเจอร์นี้ว่า Device Administrator แต่สำหรับนักพัฒนาเวลาจะใช้งานฟีเจอร์นี้ก็จะต้องเรียกใช้งานผ่าน Device Administration API นั่นเอง

        แล้ว Enterprise Application มันต่างกับแอพทั่วๆไปยังไงล่ะ?

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

        ซึ่งเจ้า Device Administrator นี่ล่ะที่จะมาทำให้แอพสามารถควบคุมการทำงานของอุปกรณ์ในระดับ System Level ได้

        อาจจะฟังดูลึกล้ำ แต่เอาจริงๆก็ทำได้ไม่ค่อยเยอะหรอกนะ...ถ้าเอาพื้นฐานหลักๆจะมีแค่

        • ควบคุมรหัสผ่านใน Lock Screen
        • Storage Encryption
        • ปิดไม่ให้ใช้งานกล้อง
        • Factory Reset
        • ล็อคหน้าจอ

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

        แต่พอการมาของ Android 5.0 Lollipop ทาง Google ก็ได้หยิบเจ้า Device Administrator มาปัดฝุ่นใหม่และเพิ่มความสามารถเข้าไปมากขึ้นอีก เพื่อให้แอพสามารถควบคุมการทำงานของเครื่องได้มากกว่าเดิม ไม่ว่าจะเป็น

        • บล็อคการเพิ่ม/ลดเสียง
        • บล็อคการตั้งค่าบลูทูธ
        • บล็อคการตั้งค่า WiFi
        • บล็อคการใช้งาน USB Debugging
        • บล็อคการสั่ง Factory Reset
        • บล็อคการติดตั้ง/ลบแอพ
        • บล็อคการโทรออก
        • บล็อคการใช้งาน Location Sharing
        • บล็อคการรับ/ส่ง SMS
        • บล็อคการถ่ายโอนข้อมูลผ่าน USB
        • ฯลฯ

        คือแบบว่า... มันเพิ่มมาเยอะมาก ซึ่งไอ้สิ่งที่เพิ่มมาเยอะแยะนี่แหละคือที่มาของ Android for Work ที่มาพร้อมกับ Android 5.0 Lollipop นั่นเอง

        นั่นหมายความว่าบนเครื่อง Android 5.0 Lollipop ขึ้นไปเมื่อใช้งาน Device Administrator ก็จะมาพร้อมกับความสามารถอีกมากมายเพื่อตอบโจทย์ Enterprise Application นั่นเอง แต่เดี๋ยวจะเล่าให้ฟังอีกทีในตอนหลังนะ

อยากจะเรียกใช้งาน Device Administrator ต้องทำยังไงบ้างนะ?

      เอาจริงๆก็ไม่ยุ่งยากซักเท่าไรนะ แต่ก็จะแตกต่างกับพวก Permission นิดหน่อย โดยที่ความสามารถในการทำงานในแต่ละอย่างของ Device Administator นั้นจะเรียกว่า Policy ครับ ซึ่งคล้ายๆกับ Permission ตรงที่นักพัฒนาสามารถระบุได้ว่าจะขอใช้ Policy ตัวไหนบ้าง

      แต่การประกาศ​ Policy ที่จะใช้งานภายในแอพของผู้ที่หลงเข้ามาอ่านนั้นไม่ได้ประกาศไว้ใน Android Manifest นะ แต่จะต้องสร้าง XML ขึ้นมาเองแล้วกำหนด Policy ที่ต้องการไว้ในนั้น


      โดยสร้างโฟลเดอร์ xml ขึ้นมาใน res (อยู่ที่เดียวกับบรรดา drawable, layout, mipmap และ values น่ะแหละ) แล้วสร้างไฟล์ XML ขึ้นมา ตั้งชื่ออะไรก็ได้ ขอให้จำได้ก็แล้วกัน ยกตัวอย่างเช่นเจ้าของบล็อกตั้งชื่อไฟล์ว่า device_admin.xml

<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>

        <force-lock />

        <disable-camera />

    </uses-policies>
</device-admin>

        ซึ่ง Policy ที่มีให้ใช้งานก็จะมีทั้งหมดเท่านี้

<limit-password/>
<watch-login/>
<reset-password/>
<force-lock/>
<wipe-data/>
<expire-password/>
<encrypted-storage/>
<disable-camera/>

        และต้องสร้าง Broadcast Receiver เพื่อดักเหตุการณ์สำหรับ Device Administrator ซึ่งเจ้าของบล็อกขอตั้งชื่อว่า AdminReceiver.java

import android.app.admin.DeviceAdminReceiver;
import android.content.Context;
import android.content.Intent;

public class AdminReceiver extends DeviceAdminReceiver {
    @Override
    public void onEnabled(Context context, Intent intent) {

    }

    @Override
    public CharSequence onDisableRequested(Context context, Intent intent) {
        return null;
    }

    @Override
    public void onDisabled(Context context, Intent intent) {

    }
}

        ซึ่ง Broadcast Receiver ตัวนี้ก็จะดักเหตุการณ์เมื่อแอปฯตัวนี้มีการเปิดใช้ Device Administrator หรือยกเลิกใช้งาน อยากจะทำอะไรต่อก็ใส่โค้ดในนี้ได้เลย แต่ตัวอย่างนี้คงไม่ได้ใส่โค้ดอะไร

        ต่อมาก็ประกาศ AdminReceiver ไว้ใน Android Manifest แบบนี้

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>

    <application
        ...>

        ...

        <receiver
            android:name=".AdminReceiver"
            android:permission="android.permission.BIND_DEVICE_ADMIN">
            
            <meta-data
                android:name="android.app.device_admin"
                android:resource="@xml/device_admin" />

            <intent-filter>
                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
                <action android:name="android.app.action.DEVICE_ADMIN_DISABLED" />
                <action android:name="android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

        จะเห็นว่าใน <meta-data> จะมีการกำหนดค่า android:resource ด้วยไฟล์ xml ที่สร้างไว้ในตอนแรกนั่นเอง และ Intent Filter ก็จะกำหนดว่าจะให้ Broadcast Receiver คอยดักเหตุการณ์สำหรับ Device Administrator เท่านั้น

        โอเคละ เตรียมไฟล์เบื้องต้นสำหรับ Device Administrator เรียบร้อยแล้ว คราวนี้มาดูคำสั่งต่างๆที่จะต้องเรียกใช้งานกันบ้าง

        เมื่อต้องการเปิดใช้งาน Device Administrator ให้ใช้คำสั่ง

public void activateDeviceAdmin(Activity activity) {
    ComponentName componentName = new ComponentName(activity, AdminReceiver.class);
    Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
    intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);
    activity.startActivity(intent);
}

        เมื่อคำสั่งนี้ทำงานก็จะเป็นการเปิดหน้าขอเปิดใช้งาน Device Administrator ในแอปฯของเจ้าของบล็อก


        คำสั่งนี้สามารถใช้เป็น startActivityForResult ก็ได้เหมือนกันนะ เพื่อให้เข้า onActivityResult จะได้เช็คว่าผู้ใช้กดเปิดใช้งาน Device Administrator หรือไม่

        ถ้าต้องการปิด Device Administrator ให้ใช้คำสั่ง

public void deactivateDeviceAdmin(Context context) {
    DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
    ComponentName componentName = new ComponentName(context, AdminReceiver.class);
    devicePolicyManager.removeActiveAdmin(componentName);
}

        คำสั่งนี้จะเป็นการยกเลิกใช้งาน Device Administrator ทันที โดยไม่มีการถามเพื่อยืนยันจากผูใช้งาน ซึ่งจะต่างจากเวลาที่ผู้ใช้เลือกไปที่ Settings > Security > Device administrators เพราะในหน้านั้นจะมีหน้าต่างให้ผู้ใช้กดเพื่อยกเลิกใช้งาน

        และสามารถเช็คได้ว่าแอปฯตัวนี้เปิดใช้งาน Device Administrator แล้วหรือยัง ด้วยคำสั่ง

public boolean isDeviceAdminActivated(Context context) {
    DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
    ComponentName componentName = new ComponentName(context, AdminActivationReceiver.class);
    return devicePolicyManager.isAdminActive(componentName);
}

        เมื่อเปิดใช้งาน Device Administrator เสร็จเรียบร้อยแล้ว ก็จะสามารถเรียกใช้คำสั่งต่างๆที่อยู่ในคลาส DevicePolicyManager ได้เลย

//ตัวอย่างคำสั่งปิดหน้าจอ
DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
devicePolicyManager.lockNow();

เรื่องที่ควรระวัง เวลาใช้งาน Device Administrator

        ถ้าสังเกตกันดีๆจะเห็นว่ามีแอปฯอยู่หลายๆตัวที่ต้องมีการเปิดใช้งาน Device Administrator ก่อนถึงจะใช้งานได้ (เพราะฟีเจอร์บางอย่างจำเป็นต้องใช้ความสามารถของ Device Administrator) ซึ่งนักพัฒนาควรจำไว้เลยว่า การเปิดใช้งาน Device Administrator ภายในแอปฯของผู้ที่หลงเข้ามาอ่านนั้น จะทำให้ผู้ใช้ไม่สามารถ Uninstall แอปฯตัวนั้นทิ้งได้ 


        ซึ่งวิธีแก้ปัญหาก็คือผู้ใช้จะต้องไปกดยกเลิกใช้งาน Device Administrator ก่อน (Settings > Security > Device Administrator)


        ปัญหาก็คือผู้ใช้งานส่วนใหญ่ไม่รู้หรอก...

        ก็ไม่แปลกใจซักเท่าไร เพราะส่วนใหญ่ไม่รู้จักหรอก ไอ้ Device Administrator เนี่ย แต่ที่แน่ๆ ถ้ากด Uninstall แอปฯออกไปจากเครื่องไม่ได้ ก็เตรียมตัวโดน Comment ในแง่ลบบน Play Store ได้เลย

        ดังนั้นเพื่อให้ง่ายต่อผู้ใช้งานควรมีการแจ้งเตือนถึงเรื่อง Device Administrator ในตอนใช้งานด้วย เช่น ก่อนจะให้ผู้ใช้เปิดใช้งาน Device Administrator ก็ควรแจ้งไว้ด้วยว่าจะไม่สามารถ Uninstall แอปฯออกจากเครื่องได้ทันที แต่ต้องไปยกเลิกการใช้งาน Device Administrator ด้วยตัวเองก่อน หรือถ้าจะให้ดีกว่านั้นก็ควรทำให้สามารถยกเลิกใช้งานจากในแอปฯได้เลย (เช่น มีปุ่มกดเพื่อยกเลิกใช้งาน Device Administrator)

การเรียกใช้งานคำสั่งที่เพิ่มเข้ามาใน Android 5.0 Lollipop ขึ้นไป

        เมื่อลองเข้าไปเช็คใน API Reference ของคลาส DevicePolicyManager ก็จะเห็นว่า คำสั่งที่มาใหม่ใน API 21 นั้นมีเงื่อนไขว่าจะต้องเปิด Device Owner หรือ Profile Owner

        บอกเลยว่าไม่ใช่เรื่องง่ายเลย แต่ก็สามารถเข้าไปดูขั้นตอนได้ที่ Provisioning for Device Administration [Android Developer]

        ซึ่งขั้นตอนนี้เป็นขั้นตอนการเปลี่ยนให้เครื่องนั้นๆกลายเป็น Corporate Device ดีๆนี่เอง ดังนั้นเจ้าของบล็อกจึงขอข้ามการอธิบายขั้นตอนนี้ไปนะครับ

        และหลังจากที่เปิด Device Owner หรือ Profile Owner แล้วก็จะทำให้สามารถเรียกใช้คำสั่งของ Device Administrator ใน API 21+ ได้

       นั่นหมายความว่านักพัฒนาทั่วๆไปจะไม่สามารถใช้งานคำสั่งของ API 21+ ได้เลย เพราะเป็นคำสั่งที่จะต้องมีการ Setup ตัวอุปกรณ์ก่อนถึงจะใช้งานได้ ดังนั้นที่ใช้งานได้ก็จะมีแค่คำสั่งเก่าๆเท่านั้น

ผู้ใช้ Uninstall ง่ายขึ้น สำหรับ Android 7.0 Nugat

        ล่าสุดที่เขียนบทความนี้ซึ่งอยู่ในช่วงที่ Android 7.0 Nugat กำลังมาพอดี โดยเวอร์ชันนี้ก็ได้มีการปรับเล็กน้อยเพื่อให้ User สามารถรู้ได้ว่าต้องไปปิดใช้งาน Device Administrator ก่อน

        แอปฯตัวไหนที่เปิดใช้งาน Device Administrator อยู่ สามารถลากเพื่อ Uninstall ได้แล้ว แต่ระหว่างขั้นตอนจะมีการแจ้งให้ไปปิดใช้งาน Device Administrator โดยจะมีปุ่มให้กดเพื่อไปหน้านั้นทันที ซึ่งจะลดปัญหา User ที่ไม่รู้วิธีปิดได้


        และภาพตอนเปิดใช้งาน Device Administrator ก็มีการเปลี่ยนแปลงเล็กน้อยให้เป็นดังภาพ

สรุป

       Device Administrator เป็นหนึ่งในความสามารถของแอนดรอยด์ที่น้อยคนจะรู้จัก ซึ่งจะทำให้สามารถใช้คำสั่งบางอย่างที่เดิมทำไม่ได้ อย่างเช่น สั่งล็อคหน้าจอ หรือ Factory Reset ซึ่งการเรียกใช้งานคำสั่งเหล่านี้ก็มีเงื่อนไขว่าแอปฯจะต้องเปิดใช้งาน Device Administrator ก่อน โดยผู้ใช้สามารถกดเปิดและปิดเองได้ตามต้องการ


         แต่ในขณะเดียวกันผู้ใช้ก็อาจจะเกิดความรู้สึกหวาดระแวงเล็กน้อย เพราะว่าหน้าจอตอนขอใช้งาน Device Administrator จะมีขึ้นรายชื่อ Policy ที่ต้องการขอใช้งาน รวมไปถึงเวลา Uninstall ที่ผู้ใช้ต้องปิดใช้งาน Device Administrator ก่อน ถึงจะ Uninstall ได้ (แต่จากทดลองดู พบว่าให้ทำใจโดนด่าในหน้าดาวน์โหลดแอปฯได้เลย..)

        และเมื่อมาถึงยุคของ Android 5.0 Lollipop ก็มีการปรับปรุงใหม่ให้ Device Administrator สามารถทำได้เยอะขึ้น เพื่อตอบโจทย์การใช้งานในระดับองค์กร มีขั้นตอนในการ Setup เครื่องด้วย นั่นหมายความว่าความสามารถใหม่ๆพวกนี้จะไม่สามารถใช้งานกับเครื่องทั่วๆไปได้นั่นเอง

แหล่งข้อมูลอ้างอิง

        • Device Administration
        • API Reference - Device Policy Manager
        • Provisioning for Device Administrator
        • Android for Work




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

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