{"record":{"id":"e0aaacbdca3d729d","repo":"AvaloniaUI/Avalonia","slug":"main-activity-must-implement-iactivityresulthandle","errorCode":null,"errorMessage":"Main activity must implement IActivityResultHandler interface.","messagePattern":"Main activity must implement IActivityResultHandler interface\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Android/Avalonia.Android/Platform/PlatformSupport.cs","lineNumber":19,"sourceCode":"﻿using System;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Android.App;\nusing Android.Content.PM;\n\nnamespace Avalonia.Android.Platform;\n\ninternal static class PlatformSupport\n{\n    private static int s_lastRequestCode = 20000;\n\n    public static int GetNextRequestCode() => s_lastRequestCode++;\n\n    public static async Task<bool> CheckPermission(this Activity activity, string permission)\n    {\n        if (activity is not IActivityResultHandler mainActivity)\n        {\n            throw new InvalidOperationException(\"Main activity must implement IActivityResultHandler interface.\");\n        }\n\n        if (!OperatingSystem.IsAndroidVersionAtLeast(23))\n        {\n            return true;\n        }\n\n        if (activity.CheckSelfPermission(permission) == Permission.Granted)\n        {\n            return true;\n        }\n        \n        var currentRequestCode = GetNextRequestCode();\n        var tcs = new TaskCompletionSource<bool>();\n        mainActivity.RequestPermissionsResult += RequestPermissionsResult;\n        activity.RequestPermissions(new [] { permission }, currentRequestCode);\n\n        return await tcs.Task;","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Android/Avalonia.Android/Platform/PlatformSupport.cs#L1-L37","documentation":"PlatformSupport.CheckPermission is an extension on Activity that launches the runtime permission request flow, which needs the activity to route OnRequestPermissionsResult callbacks. It throws InvalidOperationException when the activity is not an IActivityResultHandler (Avalonia's main activity contract). Without it, the permission result cannot be delivered.","triggerScenarios":"Calling activity.CheckPermission(...) on an Activity that is not the Avalonia main activity (i.e. does not implement IActivityResultHandler). The permission request needs IActivityResultHandler.OnRequestPermissionsResult wiring that only the main activity provides.","commonSituations":"Requesting permissions from a secondary Activity, a Fragment context cast to Activity, or a custom Activity that did not extend AvaloniaMainActivity; integrating permission requests before wiring the activity-result handler.","solutions":["Call CheckPermission from the Avalonia main activity (AvaloniaMainActivity / AvaloniaActivity), which implements IActivityResultHandler.","If using a custom Activity, implement IActivityResultHandler and forward OnRequestActivityResult to RequestPermissionsResult.","Resolve the activity to the main activity (e.g. via the activatable lifetime) before calling CheckPermission.","For Fragments, route through the host main activity rather than the fragment's Activity."],"exampleFix":"// before\nif (activity is not IActivityResultHandler mainActivity)\n    throw new InvalidOperationException(\"Main activity must implement IActivityResultHandler interface.\");\n\n// after (use the main activity from the activatable lifetime, with a clearer message)\nvar handler = (activity as IActivityResultHandler)\n    ?? (Avalonia.Application.Current?.TryGetFeature<IActivatableLifetime>() as AndroidActivatableLifetime)?.CurrentMainActivity as IActivityResultHandler\n    ?? throw new InvalidOperationException(\n        $\"Activity '{activity.GetType().FullName}' must implement IActivityResultHandler; call CheckPermission from the Avalonia main activity.\");","handlingStrategy":"type-guard","validationCode":"// call from the main activity, not an arbitrary activity\nif (activity is not IActivityResultHandler) return; // or route to the main activity","typeGuard":"static bool CanRequest(Activity a) => a is IActivityResultHandler;","tryCatchPattern":"// guard the caller; ensure CheckPermission runs against the Avalonia main activity.","preventionTips":["Route permission requests through AvaloniaMainActivity (IActivityResultHandler).","Implement IActivityResultHandler on custom activities.","Resolve the main activity from the activatable lifetime."],"tags":["android","permissions","activity-result","iactivityresulthandler","platform"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}