13

ファイル名、ファイルパス、および実行された操作を使用して、オーディオファイルのAndroid SDカードの変更を検出する必要があるAndroidアプリを開発しています。SD カードにファイルを追加する場合の例を知りたい

  1. 追加するファイル名
  2. ファイルのパス
  3. 操作 -- 追加

以前にファイルオブザーバーを試しましたが、そのためにはすべてのディレクトリに適用する必要があります。そこで、他の解決策を探して、Audio.Media.EXTERNAL_CONTENT_URIに関する情報を取得しました。次に、このようなコンテンツオブザーバーを作成しました

UriObserver.java -- これはコンテンツ オブザーバーです。

class UriObserver extends ContentObserver {

    public UriObserver(Handler handler) {
        super(handler);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void onChange(boolean selfChange) {
        // TODO Auto-generated method stub
        super.onChange(selfChange);

        Log.d("INSTANT", "GETTING CHANGES");
    }

}

これはその登録用のコードです

UriObserver observer = new UriObserver(new Handler());

Log.d("INSTANT", "registered content observer");

this.getApplicationContext()
    .getContentResolver()
    .registerContentObserver(
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, false,
    observer);

Log.d("INSTANT", "registered content observer");

音声ファイル関連のsdcardに一部変更があったことをお知らせいたします。ただし、どのファイルが追加、編集、または削除されたかについての情報は何も提供しません。

次に、解決策を検索し、この投稿を取得しました

Android: MTP 経由で接続したときに MediaStore の変更を検出する方法

この投稿では、いくつかのコードがBhieferによって回答として提供されていますが、これはうまくいくと思われるので、それを実装しようとしましたが、実装できませんでした。

これには何ができますか?

アップデート

Audio.Media.EXTERNAL_CONTENT_URI に最新の変更を問い合わせることはできますか? このコード:

mCursor = context.getContentResolver().query(
                    Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, "_id");

mCursor.moveToLast();

最新の変更を提供しません。最新の変更を取得する他の方法はありますか?

4

2 に答える 2

9

ほぐしてみようかな

コンテンツオブザーバー

何が変更されたかについての情報は提供しません

デザイン次第です。ドキュメントには、この情報が得られるとは書かれていません。

ファイルオブザーバー

再帰的ではありません

はい。既知の問題です。すべてのディレクトリを繰り返し処理し、オブザーバーを設定する際の問題は何ですか? 私の理解では、デフォルトでは多くはないはずです(1ダースほどとしましょう)。

Android: MTP 経由で接続したときに MediaStore の変更を検出する方法

あなたが見つけたコードは、UriObserver にラップされた ContentObserver です。

それはいくつかのことをします

  • 彼はコンテンツ提供の 1 つにカーソルを取得します (彼の場合、それは MediaStore からの画像だと思います)。

  • 彼はこれのためにオブザーバーを登録します

  • 何らかの変更が発生するとすぐに、この変更を外部リスナーに転送します

ただし、このソリューションには 2 つの制限があります。

  • データに何が起こったのかを報告しない ContentObserver の問題を継承しています。

  • この MediaStore コンテンツ プロバイダに登録されているファイルへの変更のみが報告されると思います。システムは、SD カードの特別なディレクトリのみをスキャンして、画像などをチェックしていると思います。したがって、ファイルが別のディレクトリに配置される場合、このソリューションはそれを認識しません。

それで、彼のコードについてのあなたの質問は何でしたか?

概要

その場合、scdard 上のすべてのファイルの正確な変更の種類を知りたい場合、FileObserver よりも優れたものを見つけることができるとは思いません

更新 1

あなたには適さないかもしれないアイデアをさらにいくつか組み合わせてください。デバイスをルート化できる場合は、ファイルシステム用のフィルター ドライバーを作成するオプションがあるため、何かが変更されるたびにドライバーが呼び出されます。

このリンクを見ることができます: http://www.gossamer-threads.com/lists/linux/kernel/355190

または、既存の Linux 変更通知システムを再利用することもできます。例として、 http ://stefan.buettcher.org/cs/fschange/ を見てください。ただし、FileObserver がまさにそれに基づいている可能性があります。

とにかく、これらのアプローチはどちらも低レベルであり、理解するにはさらに時間がかかります。

于 2013-04-12T16:48:18.977 に答える
1

DATE_ADDED および DATE_MODIFIED 列に対してクエリを実行することで、最新の追加/変更を取得できますが、 DELETIONS は取得できません

これが私がそれを行う方法です:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
long lastDatabaseUpdateTime = preferences.getLong("lastDatabaseUpdateTime", 0);
long newDatabaseUpdateTime = (new Date()).getTime();

String[] cols = new String[] {MediaStore.Audio.Media._ID /* and other columns */};

String where = "("+MediaStore.MediaColumns.DATE_ADDED + ">" + (lastDatabaseUpdateTime/1000);
where += " or " + MediaStore.MediaColumns.DATE_MODIFIED + ">" + (lastDatabaseUpdateTime/1000);
where += ") and "+MediaStore.Audio.AudioColumns.IS_MUSIC+"==1 ";

Cursor cursor = MusicUtils.query(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, cols, where, null, null);

/* Do my work on the cursor and close the cursor */

//If no exceptions, then save the new timestamp
SharedPreferences.Editor editor = preferences.edit();
editor.putLong("lastDatabaseUpdateTime", newDatabaseUpdateTime);
editor.commit();
于 2015-10-13T20:33:49.927 に答える