AMAPI দিয়ে কাস্টম অ্যাপ পরিচালনা করুন

অ্যান্ড্রয়েড ম্যানেজমেন্ট এপিআই ভিত্তিক ইএমএম হিসেবে, আপনি ডিভাইসগুলিতে দূরবর্তীভাবে কাস্টম অ্যাপ্লিকেশন পরিচালনা করতে পারেন। এর মধ্যে এই অ্যাপগুলি ইনস্টল এবং আনইনস্টল উভয়ই অন্তর্ভুক্ত। AMAPI SDK ব্যবহার করে স্থানীয়ভাবে একটি এক্সটেনশন অ্যাপ তৈরি করে এই কার্যকারিতা অর্জন করা হয়।

পূর্বশর্ত

১. বৈশিষ্ট্যটি ব্যবহারের জন্য আপনার অ্যাপটি প্রস্তুত করুন

১.১. আপনার এক্সটেনশন অ্যাপে AMAPI SDK এর সাথে একীভূত করুন।

কাস্টম অ্যাপ ম্যানেজমেন্ট প্রক্রিয়ার জন্য আপনাকে আপনার এক্সটেনশন অ্যাপে AMAPI SDK ইন্টিগ্রেশন করতে হবে। এই লাইব্রেরি এবং এটি আপনার অ্যাপে কীভাবে যুক্ত করবেন সে সম্পর্কে আরও তথ্য আপনি AMAPI SDK ইন্টিগ্রেশন গাইডে পেতে পারেন।

১.২. FileProvider সমর্থন করার জন্য আপনার অ্যাপের ম্যানিফেস্ট আপডেট করুন।

  • AMAPI SDK ইন্টিগ্রেশন গাইডে দেখানো Android Device Policy (ADP) অ্যাপ্লিকেশনের জন্য <queries> উপাদানটি আপনার AndroidManifest.xml এ যোগ করুন।
  • আপনার অ্যাপের AndroidManifest.xml<application> ট্যাগের ভিতরে নিম্নলিখিত <provider> স্নিপেটটি প্রয়োগ করুন। কাস্টম অ্যাপ 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>
  • আপনার অ্যাপের res/xml/ ডিরেক্টরিতে একটি নতুন XML ফাইল তৈরি করুন যাতে কাস্টম apks-এর স্টোরেজ পাথ থাকবে।

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-এর কাস্টম অ্যাপ বৈশিষ্ট্যের সাথে একীভূত করুন

২.১. ইনস্টলেশনের জন্য কাস্টম 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);
  ...
}

২.২. একটি কাস্টম অ্যাপ ইনস্টল করার জন্য একটি অনুরোধ জারি করুন

নিম্নলিখিত স্নিপেটটি দেখায় কিভাবে একটি কাস্টম অ্যাপ ইনস্টল করার জন্য অনুরোধ জারি করতে হয়:

কোটলিন

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();
  }

২.৩. ইনস্টল করা অ্যাপ পাওয়ার জন্য একটি অনুরোধ জারি করুন

কোটলিন

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
        );
    }

৩. কাস্টম অ্যাপস ম্যানেজমেন্ট নীতিমালা সহ ডিভাইসটি সরবরাহ করুন

  1. আপনি যে কাস্টম অ্যাপগুলি পরিচালনা করতে চান তার সাথে একটি policy সেট আপ করুন।

      {
        "statusReportingSettings": {
          "applicationReportsEnabled": true
        },
        "applications": [
        {
          "signingKeyCerts": [
            {
            "signingKeyCertFingerprintSha256": <sha256 signing key certificate hash value>
            }
          ],
          "packageName": "<emm_extensibility_app>",
          "installType": "AVAILABLE",
          "defaultPermissionPolicy": "GRANT",
          "extensionConfig": {
              "notificationReceiver": "com.example.customapp.NotificationReceiverService"
          }
        },
        {
          "signingKeyCerts": [
            {
            "signingKeyCertFingerprintSha256": <sha256 signing key certificate hash value>
            },
          ],
          "packageName": "<custom_app>",
          "installType": "CUSTOM",
          "defaultPermissionPolicy": "GRANT",
          "customAppConfig": {
              "userUninstallSettings": "DISALLOW_UNINSTALL_BY_USER"
          }
        }
        ]
      }
      ```
    
  2. enterprises.enrollmentTokens.create এ কল করে ডিভাইসের জন্য একটি তালিকাভুক্তি টোকেন তৈরি করুন, allowPersonalUsage PERSONAL_USAGE_DISALLOWED এ সেট করে।

  3. সম্পূর্ণরূপে পরিচালিত মোডে ডিভাইসটিকে তালিকাভুক্তি টোকেন সহ সরবরাহ করুন

  4. Managed Play থেকে আপনার এক্সটেনসিবিলিটি অ্যাপটি ইনস্টল করুন।

  5. আপনার এক্সটেনসিবিলিটি অ্যাপ:

    • কাস্টম অ্যাপের APK ফাইল ডাউনলোড করতে পারেন
    • কাস্টম অ্যাপটি ইনস্টল করার জন্য একটি অনুরোধ জারি করতে পারে (আগে দেখানো কোড স্নিপেটটি দেখুন)
    • একটি প্রতিক্রিয়া পাওয়া উচিত
  6. যদি কাস্টম অ্যাপটি নীতি থেকে সরিয়ে ফেলা হয়, তাহলে ইনস্টল করা সাইডলোডেড অ্যাপ্লিকেশনটি playStoreMode এর সাথে সামঞ্জস্যপূর্ণ হলে আনইনস্টল হবে না।

  7. আরও বিস্তারিত জানার জন্য, CUSTOM ইনস্টলের ধরণটি পরীক্ষা করুন।

এপিআই

সার্ভার-ক্লায়েন্ট API

তালিকাভুক্ত নতুন ক্ষেত্র এবং এনামগুলি দেখুন: