如何创建 COSU 应用程序?没有活动管理员错误

Posted

技术标签:

【中文标题】如何创建 COSU 应用程序?没有活动管理员错误【英文标题】:How to create a COSU app? No Active Admin Error 【发布时间】:2017-11-06 21:11:59 【问题描述】:

我目前正在尝试创建一个 COSU 应用程序。我想将用户锁定在应用程序中,并禁用所有功能以离开,例如主页按钮、菜单按钮、返回按钮、工具栏等。我已按照此处的指南进行操作:https://developer.android.com/work/cosu.html#cosu-solutions

我遇到的问题是我收到“无活动管理员”错误。我不知道如何让我活跃。是否有意图调用会显示此提示?我直接按照开发人员的说明进行操作,但遗漏了一些未在网站上发布的详细信息。

原因:java.lang.SecurityException:没有活动管理员 ComponentInfoandroid.example.stage/com.example.app.framework.utilities.kiosk.DeviceAdminReceiver 在 android.os.Parcel.readException(Parcel.java:1693) 在 android.os.Parcel.readException(Parcel.java:1646) 在 android.app.admin.IDevicePolicyManager$Stub$Proxy.setUserRestriction(IDevicePolicyManager.java:7977) 在 android.app.admin.DevicePolicyManager.addUserRestriction(DevicePolicyManager.java:6296) 在 android.example.activity.RegistrationActivity.setUserRestriction(RegistrationActivity.java:320) 在 android.example.activity.RegistrationActivity.setDefaultCosuPolicies(RegistrationActivity.java:274) 在 android.example.activity.RegistrationActivity.onCreate(RegistrationActivity.java:110) 在 android.app.Activity.performCreate(Activity.java:6942) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2880) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2988) 在 android.app.ActivityThread.-wrap14(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1631) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6682) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

这是我的实现的样子。

在 OnCreate() 中

    mAdminComponentName = DeviceAdminReceiver.getComponentName(this);
    mDevicePolicyManager = (DevicePolicyManager) getSystemService(
            Context.DEVICE_POLICY_SERVICE);
    mPackageManager = getPackageManager();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
        setDefaultCosuPolicies(true);
    

在 onStart() 中

    // start lock task mode if it's not already active
    ActivityManager am = (ActivityManager) getSystemService(
            Context.ACTIVITY_SERVICE);
    // ActivityManager.getLockTaskModeState api is not available in pre-M.
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
            if (!am.isInLockTaskMode()) 
                startLockTask();
            
        
     else 
        if (am.getLockTaskModeState() ==
                ActivityManager.LOCK_TASK_MODE_NONE) 
            startLockTask();
        
    

我的辅助方法

@TargetApi(Build.VERSION_CODES.M)
 private void setDefaultCosuPolicies(boolean active) 
     // set user restrictions
     setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, active);
     setUserRestriction(UserManager.DISALLOW_FACTORY_RESET, active);
     setUserRestriction(UserManager.DISALLOW_ADD_USER, active);
     setUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA, active);
     setUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME, active);

     // disable keyguard and status bar
     mDevicePolicyManager.setKeyguardDisabled(mAdminComponentName, active);
     mDevicePolicyManager.setStatusBarDisabled(mAdminComponentName, active);

     // enable STAY_ON_WHILE_PLUGGED_IN
     enableStayOnWhilePluggedIn(active);

     // set System Update policy

     if (active)
         mDevicePolicyManager.setSystemUpdatePolicy(mAdminComponentName,
                 SystemUpdatePolicy.createWindowedInstallPolicy(60,120));
      else 
         mDevicePolicyManager.setSystemUpdatePolicy(mAdminComponentName, null);
     

     // set this Activity as a lock task package

     mDevicePolicyManager.setLockTaskPackages(mAdminComponentName,
             active ? new String[]getPackageName() : new String[]);

     IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MAIN);
     intentFilter.addCategory(Intent.CATEGORY_HOME);
     intentFilter.addCategory(Intent.CATEGORY_DEFAULT);

     if (active) 
         // set Cosu activity as home intent receiver so that it is started
         // on reboot
         mDevicePolicyManager.addPersistentPreferredActivity(
                 mAdminComponentName, intentFilter, new ComponentName(
                         getPackageName(), RegistrationActivity.class.getName()));
      else 
         mDevicePolicyManager.clearPackagePersistentPreferredActivities(
                 mAdminComponentName, getPackageName());
     
 

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void setUserRestriction(String restriction, boolean disallow) 
        if (disallow) 
            mDevicePolicyManager.addUserRestriction(mAdminComponentName,
                    restriction);
         else 
            mDevicePolicyManager.clearUserRestriction(mAdminComponentName,
                    restriction);
        
    

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void enableStayOnWhilePluggedIn(boolean enabled) 
        if (enabled) 
            mDevicePolicyManager.setGlobalSetting(
                    mAdminComponentName,
                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
                    Battery_PLUGGED_ANY);
         else 
            mDevicePolicyManager.setGlobalSetting(
                    mAdminComponentName,
                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN, DONT_STAY_ON);
        
    

我的 device_admin.xml

<?xml version="1.0" encoding="utf-8"?>
<device-admin>
    <uses-policies>
        <limit-password/>
        <watch-login/>
        <reset-password/>
        <force-lock/>
        <wipe-data/>
        <expire-password/>
        <encrypted-storage/>
        <disable-camera/>
        <disable-keyguard-features/>
    </uses-policies>
</device-admin>

我在 AndroidManifest.xml 中的接收器

    <receiver
        android:name="com.example.app.framework.utilities.kiosk.DeviceAdminReceiver"
        android:description="@string/app_name"
        android:label="@string/app_name"
        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.intent.action.DEVICE_ADMIN_ENABLED"/>
            <action android:name="android.intent.action.PROFILE_PROVISIONING_COMPLETE"/>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
        </intent-filter>
    </receiver>

【问题讨论】:

你找到解决办法了吗? 您是否使用了 DPM 命令?见COSU codelabs 我也很好奇你是否解决了这个问题,因为我遇到了同样的错误。 【参考方案1】:
    Create a device administration receiver in MyDeviceAdminReceiver.kt:
class MyDeviceAdminReceiver : DeviceAdminReceiver()
    Define and declare your policy:

res/xml/device_admin.xml:

<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
        <!-- Put whatever policies you need below -->
        <limit-password />
    </uses-policies>
</device-admin>

AndroidManifest.xml:

<receiver android:name=".MyDeviceAdminReceiver"
    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" />
    </intent-filter>
</receiver>

    Make sure to log out of all accounts 在“设置”>“设备上的帐户”中。

    Run the dpm command to set device owner:

adb shell dpm set-device-owner com.example.myapp/.MyDeviceAdminReceiver

    Allowlist apps(这次是 Java 而不是 Kotlin):
String[] ALLOWED_PACKAGES = getPackageName();
DevicePolicyManager dpm = (DevicePolicyManager) getApplicationContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminName = new ComponentName(getApplicationContext(), MyDeviceAdminReceiver.class);
dpm.setLockTaskPackages(adminName, ALLOWED_PACKAGES);
    Start lock task mode:
val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
if (dpm.isLockTaskPermitted(packageName)) 
    startLockTask()

【讨论】:

以上是关于如何创建 COSU 应用程序?没有活动管理员错误的主要内容,如果未能解决你的问题,请参考以下文章

NLP在生活管理亲子教育中的应用

通过 Android Management Api 或设备所有者 locktask 开发 Cosu 应用程序

TCP的保活机制

我的设置活动的布局文件在哪里?

如何在前台(顶部)活动(应用程序)更改时收到通知

敏捷个人4月份大会:提升可迁移能力和自我管理能力的秘诀竟然隐藏在生活中?