I’m trying to run an app on the android emulator with full kiosk mode. So I wrote a DeviceAdminReceiver:
public class AdminReceiver : DeviceAdminReceiver { public override void OnEnabled(Context context, Intent intent) { base.OnEnabled(context, intent); Log.Info("Device Admin: ", "Enabled"); } public override void OnDisabled(Context context, Intent intent) { base.OnDisabled(context, intent); Log.Info("Device Admin: ", "Disabled"); } }
Here’s the MainActivity:
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)] [IntentFilter(new[] { Intent.ActionMain }, Categories = new[] { Intent.CategoryHome, Intent.CategoryDefault })] public class MainActivity : MauiAppCompatActivity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetFullscreenFlags(); var devicePolicyManager = (DevicePolicyManager)GetSystemService(Context.DevicePolicyService); var deviceAdminComponent = new ComponentName(this, Java.Lang.Class.FromType(typeof(AdminReceiver))); var intent = new Intent(DevicePolicyManager.ActionAddDeviceAdmin); intent.PutExtra(DevicePolicyManager.ExtraDeviceAdmin, deviceAdminComponent); intent.PutExtra(DevicePolicyManager.ExtraAddExplanation, "Device administrator"); StartActivity(intent); devicePolicyManager.SetLockTaskPackages(deviceAdminComponent, new[] { PackageName }); StartLockTask(); } private void SetFullscreenFlags() { Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen); if (Build.VERSION.SdkInt >= BuildVersionCodes.R) { Window.SetDecorFitsSystemWindows(true); var controller = Window.InsetsController; if (controller is not null) { controller.Hide(WindowInsets.Type.StatusBars() | WindowInsets.Type.NavigationBars()); } } else { Window.DecorView.SystemUiVisibility = (StatusBarVisibility) (SystemUiFlags.LowProfile | SystemUiFlags.Fullscreen | SystemUiFlags.LayoutFullscreen | SystemUiFlags.HideNavigation | SystemUiFlags.LayoutHideNavigation | SystemUiFlags.Immersive | SystemUiFlags.ImmersiveSticky); } }
And finally here’s the AndroidManifest.xml:
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" /> <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"> <receiver android:name=".AdminReceiver" 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" /> <action android:name="android.app.action.DEVICE_ADMIN_DISABLED" /> </intent-filter> </receiver> <receiver android:name=".BootReceiver"> <intent-filter> <action android:name="android.intent.action.PROFILE_PROVISIONING_COMPLETE"/> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> </application>
The problem is that this line in MainActivity throw this exception:
devicePolicyManager.SetLockTaskPackages(deviceAdminComponent, new[] { PackageName }); Java.Lang.SecurityException: 'No active admin ComponentInfo{com.companyName.TestApp/crc6463b464086cdcaa12.AdminReceiver}'
I already have a device_admin.xml in resources/xml with a device-admin tag, does it need more configuration? Or is the issue else where? Or maybe i’m instanciating two difference admin receiver?
Note: I already did the procedure to allow this app as device admin on the emulator and run the command via android debug bridge setting it as device owner:
dpm set-device-owner com.companyName.TestApp/.AdminReceiver
Advertisement
Answer
Can you ensure that you are actually registering your BroadcastReceiver
with attributes on the class instead of modifying the AndroidManifest.xml manually. I think what is throwing you off is that if you don’t register the receiver, it will get named as <md5 sum>.AdminReceiver
. However, when you are adding the reciever as .AdminReceiver
in the AndroidManifest.xml, then Android will inflate that as <package name>.AdminReciever
. So your AdminReceiver won’t get called.
So try something like:
[BroadcastReceiver( Name = "your.packagename.AdminReceiver", Description = "@string/device_owner_description", Label = "My Device Admin Receiver", Permission = Manifest.Permission.BindDeviceAdmin)] [MetaData("android.app.device_admin", Resource = "@xml/device_admin")] public class AdminReceiver : DeviceAdminReceiver { }
Then you should remove your entry in the manifest.
If you need to filter specific intents, you can also add the [IntentFilter]
attribute to add those, but it shouldn’t be necessary for device admin.