به عنوان یک EMM مبتنی بر API مدیریت Android، میتوانید از راه دور برنامههای سفارشی را روی دستگاهها مدیریت کنید. این شامل نصب و حذف این برنامه ها می شود. این عملکرد با توسعه یک برنامه افزودنی به صورت محلی با استفاده از AMAPI SDK به دست می آید.
پیش نیازها
- برنامه افزودنی شما با AMAPI SDK یکپارچه شده است.
- دستگاه به طور کامل مدیریت می شود.
- AMAPI SDK نسخه 1.6.0-rc01 یا بالاتر مورد نیاز است.
1. برنامه خود را برای استفاده از ویژگی آماده کنید
1.1. با AMAPI SDK در برنامه برنامه افزودنی خود یکپارچه شوید
فرآیند مدیریت برنامه سفارشی از شما میخواهد که AMAPI SDK را در برنامه افزودنی خود یکپارچه کنید. می توانید اطلاعات بیشتری درباره این کتابخانه و نحوه افزودن آن به برنامه خود در راهنمای ادغام AMAPI SDK بیابید.
1.2. مانیفست برنامه خود را برای پشتیبانی FileProvider
به روز کنید
- همانطور که در راهنمای ادغام AMAPI SDK نشان داده شده است، عنصر
<queries>
را برای برنامه Android Device Policy (ADP) بهAndroidManifest.xml
خود اضافه کنید. - قطعه
<provider>
زیر را درAndroidManifest.xml
برنامه خود در داخل تگ<application>
پیاده سازی کنید. این قطعه برای ذخیره فایلها هنگام اشتراکگذاری APK برنامه سفارشی استفاده میشود و نصب برنامههای سفارشی را با استفاده از AMAPI امکانپذیر میکند.
AndroidManifest.xml
:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.customapp">
<queries>
<package android:name="com.google.android.apps.work.clouddpc" />
</queries>
<application>
<!--This is used to store files when sharing the custom app apk.-->
<provider
android:name="com.google.android.managementapi.customapp.provider.CustomAppProvider"
android:authorities="${applicationId}.AmapiCustomAppProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_paths" />
</provider>
</application>
</manifest>
- یک فایل XML جدید در دایرکتوری
res/xml/
برنامه خود ایجاد کنید که حاوی مسیر ذخیره سازی apk های سفارشی است.
file_provider_paths.xml
:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path
name="android_managementapi_custom_apks"
path="com.google.android.managementapi/customapp/apks/" />
</paths>
2. با ویژگی برنامه سفارشی AMAPI SDK یکپارچه شوید
2.1. فایل APK سفارشی را برای نصب آماده کنید
قبل از استقرار، فایل APK برنامه باید برای نصب آماده شود. قطعه کد زیر این فرآیند را نشان می دهد:
کاتلین
import android.net.Uri import androidx.core.net.Uri import java.io.File ... import com.google.android.managementapi.commands.LocalCommandClient import com.google.android.managementapi.commands.LocalCommandClient.InstallCustomAppCommandHelper import com.google.android.managementapi.commands.LocalCommandClientFactory ... fun prepareApkFile(): Uri? { // Get the storage location of custom APK files from AM API val client: LocalCommandClient = LocalCommandClientFactory.create(context) val installCustomAppCommandHelper = client.installCustomAppCommandHelper val customApksStorageDir: File = installCustomAppCommandHelper.customApksStorageDirectory ?: return null // Once you get hold of the custom APKs storage directory, you must store your custom APK // in that location before issuing the install command. val customApkFile: File = fetchMyAppToDir(customApksStorageDir) ?: return null val customApkFileUri: Uri = customApkFile.toUri() return customApkFileUri }
جاوا
import android.net.Uri; import androidx.core.net.Uri; import java.io.File; ... import com.google.android.managementapi.commands.LocalCommandClient; import com.google.android.managementapi.commands.LocalCommandClient.InstallCustomAppCommandHelper; import com.google.android.managementapi.commands.LocalCommandClientFactory; ... Uri prepareApkFile() { // Get the storage location of custom APK files from AM API LocalCommandClient client = LocalCommandClientFactory.create(); InstallCustomAppCommandHelper installCustomAppCommandHelper = client.getInstallCustomAppCommandHelper(); File customApksStorageDir = installCustomAppCommandHelper.getCustomApksStorageDirectory(); // Once you get hold of the custom APKs storage directory, you must store your custom APK // in that location before issuing the install command. File customApkFile = fetchMyAppToDir(customApksStorageDir); Uri customApkFileUri = Uri.fromFile(customApkFile); ... }
2.2. درخواست نصب یک برنامه سفارشی را صادر کنید
قطعه زیر نحوه صدور درخواست برای نصب یک برنامه سفارشی را نشان می دهد:
کاتلین
import android.content.Context import android.net.Uri import android.util.Log import com.google.android.managementapi.commands.LocalCommandClientFactory import com.google.android.managementapi.commands.model.Command import com.google.android.managementapi.commands.model.IssueCommandRequest import com.google.android.managementapi.commands.model.IssueCommandRequest.InstallCustomApp import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import kotlinx.coroutines.guava.await import kotlinx.coroutines.withContext import java.lang.Exception private const val TAG = "MyClass" ... // Requires a file URI of the APK file. fun issueInstallCustomAppCommand(packageName: String, fileUri: Uri) { coroutineScope.launch { try { withContext(coroutineScope.coroutineContext) { val result: Command = LocalCommandClientFactory.create(context) .issueCommand(createInstallCustomAppRequest(packageName, fileUri)).await() // Process the returned command result here. Log.i(TAG, "Successfully issued command: $result") } } catch (t: Exception) { Log.e(TAG, "Failed to issue command", t) // Handle the exception (e.g., show an error message) } finally { // Make sure to clean up the apk file after the command is executed. cleanUpApkFile(fileUri) } } } private fun createInstallCustomAppRequest(packageName: String, fileUri: Uri): IssueCommandRequest { return IssueCommandRequest.builder() .setInstallCustomApp( InstallCustomApp.builder() .setPackageName(packageName) .setPackageUri(fileUri.toString()) .build() ) .build() } }
جاوا
import android.util.Log; ... import com.google.android.managementapi.commands.LocalCommandClientFactory; import com.google.android.managementapi.commands.model.Command; import com.google.android.managementapi.commands.model.GetCommandRequest; import com.google.android.managementapi.commands.model.IssueCommandRequest; import com.google.android.managementapi.commands.model.IssueCommandRequest.ClearAppsData; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.MoreExecutors; ... // Requires a file URI of the APK file. void issueInstallCustomAppCommand(String packageName, Uri fileUri) { Futures.addCallback( LocalCommandClientFactory.create(getContext()) .issueCommand(createInstallCustomAppRequest(packageName, fileUri)), new FutureCallback() { @Override public void onSuccess(Command result) { // Process the returned command result here. Log.i(TAG, "Successfully issued command"); } @Override public void onFailure(Throwable t) { Log.e(TAG, "Failed to issue command", t); } }, MoreExecutors.directExecutor()); } IssueCommandRequest createInstallCustomAppRequest(String packageName, Uri fileUri) { return IssueCommandRequest.builder() .setInstallCustomApp( InstallCustomApp.builder() .setPackageName(packageName) .setPackageUri(fileUri.toString()) .build() ) .build(); }
2.3. درخواستی برای دریافت برنامه های نصب شده صادر کنید
کاتلین
import android.content.Context import com.google.android.managementapi.device.DeviceClientFactory import com.google.android.managementapi.device.model.GetDeviceRequest import kotlinx.coroutines.guava.await suspend fun getInstalledApps(context: Context) = DeviceClientFactory.create(context) .getDevice(GetDeviceRequest.getDefaultInstance()) .await() .getApplicationReports()
جاوا
import android.content.Context; import com.google.android.managementapi.device.DeviceClientFactory; import com.google.android.managementapi.device.model.GetDeviceRequest; import com.google.android.managementapi.device.model.Device; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import java.util.List; import java.util.concurrent.Executor; public ListenableFuture<List> getInstalledApps() { ListenableFuture deviceFuture = DeviceClientFactory.create(context) .getDevice(GetDeviceRequest.getDefaultInstance()); return Futures.transform( deviceFuture, Device::getApplicationReports, executor // Use the provided executor ); }
3. دستگاه را با خط مشی های مدیریت برنامه های سفارشی تهیه کنید
با برنامههای سفارشی که میخواهید مدیریت کنید،
policy
تنظیم کنید.{ "statusReportingSettings": { "applicationReportsEnabled": true }, "applications": [ { "signingKeyCerts": [ { "signingKeyCertFingerprintSha256": <sha256 signing key certificate hash value> } ], "packageName": "<emm_extensibility_app>", "installType": "AVAILABLE", "lockTaskAllowed": true, "defaultPermissionPolicy": "GRANT", "extensionConfig": { "notificationReceiver": "com.example.customapp.NotificationReceiverService" } }, { "signingKeyCerts": [ { "signingKeyCertFingerprintSha256": <sha256 signing key certificate hash value> }, ], "packageName": "<custom_app>", "installType": "CUSTOM", "lockTaskAllowed": true, "defaultPermissionPolicy": "GRANT", "customAppConfig": { "userUninstallSettings": "DISALLOW_UNINSTALL_BY_USER" } } ] } ```
با فراخوانی enterprises.enrollmentTokens.create ، با
allowPersonalUsage
رویPERSONAL_USAGE_DISALLOWED
، یک نشانه ثبت نام برای دستگاه ایجاد کنید.دستگاه را در حالت کاملاً مدیریت شده با رمز ثبت نام ارائه کنید .
برنامه توسعه پذیری خود را از بازی مدیریت شده نصب کنید.
برنامه توسعه پذیری شما:
- می توانید فایل APK برنامه سفارشی را دانلود کنید
- می تواند درخواستی برای نصب برنامه سفارشی صادر کند (به قطعه کد نشان داده شده قبلی مراجعه کنید)
- باید پاسخ دریافت کند
API
API سرور-کلینت
به فیلدها و فهرست های جدید فهرست شده مراجعه کنید: