0

My original question is here: Android - How to programmatically switch users by user name? and it still unanswered, but I got some progress and now I'm completely stuck.

Now I've followed these steps:

  1. Added a DeviceAdmin class as shown in the code samples, I don't know if it is good or am I supposed to implement something there:

    import android.app.admin.DeviceAdminReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.widget.Toast;
    
    public class DeviceAdmin extends DeviceAdminReceiver {
    
    void showToast(Context context, String msg) {
        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
    }
    
    @Override
    public void onEnabled(Context context, Intent intent) {
        showToast(context, "admin_receiver_status_enabled");
    }
    
    @Override
    public CharSequence onDisableRequested(Context context, Intent intent) {
        return ""; //context.getString(R.string.admin_receiver_status_disable_warning);
    }
    
    @Override
    public void onDisabled(Context context, Intent intent) {
        showToast(context, "admin_receiver_status_disabled");
    }
    
    @Override
    public void onPasswordChanged(Context context, Intent intent) {
        showToast(context, "admin_receiver_status_pw_changed");
    }
    }
    
  2. Added the DeviceAdmin in the manifest:

    <receiver android:name=".DeviceAdmin"
            android:label="@string/device_admin"
            android:description="@string/device_admin_description"
            android:permission="android.permission.BIND_DEVICE_ADMIN">
            <meta-data android:name="android.app.device_admin"
                android:resource="@xml/security_policies" />
            <intent-filter>
                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
            </intent-filter>
        </receiver>
    
  3. In my MainActivity class I've added this code to get admin permissions:

    DevicePolicyManager mDPM;
    ComponentName mDeviceAdmin;
    final int REQUEST_CODE_ENABLE_ADMIN = 1;
    
    
    mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
    mDeviceAdmin = new ComponentName(this, DeviceAdmin.class);
    if (!mDPM.isAdminActive(mDeviceAdmin)) {
        // try to become active – must happen here in this activity, to get result
        Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mDeviceAdmin);
        intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, mContext.getString(R.string.device_admin_description));
        startActivityForResult(intent, REQUEST_CODE_ENABLE_ADMIN);
    } else {
        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        // always return 1
        List<UserHandle> h = um.getUserProfiles();
        // crashes !!! saying I need MANAGE_USERS persmission
        mDPM.switchUser(mDeviceAdmin, h.get(0)); 
    }
    

    I can see my app in the settings menu as device administrator.

  4. So I went to the manifest and added these 2 permissions:

    <permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
        android:protectionLevel="signature"
        android:label="@string/manage_users_permission"
        android:description="@string/manage_users_permission_description" />
    
    <permission android:name="android.permission.MANAGE_USERS"
        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
        android:protectionLevel="signature"
        android:label="@string/manage_users_permission"
        android:description="@string/manage_users_permission_description" />
    
  5. This also didn't work, so I found out that I need to sign my app and I have no idea how to even start doing that. I found posts saying I need these 2 files: platform.x509.pem, platform.pk8 so I went and got them from our source code team who worked on the ROM we have installed. I asked a Linux guy to run keytool-importkeypair as shown here: Apk with system privileges, this got me a file: debug.keystore which I placed in the app folder of my application.

  6. Then I've added this to the build.gradle file in the project:

    signingConfigs {
        release {
            storeFile file("debug.keystore")
            storePassword "test123"
            keyAlias "platform"
            keyPassword "test123"
        }
    }
    
  7. None of these solved my problem and I still can't get MANAGE_USERS permission and I still can't switch users and then I saw a post saying add this: android:sharedUserId="android.uid.system" to the <manifest> tag and this got me this error INSTALL_FAILD_SHARED_USER_INCOMPATIBLE

I'm very new to android, and this is very advanced for me to understand but I have to do this at work and there are no other Android developers here...

Community
  • 1
  • 1
Liran Friedman
  • 4,027
  • 13
  • 53
  • 96

1 Answers1

0

You can only use "android.uid.system" when your app is signed with platform key.

Anuj J Pandey
  • 656
  • 1
  • 4
  • 17
  • Can you please tell me how can I sign my app with platform key? And please be as specific as possible since I'm very new to Android :-) – Liran Friedman Mar 02 '17 at 10:25
  • It is only possible if you have platform key pair of the device and if you are developing simply an app for universal devices then it wont be possible. – Anuj J Pandey Mar 02 '17 at 10:54
  • I install the app on a device at work which have a custom CyanogenMod ROM, they gave me the platform key pair files: `platform.x509.pem`& `platform.pk8`. – Liran Friedman Mar 02 '17 at 10:59
  • great then signed your build with this credentials, and install it – Anuj J Pandey Mar 02 '17 at 11:10
  • PLEASE tell me what does it mean and how do I do this: "to sign my build with these credentials and install it" – Liran Friedman Mar 02 '17 at 11:12
  • First you need to create an unsigned build then you can signed it using 'signedapk.jar' 1. Open your project in android studio 2. Go to Run>>Edit Congfiguration 3. Configuration screen have an Add button on left corner click it 4. Select Gradle 5. write assemble in Tasks 6. In Gradle Project Select your app 7. Press ok 8. Click on run button and make sure your configuration is selected 9. Once you'll run this an unsigned build will there in builds directory Now you can signed it using the below instruction https://github.com/appium/sign – Anuj J Pandey Mar 02 '17 at 13:09
  • Thank you for the instructions, I followed them up until #9. Where do I find this "builds" folder ? Is it under: "MyApp\app\build\outputs\apk" ? I saw 2 files there: `app-debug.apk` & `app-release-unsigned.apk` – Liran Friedman Mar 02 '17 at 13:57
  • Yes use this one app-release-unsigned.apk – Anuj J Pandey Mar 03 '17 at 05:01
  • I'll try to sign my apk as you instructed, after that I need to manually copy it to the device and install it with ads install? How can I debug my app this way? Is there a way I can run it on the device using Android Studio and be able to debug it the regular way ? – Liran Friedman Mar 03 '17 at 08:13
  • No even I don't able to debug it while it is running as system app – Anuj J Pandey Mar 03 '17 at 09:57
  • So just install apk each time and test on the device. Right? – Liran Friedman Mar 03 '17 at 10:00
  • yes how ever you can create bat files to create signed build and install it on device:
    java -jar signapk.jar platform.x509.pem platform.pk8 app-platform-unsigned.apk Platform.apk adb install Platform.apk TIMEOUT /T 5
    or for update
    java -jar signapk.jar platform.x509.pem platform.pk8 app-platform-unsigned.apk Platform.apk adb install -r Platform.apk TIMEOUT /T 5
    – Anuj J Pandey Mar 03 '17 at 10:03
  • If you satisfied with ans please don't forget rate, – Anuj J Pandey Mar 03 '17 at 10:04
  • Sorry for the delay, I signed my apk and copied it to the device, clicked the apk file to install it but the installation failed... – Liran Friedman Mar 07 '17 at 07:34
  • I tried running on terminal `adb Install Platform.apk` I get this error message: `error: cannot connect to daemon * daemon not runing. starting it now on port 5038 * cannot bind 'tcp:5038' ADB server didn't ACK * failed to start daemon *` – Liran Friedman Mar 07 '17 at 07:41
  • check there may b more than one adb server is running on your system – Anuj J Pandey Mar 07 '17 at 08:43
  • I was told that when running on a terminal from the device it self to use `pm install`. Can that be the issue? If not, how can I perform the check you suggested? – Liran Friedman Mar 07 '17 at 09:41
  • Now I'm getting `install_failed_invalid_install_location` – Liran Friedman Mar 07 '17 at 15:46
  • Although my reply is a few months past the the time of the initial thread, but if it may serve to help in any future projects, it seems there's a manner of a short how-to available at https://stackoverflow.com/a/3651653 Of course there's also Android for Enterprise https://www.android.com/enterprise/ perhaps they may have some documentation available about device management for development in the corporate institution, if an agency may so endeavor – Sean Champ Dec 18 '17 at 00:35