โปรไฟล์งาน

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

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

ภาพรวม

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

ในการแก้ปัญหานี้ Android 5.0 (API ระดับ 21) ช่วยให้องค์กรสามารถ ตั้งค่าโปรไฟล์งาน หากอุปกรณ์มีโปรไฟล์งาน การตั้งค่าจะอยู่ภายใต้การควบคุมของผู้ดูแลระบบไอที ผู้ดูแลระบบไอทีเลือกได้ว่าจะอนุญาตแอปใดสำหรับโปรไฟล์นั้น และ ควบคุมเฉพาะฟีเจอร์ของอุปกรณ์ที่ใช้ได้กับโปรไฟล์

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

  • โดยค่าเริ่มต้น Intent ส่วนใหญ่จะไม่ข้ามจากโปรไฟล์หนึ่งไปยังอีกโปรไฟล์หนึ่ง หากมี แอปที่ทำงานในโปรไฟล์ทำให้ Intent เริ่มทำงาน ไม่มีเครื่องจัดการสำหรับ Intent โปรไฟล์นั้น และ Intent ไม่ได้ข้ามไปยังโปรไฟล์อื่น เนื่องจากข้อจำกัดด้านโปรไฟล์ คำขอจึงล้มเหลวและแอปอาจปิดลง โดยไม่คาดคิด
  • ผู้ดูแลระบบไอทีโปรไฟล์สามารถจำกัดแอประบบที่พร้อมใช้งานใน โปรไฟล์งาน การจำกัดนี้ยังอาจส่งผลให้ไม่มีตัวแฮนเดิลสำหรับ จุดประสงค์ทั่วไปบางอย่างในโปรไฟล์งาน
  • และเนื่องจากโปรไฟล์ส่วนตัวและโปรไฟล์งานจะมีพื้นที่เก็บข้อมูลแยกกัน URI ของไฟล์ที่ถูกต้องในโปรไฟล์หนึ่ง ไม่สามารถใช้งานได้ในอีกโปรไฟล์ ช่วง Intent ที่เริ่มทำงานในโปรไฟล์หนึ่งอาจได้รับการจัดการในอีกโปรไฟล์หนึ่ง (ขึ้นอยู่กับโปรไฟล์ ) ดังนั้นจึงไม่ปลอดภัยที่จะแนบ URI ของไฟล์ไปยัง Intent

ป้องกัน Intent ที่ล้มเหลว

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

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

ก่อนที่แอปจะเริ่มกิจกรรม คุณควรยืนยันว่ามี ความละเอียดที่เหมาะสม คุณ ตรวจสอบได้ว่ามีวิธีแก้ปัญหาที่ยอมรับได้โดยโทรหา Intent.resolveActivity() หากไม่มี ในการแปลค่าความตั้งใจ เมธอดจะแสดง null หากเมธอดแสดงค่าที่ไม่ใช่ Null จะมีอย่างน้อย 1 วิธีในการ ความตั้งใจนั้น และสามารถทำให้ความตั้งใจนั้นออกมาโลดแล่นได้ ในกรณีนี้ ค่า ความตั้งใจนั้นจะแก้ไขได้ เนื่องจากมีเครื่องจัดการในโปรไฟล์ปัจจุบัน หรือเนื่องจาก Intent อนุญาตให้ข้ามไปยังตัวแฮนเดิลในอีกโปรไฟล์หนึ่งได้ (สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ การแก้ไขความตั้งใจ โปรดดู Intent ทั่วไป)

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

Kotlin

fun startTimer(message: String, seconds: Int) {

    // Build the "set timer" intent
    val timerIntent = Intent(AlarmClock.ACTION_SET_TIMER).apply {
        putExtra(AlarmClock.EXTRA_MESSAGE, message)
        putExtra(AlarmClock.EXTRA_LENGTH, seconds)
        putExtra(AlarmClock.EXTRA_SKIP_UI, true)
    }

    // Check if there's a handler for the intent
    if (timerIntent.resolveActivity(packageManager) == null) {

        // Can't resolve the intent! Fail this operation cleanly
        // (perhaps by showing an error message)

    } else {
        // Intent resolves, it's safe to fire it off
        startActivity(timerIntent)

    }
}

Java

public void startTimer(String message, int seconds) {

    // Build the "set timer" intent
    Intent timerIntent = new Intent(AlarmClock.ACTION_SET_TIMER)
            .putExtra(AlarmClock.EXTRA_MESSAGE, message)
            .putExtra(AlarmClock.EXTRA_LENGTH, seconds)
            .putExtra(AlarmClock.EXTRA_SKIP_UI, true);

    // Check if there's a handler for the intent
    if (timerIntent.resolveActivity(getPackageManager()) == null) {

        // Can't resolve the intent! Fail this operation cleanly
        // (perhaps by showing an error message)

    } else {
        // Intent resolves, it's safe to fire it off
        startActivity(timerIntent);

    }
}

แชร์ไฟล์ระหว่างโปรไฟล์

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

URI ของไฟล์จะขึ้นต้นด้วย file: ตามด้วย Absolute Path ของไฟล์บนพื้นที่เก็บข้อมูลของอุปกรณ์ อย่างไรก็ตาม เนื่องจาก โปรไฟล์งานและโปรไฟล์ส่วนตัวจะใช้พื้นที่เก็บข้อมูลแยกกัน, URI ของไฟล์ ที่ถูกต้องในโปรไฟล์หนึ่ง ไม่สามารถใช้ได้ในอีกโปรไฟล์หนึ่ง สถานการณ์นี้ หมายความว่าหากคุณ แนบ URI ของไฟล์ไปยัง Intent จากนั้นระบบจะจัดการ Intent ในโปรไฟล์อื่น ตัวแฮนเดิลไม่สามารถเข้าถึงไฟล์

แต่ควรแชร์ไฟล์กับ URI เนื้อหา แทน URI เนื้อหา ระบุไฟล์ในรูปแบบที่ปลอดภัยและแชร์ได้มากยิ่งขึ้น URI เนื้อหาประกอบด้วย เส้นทางไฟล์ แต่สิทธิ์ที่มอบไฟล์ และหมายเลขรหัสด้วย เพื่อระบุไฟล์ คุณสามารถสร้างรหัสเนื้อหาสำหรับไฟล์ใดไฟล์หนึ่งโดยใช้ FileProvider จากนั้น คุณจะแชร์เนื้อหานั้น บัตรประจำตัวกับแอปอื่นๆ (แม้จะอยู่ในโปรไฟล์อื่นก็ตาม) ผู้รับสามารถใช้ Content ID เพื่อรับสิทธิ์เข้าถึงไฟล์จริง

ตัวอย่างเช่น วิธีที่คุณใช้รับ URI เนื้อหาสำหรับไฟล์หนึ่งๆ มีดังนี้ URI:

Kotlin

// Open File object from its file URI
val fileToShare = File(fileUriToShare)

val contentUriToShare: Uri = FileProvider.getUriForFile(
        context,
        "com.example.myapp.fileprovider",
        fileToShare
)

Java

// Open File object from its file URI
File fileToShare = new File(fileUriToShare);

Uri contentUriToShare = FileProvider.getUriForFile(getContext(),
        "com.example.myapp.fileprovider", fileToShare);

เมื่อเรียกใช้เมธอด getUriForFile() คุณต้องรวมสิทธิ์ของผู้ให้บริการไฟล์ (ในตัวอย่างนี้ "com.example.myapp.fileprovider") ซึ่งระบุอยู่ใน <provider> ของไฟล์ Manifest ของแอป ดูข้อมูลเพิ่มเติมเกี่ยวกับการแชร์ไฟล์ด้วย URI เนื้อหาได้ที่ มีการแบ่งรายได้ Files

ฟังการแจ้งเตือน

โดยทั่วไปแอปจะมี NotificationListenerService คลาสย่อยไปยัง รับการติดต่อกลับจากระบบเกี่ยวกับการเปลี่ยนแปลงการแจ้งเตือน อุปกรณ์ที่มี โปรไฟล์งานอาจส่งผลต่อวิธีการทำงานของ NotificationListenerService กับแอปของคุณ

ในโปรไฟล์งาน

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

ในโปรไฟล์ส่วนตัว

เมื่อแอปทำงานในโปรไฟล์ส่วนตัว คุณอาจไม่ได้รับการแจ้งเตือน สำหรับแอปที่ทำงานในโปรไฟล์งาน โดยค่าเริ่มต้น แอปโปรไฟล์ส่วนตัวทั้งหมด ได้รับการติดต่อกลับ แต่ผู้ดูแลระบบไอทีสามารถเพิ่มโปรไฟล์ส่วนตัวอย่างน้อย 1 รายการลงในรายการที่อนุญาตได้ แอปที่อนุญาตให้ฟังการเปลี่ยนแปลงการแจ้งเตือน จากนั้นระบบจะบล็อก แอปที่ไม่ได้อยู่ในรายการที่อนุญาต ใน Android 8.0 (API ระดับ 26) ขึ้นไป นโยบายด้านอุปกรณ์ ตัวควบคุม (DPC) ที่จัดการโปรไฟล์งานอาจบล็อกแอปไม่ให้ฟัง ไปยังการแจ้งเตือนของโปรไฟล์งานโดยใช้DevicePolicyManager วิธีการ setPermittedCrossProfileNotificationListeners() แอปของคุณยังคงได้รับ Callback เกี่ยวกับการแจ้งเตือนที่โพสต์ในบัญชีส่วนบุคคล โปรไฟล์

ทดสอบแอปเพื่อดูความเข้ากันได้กับโปรไฟล์งาน

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

เราได้ให้ตัวอย่างแอป TestDPC ซึ่งคุณสามารถใช้เพื่อตั้งค่าโปรไฟล์งานในอุปกรณ์ Android ที่ใช้ Android 5.0 (API ระดับ 21) ขึ้นไป แอปนี้มอบวิธีง่ายๆ ในการทดสอบ แอปในสภาพแวดล้อมโปรไฟล์งาน นอกจากนี้คุณยังใช้แอปนี้เพื่อ กำหนดค่าโปรไฟล์งานดังนี้

  • ระบุแอปเริ่มต้นที่พร้อมใช้งานในที่มีการจัดการ โปรไฟล์
  • กำหนดค่า Intent ที่จะข้ามจากโปรไฟล์หนึ่งไปยัง อื่นๆ

หากคุณติดตั้งแอปด้วยตนเองผ่านสาย USB ในอุปกรณ์ที่มี โปรไฟล์งานของคุณ ซึ่งแอปจะติดตั้งทั้งในงานส่วนตัวและที่ทํางาน โปรไฟล์ เมื่อติดตั้งแอปแล้ว คุณจะทดสอบแอปภายใต้ เงื่อนไขต่อไปนี้

  • หากแอปเริ่มต้นมักจัดการ Intent (ตัวอย่างเช่น แอปกล้อง) ให้ลองปิดใช้แอปเริ่มต้นนั้นในโปรไฟล์งาน แล้ว โปรดตรวจสอบว่าแอปจัดการกับเรื่องนี้อย่างเหมาะสม
  • หากคุณเริ่มการทำงานของ Intent ที่คาดว่าแอปอื่นจะจัดการ Intent ดังกล่าว ให้ลอง เปิดและปิดใช้สิทธิ์ของ Intent ข้ามจากโปรไฟล์หนึ่งไปยัง อีกรายการ ยืนยันว่าแอปทำงานได้อย่างถูกต้องในทั้ง 2 สถานการณ์ หาก ไม่อนุญาตให้ Intent ข้ามโปรไฟล์ โปรดยืนยันลักษณะการทำงานของแอปทั้ง เมื่อมีตัวแฮนเดิลที่เหมาะสมในโปรไฟล์ของแอป หรือเมื่อไม่มีตัวแฮนเดิล ตัวอย่างเช่น หากแอปเริ่มการทำงานของ Intent ที่เกี่ยวข้องกับแผนที่ ให้ลองทำดังนี้ สถานการณ์ต่างๆ
    • อุปกรณ์จะอนุญาตให้ Intent ของแผนที่ข้ามจากโปรไฟล์หนึ่งไปยังอีกโปรไฟล์หนึ่ง และ มีตัวแฮนเดิลที่เหมาะสมอยู่ในอีกโปรไฟล์หนึ่ง (โปรไฟล์ที่แอปไม่ได้ ทำงานอยู่)
    • อุปกรณ์ไม่อนุญาตให้ Intent ของแผนที่ข้ามระหว่างโปรไฟล์ แต่ เป็นตัวแฮนเดิลที่เหมาะสมในโปรไฟล์ของแอป
    • อุปกรณ์ไม่อนุญาตให้ Intent แมปข้ามโปรไฟล์ระหว่างโปรไฟล์ ไม่ใช่ตัวแฮนเดิลที่เหมาะสมสำหรับความตั้งใจของแผนที่ในโปรไฟล์ของอุปกรณ์
  • หากคุณแนบเนื้อหาไปที่ Intent ให้ยืนยันว่า Intent นั้นทำงานอย่างถูกต้อง ทั้งเมื่อมีการจัดการในโปรไฟล์ของแอป และเมื่อมีการข้ามระหว่าง โปรไฟล์

การทดสอบโปรไฟล์งาน: กลเม็ดเคล็ดลับ

เคล็ดลับที่อาจเป็นประโยชน์ในการทดสอบ อุปกรณ์ที่ใช้โปรไฟล์งาน

  • ตามที่ได้แจ้งไว้ เมื่อคุณไซด์โหลดแอปในอุปกรณ์โปรไฟล์งาน ติดตั้งในทั้ง 2 โปรไฟล์แล้ว คุณสามารถลบแอปออกจากโปรไฟล์เดียวได้หากต้องการ และปล่อยทิ้งไว้เช่นนั้น
  • คำสั่งของเครื่องมือจัดการกิจกรรมส่วนใหญ่มีอยู่ในเชลล์ Android Debug Bridge (adb) รองรับแฟล็ก --user ซึ่งจะช่วยให้คุณระบุผู้ใช้ที่จะเรียกใช้ได้ ในฐานะ เมื่อระบุผู้ใช้ คุณเลือกได้ว่าจะเรียกใช้ในฐานะผู้ใช้หลักที่ไม่มีการจัดการหรือไม่ หรือโปรไฟล์งาน สำหรับข้อมูลเพิ่มเติม โปรดดู ADB คำสั่ง Shell
  • หากต้องการค้นหาผู้ใช้ที่ใช้งานอยู่ในอุปกรณ์ ให้ใช้ตัวจัดการแพ็กเกจ adb คำสั่ง list users จำนวนแรกในสตริงเอาต์พุตคือค่า รหัสผู้ใช้ที่คุณใช้กับแฟล็ก --user ได้ สำหรับข้อมูลเพิ่มเติม ดูที่ ADB Shell คำสั่ง

เช่น หากต้องการค้นหาผู้ใช้ในอุปกรณ์ ให้เรียกใช้คำสั่งนี้

$ adb shell pm list users
UserInfo{0:Drew:13} running
UserInfo{10:Work profile:30} running

ในกรณีนี้ ผู้ใช้หลัก ("Drew") มีรหัสผู้ใช้ 0 และ โปรไฟล์งานมีรหัสผู้ใช้ 10 หากต้องการเรียกใช้แอปในโปรไฟล์งาน จะใช้คำสั่งแบบนี้

$ adb shell am start --user 10 \
-n "com.example.myapp/com.example.myapp.testactivity" \
-a android.intent.action.MAIN -c android.intent.category.LAUNCHER