5

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

Eran
  • 2,324
  • 3
  • 22
  • 27
  • there is concept od device_owner.xml if you know read this -->https://developer.android.com/about/versions/android-5.0.html – KOTIOS Nov 02 '14 at 05:48
  • Thanks, d.i.v.a, but from what I read device owner is something beyond device-admin, and there can only be one, I don't think I need that for my app. If I understand correctly, device-admin should still be available and work as before, and device-owner is something more powerful beyond just being an admin. – Eran Nov 02 '14 at 05:51
  • ok if u want to just enable device admin then android 5.0 works fine , post ur manifest – KOTIOS Nov 02 '14 at 05:53

2 Answers2

8

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.

Eran
  • 2,324
  • 3
  • 22
  • 27
4

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.

ben75
  • 29,217
  • 10
  • 88
  • 134
  • Obviously the error comes from the android library (and specifically the DeviceAdmin code), I don't see how this explain anything, especially how it explains the difference that the same code works on Android 4 but not on 5. – Eran Nov 02 '14 at 13:54
  • 1
    This is the intent creating code: 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); Nothing was changed, the same code works on Android 4 and doesn't on 5 (when in singleInstance mode) and on both the app wasn't already an admin. – Eran Nov 02 '14 at 14:13
  • The variable activity in the previous comment is an instance of ConnectMainActivity. – Eran Nov 02 '14 at 14:23