Наблюдение за изменениями в обозревателе контента Android для Audio.Media.EXTERNAL_CONTENT_URI

Я разрабатываю приложение для 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");

Это дало мне знать, что в SD-карте произошли некоторые изменения, связанные с аудиофайлами. Но он не дает никакой информации о том, какой файл был добавлен, отредактирован или удален.

Затем я искал решение и получил этот пост

Android: как обнаружить изменение в MediaStore при подключении через MTP

В этом посте Bhiefer дает некоторый код в качестве ответа, который, я думаю, может сработать, поэтому я попытался реализовать его, но не смог.

Что я могу сделать для этого?

Обновлять

Могу ли я запросить Audio.Media.EXTERNAL_CONTENT_URI о последних изменениях? Этот код:

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

mCursor.moveToLast();

не дает последние изменения. Есть ли другой способ получить последние изменения?


person Nikhil Agrawal    schedule 09.04.2013    source источник
comment
Привет, я столкнулся с такой же проблемой, вы нашли какое-либо решение?   -  person Nand    schedule 04.02.2014
comment
Привет, @Nikhi Agrawal, ты смог найти решение с точки зрения довольного наблюдателя. Поскольку File Observer, даже сделанный рекурсивным, не работает на последних устройствах.   -  person MRamzan    schedule 10.08.2020


Ответы (2)


Позвольте мне попытаться расслабиться

Обозреватель контента

Это не дает вам информацию о том, что изменилось

Это по дизайну. Ничто в документации не говорит, что это даст вам эту информацию.

Обозреватель файлов

это не рекурсивно

Да. Это известная проблема. В чем проблема с перебором всех каталогов и установкой наблюдателей? Насколько я понимаю, по умолчанию их не должно быть много (скажем, дюжина или около того).

Android: как обнаружить изменение в MediaStore при подключении через MTP

Код, который вы нашли, это просто ContentObserver, завернутый в UriObserver.

Он делает несколько вещей

  • Он получает курсор для одного из материалов (в его случае я полагаю, что это изображения из MediaStore)

  • Он регистрирует наблюдателя для этого

  • Как только происходят некоторые изменения, он пересылает эти изменения внешнему слушателю.

Однако это решение имеет два ограничения:

  • Он унаследовал проблему ContentObserver, заключающуюся в том, что он не сообщает о том, что произошло с данными.

  • Я полагаю, что он будет сообщать только об изменениях в файлах, которые зарегистрированы в этом поставщике содержимого MediaStore. Я считаю, что система сканирует только специальные каталоги на SD-карте, чтобы проверить наличие изображений и так далее. Таким образом, если файл будет находиться в каком-то другом каталоге, это решение его не увидит.

Итак, какой у вас был вопрос о его коде?

Сводка

В случае, если вы хотите знать точный тип изменений для ВСЕХ файлов на scdard, я не думаю, что вы можете найти что-то лучше, чем FileObserver

Обновление 1

Еще пара идей, которые могут вам не подойти. Если вы можете рутировать устройство, у вас есть возможность написать драйвер фильтра для файловой системы, поэтому ваш драйвер будет вызываться каждый раз, когда что-то изменилось.

Вы можете взглянуть на эту ссылку: http://www.gossamer-threads.com/lists/linux/kernel/355190

Или вы можете повторно использовать некоторые существующие системы уведомлений об изменениях Linux. Например, посмотрите на это: http://stefan.buettcher.org/cs/fschange/. Однако вполне возможно, что FileObserver основан именно на нем.

В любом случае, оба эти подхода являются низкоуровневыми и потребуют больше времени, чтобы разобраться.

person Victor Ronin    schedule 12.04.2013
comment
Но мне нужно реализовать File Observers во всех каталогах. Это будет долгий процесс. - person Nikhil Agrawal; 13.04.2013
comment
@Nikhil: это зависит от количества каталогов. Если бы их были сотни, то это заняло бы много времени. Однако для Android Sd-карты обычно не так много папок. КСТАТИ. Вы пытались это сделать? Это замедляет работу устройства? - person Victor Ronin; 13.04.2013
comment
Да, это то, что у меня есть более 1500 папок на моей SD-карте на 16 ГБ. И это потребляет больше ресурсов и замедляет работу моего устройства. Вот почему я пробую этот вариант - person Nikhil Agrawal; 13.04.2013
comment
Я награждаю вас этой репутацией +50, потому что после публикации на стольких порталах разработчиков вы только вывели меня на следующий уровень для моего вопроса. Но он еще не завершен. Поэтому, если вы столкнетесь с какой-либо другой информацией, связанной с этим вопросом, обновите свой ответ. Другие, кто нашел этот пост полезным для себя, если вы, люди, столкнетесь с какой-либо другой информацией, связанной с этим вопросом, опубликуйте свои ответы в этом посте. Спасибо Виктор Ронин всегда на связи. Спасибо stackoverflow, нашим добрым и гениальным модераторам и всем умным и опытным членам этого сообщества. - person Nikhil Agrawal; 19.04.2013

Вы можете получить последние добавления/изменения, запросив столбцы DATE_ADDED и DATE_MODIFIED, но вы НЕ получите УДАЛЕНИЯ.

Вот как я это делаю:

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();
person Henry    schedule 13.10.2015