Android Lollipop becoming device admininistrator d

2019-05-02 01:02发布

问题:

I'm following this guide on how to have my app request to become a device administrator.
This works great on any 4.x android versions with any phone, but doesn't work on Lollipop (I've tried on a Nexus 5 and on a Nexus 7).

Logcat shoes the following error:

 *11-02 07:37:09.649: W/DeviceAdminAdd(10020): Cannot start ADD_DEVICE_ADMIN as a new task*  

Has anyone else come across this problem with Lollipop? What can be the cause?
I've gone over all parts of the guide and made sure my XML, menifest, receiver, etc. are all as they should be (and again, it does work on any other version of OS or phone I've tried).

If it matters, I'm compiling my app with target API=17 and min API=14 for compatibility reasons.


Adding the manifest file:

<?xml version='1.0' encoding='utf-8'?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.my.package"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="17" />

     <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
    <uses-permission android:name="com.mycompany.permission.NFProvider_WRITE" />
    <uses-permission android:name="com.mycompany.permission.NFProvider_READ" />
    <uses-permission android:name="android.permission.READ_LOGS" />

    <application
        android:name="com.mycompany.myapp.Application"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <receiver
            android:name="com.mycompany.myapp.NFAdminReceiver"
            android:permission="android.permission.BIND_DEVICE_ADMIN">
            <meta-data
                android:name="android.app.device_admin"
                android:resource="@xml/admin"/>
            <intent-filter>
                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
            </intent-filter>
        </receiver>

        <activity
            android:name="com.mycompany.myapp.ConnectMainActivity"
            android:label="@string/title_activity_connect_main"
            android:process="com.mycompany.ui"
            android:launchMode="singleInstance"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


        <service
            android:name="com.mycompany.myapp.MainService"
            android:enabled="true" />

        <meta-data android:name="applicationVersion" android:value="1.2.0.213" />


    </application>
</manifest>

Code creating the Intent:

ComponentName mComponentName = new ComponentName(activity, NFAdminReceiver.class); 
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);     
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mComponentName);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, ADMIN_REQUEST_TITLE);
activity.startActivityForResult(intent, ADMIN_INTENT); 

The variable activity is an instance of ConnectMainActivity

回答1:

Seems it was the singleInstance launchMode option that caused the problem, I'm still interested to know why it causes the problem on Lollipop and not on other versions.

For now, setting launchMode to singleTask solves the issue, and seems to still fit with the design of the app's flow.



回答2:

The root cause of this error message is in DeviceAdminAdd.java. There is this check:

if ((getIntent().getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
         Log.w(TAG, "Cannot start ADD_DEVICE_ADMIN as a new task");
         finish();
         return;
}

This check was already there in 4.0.1 : API level 14 !

The Intent subject of this check is the Intent triggering the action : DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN.

From the docs :

A "singleInstance" activity permits no other activities to be part of its task.

It don't explain the difference between API 21 and API<21 , but it explain why the FLAG_ACTIVITY_NEW_TASK is set.