3

ファイルシステムで発生した変更をリッスンしたい.私は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 ===");
}

しばらくすると停止します。正確な時間はわかりませんが、常に機能するとは限りませんが、sdcardのすべてのフォルダーに対して実行され、それぞれに対して startWatching() を呼び出すループ内でサービスで startWatching() を呼び出します。予期しない動作を示し、一部のフォルダーのリッスンを停止し、他のフォルダーに対しては完全に実行されます。

皆さんが私を助けてくれることを願っています。私は多くの方法を試しましたが、完全には機能しません。私は何か間違ったことをしていますか?または、これを行う他の方法があります。

4

4 に答える 4

9

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

警告: FileObserver がガベージ コレクションされると、イベントの送信が停止します。イベントを確実に受信し続けるには、他のライブ オブジェクトから FileObserver インスタンスへの参照を維持する必要があります。

于 2011-04-19T22:01:40.680 に答える
1

私のアプリケーションのコードの一部を紹介します。これは、携帯電話で撮影したすべての写真を事前に定義された電子メールのリストに電子メールで送信します。送信メールと受信メールのリストは共有設定に保存されます。Service クラスと FileObserver を使用して、電話の写真ディレクトリを監視します。私の場合、このスキームは、しばらくすると動作を停止する FileObserver の問題も解決します。

  1. アクティビティ (StartServicesActivity) を使用して、サービス (FileObserverService) をフォアグラウンド サービスとして開始します。
  2. BroadcastReceiver クラス (例では CommonReceiver) を使用して、いくつかの特別な状況でサービスを再起動し、サービスが強制終了された場合に備えます。
  3. サービスが再起動される (onStartCommand を実行する) たびに、FileObserver オブジェクトを再作成して、pictures ディレクトリを監視します。

このコードをアプリの「写真を自動的にメールで送信」 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 に答える