3

我想听听文件系统中发生的变化。我正在使用 FileObserver。这是我的代码:

代码:

class MyDirObserver extends FileObserver {
    String superPath;
    public MyDirObserver(String path) {
        super(path, ALL_EVENTS);
        this.superPath = path;
    }


    public void onEvent(int event, String path) {
        Log.e("onEvent of Directory", "=== onEvent ===");
        try {
            _Dump("dir", event, path, superPath);
        } catch (NullPointerException ex) {
            Log.e("ERROR", "I am getting error");
        }
    }
}


private void _Dump(final String tag, int event, String path, String superPath) {
    Log.d(tag, "=== dump begin ===");
    Log.d(tag, "path=" + path);
    Log.d(tag, "super path=" + superPath);
    Log.d(tag, "event list:");
    if ((event & FileObserver.OPEN) != 0) {
        Log.d(tag, "  OPEN");
    }
    if ((event & FileObserver.CLOSE_NOWRITE) != 0) {
        Log.d(tag, "  CLOSE_NOWRITE");
    }
    if ((event & FileObserver.CLOSE_WRITE) != 0) {


        Log.d(tag, "  CLOSE_WRITE");
        Log.i("NEWFILEOBSERVER", "File is Modified");
        if (path != null) {
            Log.d("---------FilePath", superPath + path);
        }


    }
    if ((event & FileObserver.CREATE) != 0) {
        isCreate = true;
        Log.i("NEWFILEOBSERVER", "File is Created ");
        if (path != null) {
            Log.d("---------FilePath", superPath + path);
        }
        Log.d(tag, "  CREATE");


    }
    if ((event & FileObserver.DELETE) != 0) {
        Log.i("NEWFILEOBSERVER", "File is deleted");
        if (path != null) {
            Log.d("---------FilePath", superPath + path);
        }
        //  startMyActivity("A new file is deleted thats="+superPath); 


        Log.d(tag, "  DELETE");


    }

    if ((event & FileObserver.DELETE_SELF) != 0) {
        Log.d(tag, "  DELETE_SELF");
    }

    if ((event & FileObserver.ACCESS) != 0) {
        Log.d(tag, "  ACCESS");
    }

    if ((event & FileObserver.MODIFY) != 0) {
        if (!isModified)
            isModified = true;

        if (isModified && isOpen)
            isAgainModified = true;
        Log.d(tag, "  MODIFY");
    }

    if ((event & FileObserver.MOVED_FROM) != 0) {
        Log.d(tag, "  MOVED_FROM");
        if (path != null) {
            Log.d("---------FilePath", superPath + path);
        }
    }

    if ((event & FileObserver.MOVED_TO) != 0) {
        Log.d(tag, "  MOVED_TO");
        if (path != null) {
            Log.d("---------FilePath", superPath + path);
        }
    }

    if ((event & FileObserver.MOVE_SELF) != 0) {
        Log.d(tag, "  MOVE_SELF");
    }

    if ((event & FileObserver.ATTRIB) != 0) {
        Log.d(tag, "  ATTRIB");
    }

    Log.d(tag, "=== dump end ===");
}

它在一段时间后停止。我没有得到确切的时间,但并不总是工作,尽管我在服务中调用 startWatching() 在一个循环中为 sdcard 的所有文件夹运行并为每个文件夹调用 startWatching()。它显示出不可预测的行为并停止侦听某些文件夹并为其他文件夹完美运行。

我希望你们帮助我。我尝试了很多方法,但它并不完美。难道我做错了什么?或者有其他方法可以做到这一点。

4

4 回答 4

9

http://developer.android.com/reference/android/os/FileObserver.html

警告:如果 FileObserver 被垃圾回收,它将停止发送事件。为确保您继续接收事件,您必须保留对其他活动对象的 FileObserver 实例的引用。

于 2011-04-19T22:01:40.680 回答
1

将 FileObserver 声明为静态和全局,它将保留 Fileobserver 的实例并限制操作系统将服务带入垃圾收集器。

于 2015-02-19T12:36:02.987 回答
1

我将在我的应用程序中向您展示部分代码,它将您用手机拍摄的每张照片通过电子邮件发送到预先定义的电子邮件列表。发送电子邮件和接收电子邮件列表存储在共享首选项中。我使用 Service 类和 FileObserver 来观看手机的图片目录。就我而言,这个方案也解决了 FileObserver 的问题,它在一段时间后停止工作。

  1. 使用活动 (StartServicesActivity) 将服务 (FileObserverService) 启动为前台服务。
  2. 使用 BroadcastReceiver 类(例如 CommonReceiver)在某些特殊情况下重新启动您的服务,以防它被杀死。
  3. 每次重新启动服务时(执行 onStartCommand)重新创建 FileObserver 对象以观看图片目录。

我在我的应用程序“自动通过电子邮件发送图片”中使用了此代码 https://play.google.com/store/apps/details?id=com.alexpap.EmailPicturesFree

这是 CommonReceiver 类。

public class CommonReceiver extends BroadcastReceiver {

    public void onReceive(Context paramContext, Intent paramIntent)
    {
        paramContext.startService(new Intent(paramContext, FileObserverService.class));
    }
}

这是它在 AndroidManifest.xml 中应用程序结束标记之前的定义。

<receiver android:name="com.alexpap.services.CommonReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.USER_PRESENT"/>
    </intent-filter>
</receiver>

在 StartServicesActivity 活动中启动服务。

Intent iFileObserver = new Intent(StartServicesActivity.this, FileObserverService.class);
StartServicesActivity.this.startService(iFileObserver);

这是服务 FileObserverService 的 onCreate() 方法。

//Class variables
MediaFileObserver observPictures = null;
String pathToWatchPic = "";

public void onCreate() {

    pathToWatchPic = Environment.getExternalStorageDirectory().toString() + "/DCIM/100MEDIA";       

    File  mediaStorageDir = new File(pathToWatchPic); 
    if (!mediaStorageDir.exists()){
        pathToWatchPic = Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera";
    }

}

这是服务 FileObserverService 的 onStartCommand() 方法。

public int onStartCommand(Intent intent, int flags,  int startId) {

    int res = super.onStartCommand(intent, flags, startId);

    if (observPictures != null){
        observPictures.stopWatching();
    }
    //each time service is restarted, observPictures object is recreated
    //and observation is restarted. This way File Observer never stops.
    observPictures = new MediaFileObserver(this, pathToWatchPic);
    observPictures.startWatching();

    startServiceForeground(intent, flags, startId);

    return Service.START_STICKY;  
}

public int startServiceForeground(Intent intent, int flags, int startId) {

    Intent notificationIntent = new Intent(this, StartServicesActivity.class); 
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    Notification notification = new NotificationCompat.Builder(this)
        .setContentTitle("File Observer Service")
        .setContentIntent(pendingIntent)
        .setOngoing(true)
            .build();

    startForeground(300, notification);

    return START_STICKY;
}

每次打开手机和重新启动后,服务也会重新启动。

于 2015-06-11T21:18:07.997 回答
0

尝试在 Application 类中链接对 Observer 的引用。像这样

private ArrayList<FileObserver> mObservers = new ArrayList<FileObserver>();

public void addObserver(FileObserver observer){
    mObservers.add(observer);
}

public void removeObserver(FileObserver observer){
    mObservers.remove(observer);
}

这对我有用!

于 2014-06-10T15:48:46.433 回答