I have created a device owner app but I am having trouble installing it on a real device. I'm generating Qr Code Using https://datalogic.github.io/aeqrdoc/generat.
The text I am using to create my QR Code is
{
"android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME": "com.example.demo/com.example.demo.DemoAppDeviceAdminReceiver",
"android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM": "DyseoYKEDCtnYx3jyiHCdLUvZ7F-uFenEe4sZ9bRZYw",
"android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION": "https://www.dropbox.com/scl/fi/q6094argfv56z8zd1i589/app-release.apk?rlkey=alt5estnbfj5oqazbrmfm7ppc&dl=1"
}
I generate my apk from Android studio by doing this: Build -> Generate Signed Bundle/Apk->select APK-> Create a new keystore -> Ok -> Next-> Select "Release"-> Build. Then I create the package checksum using
cat /mnt/c/Users/Antarpuneet/app-release.apk | openssl dgst -binary -sha256 | openssl base64 | tr '+/' '-_' | tr -d '='
After doing a factory reset, tapping 6 times on the welcome screen opens a QR reader app, I scan the code and then It takes me to the WIFI connection screen, I successfully connect to the Internet. It says Setting up device.. but returns with the Error Can't setup device- Couldn't install the admin app.
This is DemoAppDeviceAdminReceiver Class :-
package com.example.demo;
import static android.content.ContentValues.TAG;
import android.app.admin.DeviceAdminReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class DemoAppDeviceAdminReceiver extends DeviceAdminReceiver {
// Optional: Override methods as needed for handling device admin events
// For example:
@Override
public void onEnabled(Context context, Intent intent) {
// Device admin enabled
super.onEnabled(context, intent);
Log.d(TAG, "Device Owner Enabled");
Toast.makeText(context, "DemoAppDeviceAdminReceiver: Enable Device Admin", Toast.LENGTH_SHORT).show();
}
@Override
public CharSequence onDisableRequested(Context context, Intent intent) {
// Return a message when a user tries to disable the device admin
return "Disabling this device admin will remove important functionality.";
}
// Other overrides for admin events as required
static ComponentName getComponentName(Context context){
return new ComponentName(context.getApplicationContext(), DemoAppDeviceAdminReceiver.class);
}
}
My Main Activity:-
package com.example.demo;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private int YOUR_REQUEST_CODE = 100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ComponentName adminComponentName = new ComponentName(this, DemoAppDeviceAdminReceiver.class);
DevicePolicyManager devicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
//TODO: To request Device Admin Activation
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, adminComponentName);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "Explanation of why your app needs device admin access");
//TODO: To start Activity that will prompt the user to grant device Admin privileges to the app
startActivityForResult(intent, YOUR_REQUEST_CODE);
//TODO: To check the app is device admin or not
boolean isAdminActive = devicePolicyManager.isAdminActive(adminComponentName);
if (isAdminActive) {
// Your app is a device admin
Toast.makeText(this, "Your app is a device admin", Toast.LENGTH_SHORT).show();
} else {
// Your app is not a device admin
Toast.makeText(this, "Your app is not a device admin", Toast.LENGTH_SHORT).show();
}
//TODO: To check the app is device Owner or not
if (devicePolicyManager.isDeviceOwnerApp("com.example.demo")) {
Toast.makeText(this, "YES", Toast.LENGTH_SHORT).show();
Log.i("Status", "Yes");
} else {
Toast.makeText(this, "NO", Toast.LENGTH_SHORT).show();
Log.i("Status", "No");
}
// devicePolicyManager.reboot(adminComponentName);
}
[enter image description here](https://i.stack.imgur.com/swnkZ.jpg) //TODO: To handle the result of the device Admin Activation request
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == YOUR_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
// Device admin was activated successfully
Toast.makeText(this, "Device admin was activated successfully", Toast.LENGTH_SHORT).show();
} else {
// Device admin activation was canceled or failed
Toast.makeText(this, "Device admin activation was canceled or failed", Toast.LENGTH_SHORT).show();
}
}
}
}
My Manifest file:-
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.demo">
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
android:allowBackup="true"
android:sharedUserId="android.uid.system"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Demo"
android:testOnly="false"
>
<activity
android:name=".MainActivity"
android:exported="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Declare the Device Admin Receiver -->
<receiver
android:name=".DemoAppDeviceAdminReceiver"
android:label="@string/app_name"
android:exported="true"
android:permission="android.permission.BIND_DEVICE_ADMIN"
>
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin_receiver" />
</receiver>
</application>
</manifest>
device_admin_receive.xml :-
<?xml version="1.0" encoding="utf-8"?>
<device-admin>
<uses-policies>
<!-- Define device admin policies here -->
<limit-password />
<watch-login />
<!-- Add other policies your app requires -->
<reset-password />
<force-lock />
<wipe-data />
<expire-password />
<encrypted-storage />
<disable-camera />
<disable-keyguard-features />
</uses-policies>
</device-admin>
What I have already tried:
Installing the app on an Emulator using the adb shell command adb shell dpm set-device-owner com.example.demo/.DemoAppDeviceAdminReceiver
It successfully sets the app as a Device owner.
Installing the app on a real device(after factory reset and skipping sign in page) using the adb command above. It successfully sets up the app as device owner. I think this means that the problem is with the QR-Code.
I am trying to install it on a device with Android Version 13.
Now, My app is being downloaded but while installing, it says Blocked by Play Protect and when I tap on Install Anyway, it returns with the old error: Can't set up device - Couldn't install the admin app
Might be that you have "Verify apps over USB" turned on.
This "Check apps installed via ADB/ADT for harmful behaviour", basic it sends your app to google for review even if you don't ever submit it to Google yourself.
This can be turned of in the Developer system settings.