文件观察器在一段时间后停止工作

时间:2010-03-16 07:20:40

标签: android fileobserver

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

代码:

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 个答案:

答案 0 :(得分:8)

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

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

答案 1 :(得分:1)

将FileObserver声明为Static和global,它将保留Fileobserver的实例并限制OS将服务带入垃圾收集器。

答案 2 :(得分:1)

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

  1. 使用活动(StartServicesActivity)将服务(FileObserverService)作为Foreground服务启动。
  2. 使用BroadcastReceiver类(在示例CommonReceiver中)在某些特殊情况下重启您的服务,以防它被杀死。
  3. 每次重新启动服务(执行onStartCommand)时,重新创建FileObserver对象以观察图片目录。
  4. 我在我的应用“自动发送电子邮件”中使用了此代码 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;
    }
    

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

答案 3 :(得分: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);
}

这对我有用!