You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Xamarin的考试APP如何检测悬浮/multiwindow应用及应用切换并终止考试?

Answer: Detecting Floating Apps, Multi-Window, and App Switches in Xamarin Exam App

Hey there! Great question—this is a critical requirement for exam proctoring apps, and totally achievable with Xamarin. Let’s break this down by platform since Android and iOS handle app lifecycle, multi-window, and overlay detection very differently:

Android Implementation

Android gives us more flexibility to monitor system-level events, but you’ll need to request specific permissions first.

1. Detect App Switches (Foreground/Background)

To check if your app is no longer in the foreground, you have two reliable options:

  • Activity Lifecycle Hooks: Override OnPause() in your main Activity, but note this can trigger for normal actions like screen rotation. For stricter checks, use the UsageStatsManager to verify the current foreground app package:
    using Android.App;
    using Android.Content;
    using Android.App.Usage;
    using System;
    
    public bool IsAppInForeground(Context context)
    {
        var usageStatsManager = (UsageStatsManager)context.GetSystemService(Context.UsageStatsService);
        long currentTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
        var stats = usageStatsManager.QueryUsageStats(UsageStatsInterval.Daily, currentTime - 10000, currentTime);
    
        if (stats?.Count > 0)
        {
            string currentPackage = null;
            long lastUsed = 0;
            foreach (var stat in stats)
            {
                if (stat.LastTimeUsed > lastUsed)
                {
                    lastUsed = stat.LastTimeUsed;
                    currentPackage = stat.PackageName;
                }
            }
            return currentPackage == context.PackageName;
        }
        return false;
    }
    
  • Schedule Periodic Checks: Use a Handler or AlarmManager to run the above check every few seconds. If it returns false, trigger the exam termination.

2. Detect Multi-Window Mode

Android has a built-in callback for multi-window state changes. Add this to your main Activity:

protected override void OnMultiWindowModeChanged(bool isInMultiWindowMode, Android.OS.Configuration newConfig)
{
    base.OnMultiWindowModeChanged(isInMultiWindowMode, newConfig);
    if (isInMultiWindowMode)
    {
        // Trigger exam termination here
        TerminateExam(this);
    }
}

private void TerminateExam(Activity activity)
{
    activity.RunOnUiThread(() =>
    {
        new AlertDialog.Builder(activity)
            .SetTitle("Exam Terminated")
            .SetMessage("Multi-window mode detected. Your exam has been ended.")
            .SetPositiveButton("OK", (s, e) => activity.Finish())
            .Show();
    });
}

3. Detect Floating/Overlay Apps

To detect floating overlays (like chat heads or screen recorders):

  • First, request the SYSTEM_ALERT_WINDOW permission in your AndroidManifest.xml:
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    
  • Use an AccessibilityService to monitor window events. Create a service class:
    [Service(Label = "Overlay Monitor", Permission = Android.Manifest.Permission.BindAccessibilityService)]
    [IntentFilter(new[] { Android.Accessibility.AccessibilityService.ActionAccessibilityService })]
    [MetaData(Android.Accessibility.AccessibilityService.MetaDataAccessibilityService, Resource = "@xml/accessibility_service_config")]
    public class OverlayMonitorService : AccessibilityService
    {
        public override void OnAccessibilityEvent(AccessibilityEvent e)
        {
            if (e.EventType == Android.Accessibility.EventTypes.WindowStateChanged)
            {
                var windowType = e.WindowType;
                // Check if the window is an overlay
                if (windowType == Android.Views.WindowManagerTypes.ApplicationOverlay)
                {
                    // Trigger exam termination
                    TerminateExam(this);
                }
            }
        }
    
        public override void OnInterrupt() { }
    }
    
  • Create an accessibility config file (Resources/xml/accessibility_service_config.xml) to enable window monitoring:
    <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
        android:accessibilityEventTypes="typeWindowStateChanged"
        android:accessibilityFeedbackType="feedbackGeneric"
        android:accessibilityFlags="flagDefault"
        android:canRetrieveWindowContent="true"/>
    
  • You’ll need to guide users to enable accessibility permissions for your app in system settings.

Required Permissions

Don’t forget to add these to your AndroidManifest.xml:

<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

iOS Implementation

iOS is more restrictive, but you can still monitor app switches and multi-window (iPad-only) events using lifecycle callbacks.

1. Detect App Switches

iOS triggers DidEnterBackground when the app is sent to the background (e.g., user switches to another app). Add this to your AppDelegate:

public override void DidEnterBackground(UIApplication application)
{
    base.DidEnterBackground(application);
    // Trigger exam termination
    TerminateExam();
}

private void TerminateExam()
{
    UIApplication.SharedApplication.InvokeOnMainThread(() =>
    {
        var alert = UIAlertController.Create("Exam Terminated", "App switch detected. Your exam has been ended.", UIAlertControllerStyle.Alert);
        alert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, (action) =>
        {
            // Close all view controllers or exit the app
            foreach (var window in UIApplication.SharedApplication.Windows)
            {
                window.RootViewController.DismissViewController(true, null);
            }
        }));
        UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(alert, true, null);
    });
}

2. Detect Multi-Window Mode (iPad)

For iPad multi-window support, use SceneDelegate to monitor scene activation states:

public override void DidEnterBackground(UIScene scene)
{
    base.DidEnterBackground(scene);
    // Check if any scene is still active
    var activeScene = UIApplication.SharedApplication.ConnectedScenes
        .FirstOrDefault(s => s.ActivationState == UISceneActivationState.ForegroundActive);
    if (activeScene == null)
    {
        TerminateExam();
    }
}

3. Detect Floating Apps

iOS doesn’t allow third-party apps to monitor system overlays directly, but you can check for system-level floating features like Picture-in-Picture by listening to relevant notifications (e.g., AVPlayerPictureInPictureControllerDidStartPictureInPictureNotification if your app uses video). For most exam scenarios, monitoring app background state is sufficient to catch users switching to other tools.


Xamarin.Forms Unified Approach

To keep your code clean, use DependencyService to wrap platform-specific monitoring logic:

  1. Define a shared interface in your Forms project:
    public interface IExamMonitorService
    {
        void StartMonitoring();
        void StopMonitoring();
    }
    
  2. Implement this interface in your Android and iOS projects as shown above.
  3. Initialize the service in your Forms app:
    DependencyService.Get<IExamMonitorService>().StartMonitoring();
    

内容的提问来源于stack exchange,提问作者Alberto Pineda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:52:08