حالت قفل وظایف

این راهنمای توسعه‌دهنده توضیح می‌دهد که چگونه دستگاه‌های اختصاصی را می‌توان روی یک برنامه یا مجموعه‌ای از برنامه‌ها قفل کرد. اگر توسعه‌دهنده مدیریت پویایی سازمانی (EMM) یا یکپارچه‌ساز راهکارها هستید، این راهنما را بخوانید تا حالت قفل وظایف را به راهکارتان اضافه کنید.

نمای کلی

Android می‌تواند تکالیف را در حالت فراگیر و کیوسک‌مانندی به‌نام حالت قفل وظایف اجرا کند. اگر درحال توسعه برنامه کیوسک یا راه‌اندازی برای ارائه مجموعه‌ای از برنامه‌ها هستید، می‌توانید از حالت قفل وظایف استفاده کنید. وقتی سیستم در حالت قفل وظایف اجرا می‌شود، کاربران دستگاه معمولاً نمی‌توانند اعلان‌ها را ببینند، به برنامه‌هایی که در فهرست مجاز نیستند دسترسی داشته باشند، یا به صفحه اصلی برگردند (مگر اینکه صفحه اصلی در فهرست مجاز باشد).

فقط برنامه‌هایی که توسط کنترل‌کننده خط‌مشی دستگاه (DPC) در فهرست مجاز قرار گرفته‌اند می‌توانند هنگامی که سیستم در حالت قفل وظایف است اجرا شوند. برنامه‌ها در فهرست مجاز قرار می‌گیرند زیرا فردی که از دستگاه استفاده می‌کند نمی‌تواند همیشه از حالت قفل وظایف خارج شود.

نحوه ترکیب برنامه مجازشده برای حالت قفل وظایف و DPC مجازشده به مشکلی که می‌خواهید حل کنید بستگی دارد. چند نمونه در زیر آمده است:

  • یک بسته برنامه تکی که کیوسک (برای ارائه محتوا) و DPC کوچک (برای قرار دادن خودش در فهرست مجاز حالت قفل وظایف) را ترکیب می‌کند.
  • یک DPC که بخشی از راه‌حل مدیریت پویایی سازمانی است، برنامه‌های تلفن همراه مشتری را در حالت قفل وظایف راه‌اندازی می‌کند.

دردسترس بودن

سیستم می‌تواند در Android نسخه ۵.۰ یا بالاتر در حالت قفل وظایف اجرا شود. جدول ۱ نشان می‌دهد کدام نسخه‌های Android از برنامه‌های فهرست مجاز براساس کاربر پشتیبانی می‌کنند.

جدول ۱. پشتیبانی نسخه Android از حالت‌های سرپرست DPC
نسخه Android مدیران DPC یادداشت‌ها
‫Android نسخه ۵.۰ (سطح میانای برنامه‌سازی کاربردی ۲۱) یا بالاتر دستگاه کاملاً مدیریت‌شده
Android نسخه ۸.۰ (سطح میانای برنامه‌سازی کاربردی ۲۶) یا بالاتر کاربر فرعی وابسته کاربر ثانویه باید با کاربر اصلی مرتبط باشد. نمای کلی چند کاربر را ببینید.
‫Android نسخه ۹.۰ (سطح میانای برنامه‌سازی کاربردی ۲۸) یا بالاتر کاربر فرعی

در Android 9.0 یا نسخه‌های جدیدتر، DPC می‌تواند فعالیت هر برنامه‌ای را در حالت قفل وظایف شروع کند. در نسخه‌های قبلی، برنامه باید ازقبل از شروع فعالیت خودش در حالت قفل وظایف پشتیبانی کند.

برنامه‌های فهرست مجازها

DPC باید برنامه‌ها را در فهرست مجاز قرار دهد تا بتوان از آن‌ها در حالت قفل وظایف استفاده کرد. برای افزودن برنامه‌ها به فهرست مجاز برای حالت قفل وظایف، DevicePolicyManager.setLockTaskPackages() را فراخوانی کنید (همان‌طور که در نمونه زیر نشان داده شده است):

کاتلین

// Allowlist two apps.
private val KIOSK_PACKAGE = "com.example.kiosk"
private val PLAYER_PACKAGE = "com.example.player"
private val APP_PACKAGES = arrayOf(KIOSK_PACKAGE, PLAYER_PACKAGE)

// ...

val context = context
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE)
        as DevicePolicyManager
val adminName = getComponentName(context)
dpm.setLockTaskPackages(adminName, APP_PACKAGES)

جاوا

// Allowlist two apps.
private static final String KIOSK_PACKAGE = "com.example.kiosk";
private static final String PLAYER_PACKAGE = "com.example.player";
private static final String[] APP_PACKAGES = {KIOSK_PACKAGE, PLAYER_PACKAGE};

// ...

Context context = getContext();
DevicePolicyManager dpm =
    (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminName = getComponentName(context);
dpm.setLockTaskPackages(adminName, APP_PACKAGES);

برای پیدا کردن برنامه‌هایی که قبلاً برای حالت قفل وظایف در فهرست مجاز قرار گرفته‌اند، DPC می‌تواند DevicePolicyManager.getLockTaskPackages() را فراخوانی کند. برنامه‌های دیگر می‌توانند DevicePolicyManager.isLockTaskPermitted() را فراخوانی کنند تا تأیید کنند که بسته برنامه از حالت قفل وظایف پشتیبانی می‌کند.

شروع حالت قفل وظایف

در Android 9.0 (سطح میانای برنامه‌سازی کاربردی ۲۸) یا بالاتر، می‌توانید فعالیت برنامه دیگری را در حالت قفل وظایف شروع کنید. اگر فعالیتی ازقبل در پیش‌زمینه یا پس‌زمینه درحال اجرا است، باید آن فعالیت را مجدداً راه‌اندازی کنید. ActivityOptions.setLockTaskEnabled() را فراخوانی کنید و این گزینه‌ها را هنگام شروع فعالیت ارائه دهید. قطعه کد زیر یک روش برای انجام این کار را نشان می‌دهد:

کاتلین

// Set an option to turn on lock task mode when starting the activity.
val options = ActivityOptions.makeBasic()
options.setLockTaskEnabled(true)

// Start our kiosk app's main activity with our lock task mode option.
val packageManager = context.packageManager
val launchIntent = packageManager.getLaunchIntentForPackage(KIOSK_PACKAGE)
if (launchIntent != null) {
    context.startActivity(launchIntent, options.toBundle())
}

جاوا

// Set an option to turn on lock task mode when starting the activity.
ActivityOptions options = ActivityOptions.makeBasic();
options.setLockTaskEnabled(true);

// Start our kiosk app's main activity with our lock task mode option.
PackageManager packageManager = context.getPackageManager();
Intent launchIntent = packageManager.getLaunchIntentForPackage(KIOSK_PACKAGE);
if (launchIntent != null) {
  context.startActivity(launchIntent, options.toBundle());
}

در نسخه‌های Android قبل‌از ۹.۰، برنامه با فراخوانی Activity.startLockTask() فعالیت‌های خودش را در حالت قفل وظایف شروع می‌کند. برای فراخوانی این روش، فعالیت باید در پیش‌زمینه اجرا شود (به مفاهیم چرخه حیات فعالیت مراجعه کنید) بنابراین پیشنهاد می‌کنیم در روش onResume() مربوط به Activity یا Fragment فراخوانی کنید. در اینجا نحوه تماس با startLockTask() آورده شده است:

کاتلین

// In our Fragment subclass.
override fun onResume() {
    super.onResume()
    // First, confirm that this package is allowlisted to run in lock task mode.
    if (dpm.isLockTaskPermitted(context.packageName)) {
        activity.startLockTask()
    } else {
        // Because the package isn't allowlisted, calling startLockTask() here
        // would put the activity into screen pinning mode.
    }
}

جاوا

// In our Fragment subclass.
@Override
public void onResume() {
  super.onResume();

  // First, confirm that this package is allowlisted to run in lock task mode.
  if (dpm.isLockTaskPermitted(context.getPackageName())) {
    getActivity().startLockTask();
  } else {
    // Because the package isn't allowlisted, calling startLockTask() here
    // would put the activity into screen pinning mode.
  }
}

وقتی دستگاه قفل است، حالت قفل وظایف را شروع نکنید چون ممکن است کاربر نتواند قفل دستگاه را باز کند. می‌توانید روش‌های KeyguardManager را فراخوانی کنید تا متوجه شوید دستگاه قفل است یا نه و از فراخوانی چرخه حیات Activity (مثل onResume() که پس‌از باز کردن قفل فراخوانی می‌شود) برای شروع حالت قفل وظایف استفاده کنید.

برنامه در حالت قفل وظایف می‌تواند فعالیت‌های جدیدی را شروع کند، به‌شرطی که فعالیت تکلیف جدیدی را شروع نکند—به‌جز تکالیفی که برنامه فهرست مجاز را راه‌اندازی می‌کنند. برای درک نحوه ارتباط تکالیف با فعالیت‌ها، راهنمای درک تکالیف و پشته قبلی‌ها را بخوانید.

یا می‌توانید در فایل مانیفست برنامه خود اعلام کنید که وقتی سیستم در حالت قفل وظایف اجرا می‌شود، یک فعالیت چگونه باید رفتار کند. برای اینکه سیستم به‌طور خودکار فعالیتتان را در حالت قفل وظایف اجرا کند، مشخصه android:lockTaskMode را روی if_whitelisted تنظیم کنید، همان‌طور که در مثال زیر نشان داده شده است:

<activity
    android:name=".MainActivity"
    android:lockTaskMode="if_whitelisted">
    <!-- ... -->
</activity>

با خواندن مرجع lockTaskMode می‌توانید درباره گزینه‌های اعلام در فایل مانیفست برنامه بیشتر بدانید.

توقف حالت قفل وظایف

DPC می‌تواند با برداشتن بسته برنامه از فهرست مجاز، حالت قفل وظایف را از راه دور متوقف کند. در Android نسخه ۶.۰ (سطح میانای برنامه‌سازی کاربردی ۲۳) یا بالاتر، DevicePolicyManager.setLockTaskPackages() را فراخوانی کنید و نام بسته را از آرایه فهرست مجاز حذف کنید. وقتی فهرست مجاز را به‌روز می‌کنید، برنامه به تکلیف قبلی در پشته برمی‌گردد.

اگر فعالیتی قبلاً startLockTask() را فراخوانی کرده باشد، آن فعالیت می‌تواند Activity.stopLockTask() را فراخوانی کند تا حالت قفل وظایف متوقف شود. این روش فقط برای فعالیتی کار می‌کند که حالت قفل وظایف را شروع کرده است.

فراخوانی‌های چرخه حیات

ممکن است برای DPC شما مفید باشد که بداند چه زمانی برنامه‌ای (که در همان کاربر اجرا می‌شود) وارد حالت قفل وظایف می‌شود و از آن خارج می‌شود. برای دریافت فراخوانی‌های برگشتی، روش‌های فراخوانی برگشتی زیر را در زیرکلاس DeviceAdminReceiver DPC خود لغو کنید:

onLockTaskModeEntering()
پس‌از اینکه برنامه وارد حالت قفل وظایف شد، فراخوانی می‌شود. می‌توانید نام بسته برنامه را از آرگومان pkg دریافت کنید.
onLockTaskModeExiting()
پس‌از خروج برنامه از حالت قفل وظایف فراخوانی می‌شود. این فراخوانی اطلاعاتی درباره برنامه دریافت نمی‌کند.

اگر برنامه دیگری را در حالت قفل وظایف راه‌اندازی کنید، باید وضعیت اجرا را در برنامه خودتان ردیابی کنید. برای بررسی اینکه برنامه فعلی در حالت قفل وظایف اجرا می‌شود یا نه، از روش‌های موجود در ActivityManager استفاده کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

// Check if this app is in lock task mode. Screen pinning doesn't count.
var isLockTaskModeRunning = false

val activityManager = context
        .getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    isLockTaskModeRunning =
            activityManager.lockTaskModeState ==
            ActivityManager.LOCK_TASK_MODE_LOCKED
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Deprecated in API level 23.
    isLockTaskModeRunning = activityManager.isInLockTaskMode
}

if (isLockTaskModeRunning) {
    // Show the exit button ...
}

جاوا

// Check if this app is in lock task mode. Screen pinning doesn't count.
boolean isLockTaskModeRunning = false;

ActivityManager activityManager = (ActivityManager)
    getContext().getSystemService(Context.ACTIVITY_SERVICE);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  isLockTaskModeRunning = activityManager.getLockTaskModeState()
      == ActivityManager.LOCK_TASK_MODE_LOCKED;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  // Deprecated in API level 23.
  isLockTaskModeRunning = activityManager.isInLockTaskMode();
}

if (isLockTaskModeRunning) {
  // Show the exit button ...
}

سفارشی‌سازی میانای کاربر

وقتی برنامه‌ای در حالت قفل وظایف اجرا می‌شود، میانای کاربر (UI) سیستم به‌روش‌های زیر تغییر می‌کند:

  • نوار وضعیت خالی است و اعلان‌ها و اطلاعات سیستم پنهان شده‌اند.
  • دکمه‌های «صفحه اصلی» و «نمای کلی» پنهان شده‌اند.
  • برنامه‌های دیگر نمی‌توانند فعالیت‌های جدید راه‌اندازی کنند.
  • صفحه قفل (درصورت تنظیم) غیرفعال است.

در Android نسخه ۹.۰ یا بالاتر، وقتی حالت قفل وظایف فعال باشد، DPC شما می‌تواند برخی‌از ویژگی‌های واسط کاربر سیستم را در دستگاه فعال کند—این ویژگی برای توسعه‌دهندگانی که راه‌انداز سفارشی ایجاد می‌کنند مفید است. DevicePolicyManager.setLockTaskFeatures() را همان‌طور که در تکه‌کد زیر نشان داده شده است فراخوانی کنید:

کاتلین

// Enable the Home and Overview buttons so that our custom launcher can respond
// using our custom activities. Implicitly disables all other features.
dpm.setLockTaskFeatures(
        adminName,
        DevicePolicyManager.LOCK_TASK_FEATURE_HOME or
              DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW)

جاوا

// Enable the Home and Overview buttons so that our custom launcher can respond
// using our custom activities. Implicitly disables all other features.
dpm.setLockTaskFeatures(adminName,
    DevicePolicyManager.LOCK_TASK_FEATURE_HOME |
          DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW);

سیستم هر ویژگی‌ای را که در آرگومان flags نگنجانید غیرفعال می‌کند. ویژگی‌های فعال‌شده میانای کاربر بین راه‌اندازی‌ها در حالت قفل وظایف باقی می‌مانند. اگر دستگاه ازقبل در حالت قفل وظایف باشد، هر تغییری که در ویژگی‌های قفل وظایف ایجاد کنید فوراً نشان داده می‌شود. جدول ۲ ویژگی‌های واسط کاربری را که می‌توانید سفارشی‌سازی کنید شرح می‌دهد.

جدول ۲. ویژگی‌های واسط کاربر سیستم قابل‌سفارشی‌سازی در حالت قفل وظایف
ویژگی واسط کاربر سیستم شرح
LOCK_TASK_FEATURE_HOME دکمه «صفحه اصلی» را نشان می‌دهد. فعال کردن برای راه‌اندازهای سفارشی—ضربه زدن روی دکمه «صفحه اصلی» فعال‌شده هیچ کنشی ندارد مگراینکه راه‌انداز پیش‌فرض Android را در فهرست مجاز قرار دهید.
LOCK_TASK_FEATURE_OVERVIEW دکمه «نمای کلی» را نشان می‌دهد (با تک‌ضرب زدن روی این دکمه، صفحه موارد اخیر باز می‌شود). اگر این دکمه را فعال کنید، باید دکمه «صفحه اصلی» را هم فعال کنید.
LOCK_TASK_FEATURE_GLOBAL_ACTIONS کادر گفتگوی کنش‌های عمومی را که هنگام فشار طولانی دکمه روشن/خاموش نشان داده می‌شود فعال می‌کند. تنها ویژگی‌ای که وقتی setLockTaskFeatures() فراخوانی نشده باشد فعال است. اگر این کادر گفتگو را غیرفعال کنید، معمولاً کاربر نمی‌تواند دستگاه را خاموش کند.
LOCK_TASK_FEATURE_NOTIFICATIONS اعلان‌ها را برای همه برنامه‌ها فعال می‌کند. این گزینه نمادهای اعلان را در نوار وضعیت، اعلان‌های هشدار، و کشوی اعلانات گسترش‌یافتنی نشان می‌دهد. اگر این دکمه را فعال کنید، باید دکمه «صفحه اصلی» را هم فعال کنید. تک‌ضرب زدن روی کنش‌ها و دکمه‌های اعلان که پانل‌های جدیدی را باز می‌کنند، در حالت قفل وظایف کار نمی‌کند.
LOCK_TASK_FEATURE_SYSTEM_INFO بخش اطلاعات سیستم نوار وضعیت را که حاوی نشانگرهایی مثل اتصال‌پذیری، باتری، و گزینه‌های صدا و لرزش است فعال می‌کند.
LOCK_TASK_FEATURE_KEYGUARD هر صفحه قفلی را که ممکن است در دستگاه تنظیم شده باشد فعال می‌کند. معمولاً برای دستگاه‌هایی که کاربران عمومی دارند، مثل کیوسک‌های اطلاعاتی یا تابلوهای دیجیتالی، مناسب نیست.
LOCK_TASK_FEATURE_NONE همه ویژگی‌های واسط کاربر سیستم را که در بالا فهرست شده است غیرفعال می‌کند.

DPC می‌تواند DevicePolicyManager.getLockTaskFeatures() را فراخوانی کند تا فهرست ویژگی‌های دردسترس در دستگاه را هنگام فعال بودن حالت قفل وظایف دریافت کند. وقتی دستگاهی از حالت قفل وظایف خارج می‌شود، میانای کاربر به وضعیتی که خط‌مشی‌های موجود دستگاه تعیین کرده‌اند برمی‌گردد.

مسدود کردن پنجره‌ها و رونهادها

وقتی برنامه‌ای در حالت قفل وظایف اجرا می‌شود، برنامه‌ها و سرویس‌های پس‌زمینه‌ای دیگر می‌توانند پنجره‌های جدیدی ایجاد کنند که Android آن‌ها را در جلوی برنامه در حالت قفل وظایف نمایش می‌دهد. برنامه‌ها و سرویس‌ها این پنجره‌ها را ایجاد می‌کنند تا پیام‌های موقت، کادرهای گفتگو، و هم‌پوشانی‌ها را به فردی که از دستگاه استفاده می‌کند نشان دهند. «کنترل‌کننده خط‌مشی دستگاه» شما می‌تواند با افزودن محدودیت کاربر DISALLOW_CREATE_WINDOWS از این موارد جلوگیری کند. مثال زیر نشان می‌دهد که چگونه می‌توانید این کار را در onLockTaskModeEntering() callback انجام دهید:

کاتلین

// Called just after entering lock task mode.
override fun onLockTaskModeEntering(context: Context, intent: Intent) {
    val dpm = getManager(context)
    val admin = getWho(context)

    dpm.addUserRestriction(admin, UserManager.DISALLOW_CREATE_WINDOWS)
}

جاوا

// Called just after entering lock task mode.
public void onLockTaskModeEntering(Context context, Intent intent) {
  DevicePolicyManager dpm = getManager(context);
  ComponentName admin = getWho(context);

  dpm.addUserRestriction(admin, UserManager.DISALLOW_CREATE_WINDOWS);
}

وقتی دستگاه از حالت قفل وظایف خارج می‌شود، DPC شما می‌تواند محدودیت کاربر را بردارد.

منابع بیشتر

برای کسب اطلاعات بیشتر درباره دستگاه‌های اختصاصی، اسناد زیر را بخوانید: