Xamarin MAUI 无活动管理员安全异常(Kiosk 模式应用程序)

Xamarin MAUI No Active Admin Security Exception (Kiosk mode app)

我正在尝试 运行 android 模拟器上的一个应用程序,具有完整的信息亭模式。 所以我写了一个 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");
    }
}

这是 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);
        }
    }

最后是 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>
>

问题是 MainActivity 中的这一行抛出了这个异常:

devicePolicyManager.SetLockTaskPackages(deviceAdminComponent, new[] { PackageName });

Java.Lang.SecurityException: 'No active admin ComponentInfo{com.companyName.TestApp/crc6463b464086cdcaa12.AdminReceiver}'

我在 resources/xml 中已经有一个带有设备管理标签的 device_admin.xml,它需要更多配置吗?或者问题出在哪里? 或者也许我正在实例化两个不同的管理员接收器?

注意: 我已经执行了允许该应用程序作为模拟器上的设备管理员的程序,并通过 android 调试桥将其设置为设备所有者 运行 命令:

dpm set-device-owner com.companyName.TestApp/.AdminReceiver

您能否确保您实际上是在 class 上使用属性注册 BroadcastReceiver,而不是手动修改 AndroidManifest.xml。我认为让您失望的是,如果您不注册接收器,它将被命名为 <md5 sum>.AdminReceiver。但是,当您在 AndroidManifest.xml 中将接收器添加为 .AdminReceiver 时,Android 会将其膨胀为 <package name>.AdminReciever。所以你的 AdminReceiver 不会被调用。

所以尝试这样的事情:

[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
{
}

那么您应该在清单中删除您的条目。

如果您需要过滤特定的意图,您也可以添加 [IntentFilter] 属性来添加这些,但设备管理员不需要这样做。