You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何让Flutter应用在Android平板上24/7保持前台运行?

Fixing 24/7 Persistent Display for Your Android Tablet Flutter App

Hey there! I’ve worked on several kiosk-style Flutter apps for Android tablets that need non-stop runtime, so I know exactly the headaches you’re facing. Let’s break down how to eliminate the lockscreen issue and keep your app reliably in the foreground around the clock:

1. Stop the Lockscreen from Ever Appearing (Root Cause Fix)

Your current WAKE_LOCK and screen plugin help keep the display on, but they don’t fully disable the system lockscreen. Here are two foolproof ways:

Option A: System-Level Settings (Easiest if You Control the Tablet)

Since this is a dedicated display device, just turn off the lockscreen directly in Android settings:

  • Go to Settings > Security > Screen Lock
  • Select None (or "Swipe" if you need minimal protection, but "None" is best for 24/7 display)

Option B: Programmatic Lockscreen Disable (Device Policy Manager)

If you can’t rely on manual settings, use Android’s Device Policy Manager to permanently disable the lockscreen. This requires user approval once, but it’s fully automated after that:

Step 1: Add Device Admin Components to AndroidManifest.xml

<receiver
    android:name=".DeviceAdminReceiver"
    android:description="@string/device_admin_description"
    android:label="@string/app_name"
    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" />
    </intent-filter>
</receiver>

Step 2: Create res/xml/device_admin.xml

<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
        <disable-keyguard />
    </uses-policies>
</device-admin>

Step 3: Call Native Code via Flutter MethodChannel

In your Android native code (Kotlin/Java), add a method to activate the device admin and disable the lockscreen:

fun disableKeyguard() {
    val devicePolicyManager = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
    val componentName = ComponentName(this, DeviceAdminReceiver::class.java)
    
    if (devicePolicyManager.isAdminActive(componentName)) {
        // Already active: disable lockscreen
        devicePolicyManager.setKeyguardDisabled(componentName, true)
    } else {
        // Request user to activate device admin
        val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName)
        intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "Enable this to keep the display unlocked")
        startActivityForResult(intent, 1001)
    }
}

Then call this method from your Flutter code on app startup.

2. Keep Your App in the Foreground (Prevent System Termination)

Even with the lockscreen gone, Android’s background restrictions can kill your app after hours. Use these steps to make it "untouchable":

Use a Foreground Service

Android prioritizes foreground apps, so wrap your app’s core logic in a foreground service:

Step 1: Add Permissions to AndroidManifest.xml

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- For Android 12+, add this special use permission -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />

Step 2: Create a Foreground Service Class

class KioskForegroundService : Service() {
    override fun onBind(intent: Intent): IBinder? = null

    override fun onCreate() {
        super.onCreate()
        // Create a low-priority notification channel (won't bother users)
        val channelId = "kiosk_service_channel"
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                channelId,
                "Kiosk Display Service",
                NotificationManager.IMPORTANCE_LOW
            )
            getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
        }
        // Build and show the foreground notification
        val notification = NotificationCompat.Builder(this, channelId)
            .setContentTitle("Display App Running")
            .setContentText("Continuous display service active")
            .setSmallIcon(R.mipmap.ic_launcher)
            .build()
        startForeground(1, notification)
    }
}

Step 3: Start the Service from Flutter

Call this native method on app startup via MethodChannel:

fun startKioskService() {
    val intent = Intent(this, KioskForegroundService::class.java)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForegroundService(intent)
    } else {
        startService(intent)
    }
}

Exempt from Battery Optimization

Android’s battery saver will kill long-running apps unless you opt out:

Step 1: Add Permission to AndroidManifest.xml

<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

Step 2: Request Exemption via Native Code

fun requestBatteryOptimizationExemption() {
    val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
    intent.data = Uri.parse("package:$packageName")
    startActivity(intent)
}

This prompts the user to allow your app to bypass battery restrictions—critical for 24/7 runtime.

3. Solidify Your App as the Default Launcher

You already added the HOME category, but let’s make sure it’s set as the default so users can’t escape to the system desktop:

Verify the Activity Intent Filter

Double-check your MainActivity in AndroidManifest.xml:

<activity
    android:name=".MainActivity"
    android:exported="true"
    android:launchMode="singleTask">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <category android:name="android.intent.category.HOME" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

Set as Default Launcher Programmatically

Add this native method to prompt users to set your app as the default home screen:

fun setAsDefaultLauncher() {
    val intent = Intent(Intent.ACTION_MAIN)
    intent.addCategory(Intent.CATEGORY_HOME)
    intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
    startActivity(Intent.createChooser(intent, "Set as default display app"))
}

Final Checklist

  1. Disable lockscreen via Device Policy Manager or system settings
  2. Start a foreground service to keep the app prioritized
  3. Exempt the app from battery optimization
  4. Set the app as the default launcher

Follow these steps, and your app will run 24/7 without lockscreen interruptions or system termination.

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

火山引擎 最新活动