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

如何保持Android多线程FileObserver前台服务持续运行?

Hey there! I see you're building an Android app to monitor the entire file system, and you've got a foreground service set up but it won't run permanently. Let's break down the issues and fix them step by step.

1. Fix the Service Restart Behavior

Right now, your onStartCommand returns the default value from super.onStartCommand(), which doesn’t tell the system to restart your service if it gets killed. You need to change this return value to ensure the service sticks around:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    observe();
    // Use START_STICKY to restart the service if it's killed by the system
    return START_STICKY;
    // Or use START_REDELIVER_INTENT if you need to re-send the original intent on restart
    // return START_REDELIVER_INTENT;
}

START_STICKY tells Android to restart your service with a null intent if it’s terminated due to resource constraints—perfect for a monitoring service that doesn’t rely on specific intent data.

2. Handle Dynamic Directory Changes

Your current Observer only scans directories once when startWatching() is called. If new directories are created later, they won’t be monitored. Update your onEvent method to add observers for newly created directories:

Modify your Observer class's onEvent method:

@Override
public void onEvent(int event, final String path) {
    if (event == FileObserver.OPEN) {
        writeLog("OPEN", path);
    } else if (event == FileObserver.CREATE && (!path.equals(".probe"))) {
        writeLog("CREATE", path);
        // Check if the created item is a directory, then add a new observer
        File newDir = new File(path);
        if (newDir.isDirectory()) {
            SingleFileObserver newObserver = new SingleFileObserver(path, mMask);
            mObservers.add(newObserver);
            newObserver.startWatching();
        }
    } else if (event == FileObserver.DELETE_SELF || event == FileObserver.DELETE) {
        writeLog("DELETE", path);
    } else if (event == FileObserver.MOVE_SELF || event == FileObserver.MOVED_FROM || event == FileObserver.MOVED_TO) {
        writeLog("MOVE", path);
    }
}

This way, any new directories created after the service starts will automatically be added to your monitoring list.

3. Bypass Battery Optimization Restrictions

Android 8.0 (API 26+) and later have strict battery optimization policies that can kill even foreground services if the app is deemed idle. You need to request the user to exclude your app from battery optimization:

First, add this permission to your AndroidManifest.xml:

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

Then, add code to prompt the user to disable battery optimization (call this when the service starts or the app is first launched):

private void requestBatteryOptimizationExemption() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        Intent intent = new Intent();
        String packageName = getPackageName();
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        if (!pm.isIgnoringBatteryOptimizations(packageName)) {
            intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
            intent.setData(Uri.parse("package:" + packageName));
            startActivity(intent);
        }
    }
}

4. Ensure Boot Completion Setup

You mentioned the service is set to start on boot—double-check you have all pieces in place:

  • Add the boot permission to AndroidManifest.xml:
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    
  • Create a broadcast receiver to start your service on boot:
    public class BootReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
                Intent serviceIntent = new Intent(context, FileSystemObserverService.class);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    context.startForegroundService(serviceIntent);
                } else {
                    context.startService(serviceIntent);
                }
            }
        }
    }
    
  • Register the receiver in AndroidManifest.xml:
    <receiver android:name=".BootReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    

5. Minor Logging Improvement

Your writeLog method opens and closes the file every time an event occurs, which can be inefficient. Use try-with-resources to avoid resource leaks and simplify the code:

public void writeLog(final String event, final String path){
    String filename = getFilesDir().toString() + "/log.txt";
    String to_write = event + " " + path + "\n";
    try (BufferedWriter bw = new BufferedWriter(new FileWriter(filename, true))) {
        bw.write(to_write);
    } catch (Exception e){
        e.printStackTrace();
        Log.i("onEvent","Exception Error: " + e.getMessage());
    }
}

Putting all these changes together should make your service run much more reliably, even through system restarts and resource constraints.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 07:02:44