FileObserver回调不会触发(有关stackoverflow的详细信息,请参阅详细信息)

时间:2018-04-17 10:24:59

标签: android fileobserver

我正在尝试侦听外部存储目录中的任何事件,即通过Android FileObserver添加,删除或修改文件,但其onEvent方法永远不会被调用。

我已经尝试了以下所有解决方案:

Android FileObserver [duplicate]

FileObserver instance is being garbage collected

How do you implement a FileObserver from an Android Service

至于我的代码,下面给出了它:

清单

@extends('layout')

@section ('content')
 This page is last visited on Apr 16
@endsection

服务

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.grapgame.fileobserverdemo">

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

<application
    android:name=".AppClass"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service android:name=".FileObserverService" />
</application>

</manifest>

AppClass.java

public class FileObserverService extends Service {

public static final String TAG = "FileObserverService";

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "onStart");

    final String pathToWatch = android.os.Environment.getExternalStorageDirectory().toString();
    Toast.makeText(this, "My Service Started and trying to watch " + pathToWatch, Toast.LENGTH_LONG).show();

    AppClass.fileObserver = new FileObserver(pathToWatch) { // set up a file observer to watch this directory on sd card
        @Override
        public void onEvent(int event, String file) {
            Log.d(TAG, "File created [" + pathToWatch + file + "]");
        }
    };
    AppClass.fileObserver.startWatching();
    return START_STICKY;
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

MainActivity.java

public class AppClass extends Application {
    public static FileObserver fileObserver;

    @Override
    public void onCreate() {
        super.onCreate();
    }
}

我也尝试过没有AppClass.java,我在Stackoverflow上找到了这个解决方案并尝试过。我也试过这个GitHub代码但似乎没什么用。

我知道FileObserver不是递归的,因为现在我只是想听一个目录。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

使用RecursiveFileObserver下面的类

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import android.os.FileObserver;
import android.util.Log;

public class RecursiveFileObserver extends FileObserver {
    /**
     * Only modification events
     */
    public static int CHANGES_ONLY = CREATE | DELETE | CLOSE_WRITE | MOVE_SELF | MOVED_FROM | MOVED_TO;

    List<SingleFileObserver> mObservers;
    String mPath;
    int mMask;

    public RecursiveFileObserver(String path) {
        this(path, ALL_EVENTS);
    }

    public RecursiveFileObserver(String path, int mask) {
        super(path, mask);
        mPath = path;
        mMask = mask;
    }

    @Override
    public void startWatching() {
        if (mObservers != null) return;

        mObservers = new ArrayList<SingleFileObserver>();
        Stack<String> stack = new Stack<String>();
        stack.push(mPath);

        while (!stack.isEmpty()) {
            String parent = stack.pop();
            mObservers.add(new SingleFileObserver(parent, mMask));
            File path = new File(parent);
            File[] files = path.listFiles();
            if (null == files) continue;
            for (File f : files) {
                if (f.isDirectory() && !f.getName().equals(".") && !f.getName().equals("..")) {
                    stack.push(f.getPath());
                }
            }
        }

        for (SingleFileObserver sfo : mObservers) {
            sfo.startWatching();
        }
    }

    @Override
    public void stopWatching() {
        if (mObservers == null) return;

        for (SingleFileObserver sfo : mObservers) {
            sfo.stopWatching();
        }
        mObservers.clear();
        mObservers = null;
    }

    @Override
    public void onEvent(int event, String path) {
        switch (event) {
            case FileObserver.CREATE:
                Log.i("RecursiveFileObserver", "CREATE: " + path);

                break;
            case FileObserver.MODIFY:
                Log.i("RecursiveFileObserver", "MODIFY: " + path);
                break;
        }
    }

    /**
     * Monitor single directory and dispatch all events to its parent, with full path.
     *
     * @author uestc.Mobius <mobius@toraleap.com>
     * @version 2011.0121
     */
    class SingleFileObserver extends FileObserver {
        String mPath;

        public SingleFileObserver(String path) {
            this(path, ALL_EVENTS);
            mPath = path;
        }

        public SingleFileObserver(String path, int mask) {
            super(path, mask);
            mPath = path;
        }

        @Override
        public void onEvent(int event, String path) {
            String newPath = mPath + "/" + path;
            RecursiveFileObserver.this.onEvent(event, newPath);
        }
    }
}

您的服务将如下所示

import android.app.Service;
import android.content.Intent;
import android.os.Environment;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import java.io.File;

public class FileObserverService extends Service {

    public static final String TAG = "FileObserverService";

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand: Service Started");
        File sdCard = Environment.getExternalStorageDirectory();
        AppClass.fileObserver = new RecursiveFileObserver(sdCard.getAbsolutePath());
        AppClass.fileObserver.startWatching();
        return START_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy: Service Destroyed");
    }
}

和AppClass一样

public class AppClass extends Application {
    public static RecursiveFileObserver fileObserver;

    @Override
    public void onCreate() {
        super.onCreate();
        Intent intent = new Intent(this, FileObserverService.class);
        startService(intent);
    }
}