Как получать уведомления о каждом новом изображении, отображаемом в приложении галереи?

Задний план

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

Мне нужно получать уведомления о каждом новом изображении, как только оно было создано, независимо от того, как оно было создано (камера, браузер,...), как показывает приложение галереи.

Эта проблема

Как выяснилось, есть компонент Android mediaScanner, который отвечает за сканирование всех типов медиафайлов, и когда он завершится, он должен отправить намерение "MEDIA_SCANNER_FINISHED" (как показано на этот пример).

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

манифест:

    ...
    <receiver android:name="com.example.newgalleryimagereceivertest.MediaScannerBroadcastReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.MEDIA_SCANNER_FINISHED" />
            <data android:scheme="file" />
        </intent-filter>
    </receiver>
    ...

Java-файл:

package com.example.newgalleryimagereceivertest;
...
public class MediaScannerBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(final Context context, final Intent intent) {
        android.util.Log.d("AppLog", "gallery has new images");
    }

Почему-то этот код не работает...

Вопрос

Что не так с кодом?

Будет ли когда-нибудь вызываться BroadcastReceiver после съемки фотографии?

Как правильно это сделать?

Мне действительно нужно использовать contentObserver и отслеживать его изменения (используя что-то вроде этого ) и оставить приложение работать только для этого? очень надеюсь что нет...


person android developer    schedule 23.01.2014    source источник
comment
Я знаю, что у Toast есть некоторые ограничения для работы. Поток пользовательского интерфейса и контекст действия. Итак, прежде чем сказать, что код не работает. Не могли бы вы вместо этого сделать журнал и перепроверить Log.d("toast", "gallery have new images");   -  person Budius    schedule 23.01.2014
comment
да, использование журналов также показало, что это не работает. теперь обновит код и здесь. также нашел странную вещь в манифесте, которую я исправил.   -  person android developer    schedule 23.01.2014
comment
Это всего лишь предположение, возможно, вместо этого вызывается "android.hardware.action.NEW_PICTURE" или "com.android.camera.NEW_PICTURE"   -  person a.ch.    schedule 28.01.2014
comment
@а.ч. это будет вызываться только родным приложением камеры и только из определенного API. Я хочу получать уведомления о любом изображении, которое может отображаться в галерее, и не ограничиваться конкретным приложением. сторонние камеры не используют это намерение, когда делается новый снимок.   -  person android developer    schedule 28.01.2014
comment
Привет, у тебя есть решение? Я застрял на том же месте.   -  person Amol Sawant 96 Kuli    schedule 15.03.2014
comment
@AmolSawant96Kuli Я нашел 2 возможных решения, каждое из которых имеет свои недостатки: contentObserver, который потребует постоянного прослушивания, и механизм опроса, который будет проверять наличие нового контента каждые X минут. все другие решения, которые я нашел, будут слишком сильно влиять на производительность и/или использование памяти, чтобы их можно было использовать.   -  person android developer    schedule 15.03.2014
comment
Спасибо за ответ, дорогой, я все еще нахожу решение. Если вы получите какое-либо решение, дайте мне знать.   -  person Amol Sawant 96 Kuli    schedule 15.03.2014
comment
@ AmolSawant96Kuli Я перестал искать, но если найду об этом, напишу ответ здесь.   -  person android developer    schedule 15.03.2014
comment
@ AmolSawant96Kuli, вы нашли какое-нибудь решение для того же самого? Я застрял в аналогичной проблеме stackoverflow.com/q/45813687/4732786   -  person Adarsh Sharma    schedule 22.08.2017
comment
@AdarshSharma Я перестал заниматься этой проблемой. Возможно, вам поможет один из приведенных ниже ответов.   -  person android developer    schedule 23.08.2017


Ответы (3)


Для добавления новые каталоги в галерее:

Широковещательное действие: Сканер мультимедиа завершил сканирование каталога. Путь к сканируемому каталогу содержится в поле Intent.mData.

Постоянное значение: "android.intent.action.MEDIA_SCANNER_FINISHED"

Вы должны использовать ACTION_MEDIA_SCANNER_SCAN_FILE, который используется для добавления новых файлов, а не только каталогов:

Широковещательное действие: Запросите сканер мультимедиа для сканирования файла и добавления его в базу данных мультимедиа. Путь к файлу содержится в поле Intent.mData.

Постоянное значение: "android.intent.action.MEDIA_SCANNER_SCAN_FILE"

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

Кроме того, некоторые, как сообщается, необходимо было указать MIME-тип и расширения файлов, например:

<data android:mimeType="*/*"/>
<data android:pathPattern=".*\\.png" />
person Phil    schedule 29.01.2014
comment
к сожалению, я все еще ничего не получаю. это сработало для вас? Вы запустили свое приложение, и когда вы сделали снимок с помощью камеры, вы получили намерение? - person android developer; 29.01.2014
comment
@androiddeveloper Я добавил в ответ дополнительные сведения о типах пантомимы и расширениях файлов. Это помогает? - person Phil; 29.01.2014
comment
еще ничего. я также пробовал android:pathPattern=.*\\.jpg и android:pathPattern=.*\\.jpeg . интересно, это регулярное выражение или просто подстановочные знаки. - person android developer; 30.01.2014
comment
Я не думаю, что эти два варианта так же аналогичны, как указано в ответе. Как указано в документах, _SCAN_FILE должен запросить сканирование, а _SCANNER_FINISHED должен уведомить о том, что сканирование мультимедиа завершено. Трансляция _SCANNER_FINISHED уведомляет вас о наличии новых данных, но тогда вам нужно будет запросить хранилище мультимедиа, чтобы найти новые данные, насколько мне известно. - person parkerfath; 14.03.2015

Вы также можете добавить их в свой фильтр:

com.android.camera.NEW_PICTURE
com.android.camera.NEW_VIDEO
android.hardware.action.NEW_PICTURE
android.hardware.action.NEW_VIDEO

Действия android.hardware.x являются «официальными» текущими трансляциями, но действия com.android.x отправляются устройствами Samsung и более старыми версиями Android.

person parkerfath    schedule 13.03.2015
comment
Вопрос слишком старый, поэтому он мне больше не нужен. Однако это интересно. Что происходит с устройствами других OEM-производителей? Хорошо ли они работают? - person android developer; 14.03.2015
comment
@androiddeveloper, как вы решаете свою проблему? Вы можете рассказать нам о своем методе? - person HendraWD; 03.03.2016
comment
@HendraWijayaDjiono Я не решил это, потому что у меня его больше нет. - person android developer; 03.03.2016

я думаю, вы можете добиться этого, используя FileObserver.

как указано в документации:

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

но вы должны иметь в виду:

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

Пожалуйста, дайте мне обратную связь. Надеюсь, это поможет .

person Community    schedule 30.01.2014
comment
откуда мне знать, какие файлы слушать? мониторить надо только файлы которые хранятся для mediaStore... пробовали? как вы контролируете конкретный процесс, и какой он должен быть для mediaStore? как бы вы заставили fileObserver наблюдать за всеми файлами из всех каталогов, а не за одним (он не кажется рекурсивным)? вам нужно будет создать экземпляр для каждой папки на устройстве, а также для каждой новой... - person android developer; 30.01.2014
comment
например: вы можете прослушивать свой каталог изображений следующим образом: Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); и так далее для ваших каталогов. и нет я не пробовал. вы не хотите отслеживать, какой процесс создал файл, вы будете отслеживать любой файл, созданный любым процессом на устройстве. - person ; 30.01.2014
comment
но я не хочу отслеживать каждый созданный файл, так как некоторые из них не попадут в mediaStore (и, возможно, большинство из них). я также не хочу отслеживать только эту единственную папку, которую вы написали, поскольку пользователи могут устанавливать приложения, которые помещают файлы изображений (например, сторонние камеры) в другую папку, которые по-прежнему сообщают приложению галереи об этих файлах... - person android developer; 30.01.2014
comment
например, вы не можете контролировать SD-карту? я не знаю, правильно ли то, что я говорю, или нет. - person ; 30.01.2014
comment
я прочитал об этом сейчас. рекурсивно вроде как не умеет работать - пришлось бы самому создавать много FileObservers - по одному на каждую директорию, да еще и на новые... для каждого файла надо было бы проверять не попал ли он в mediaStore ... я думаю, что это может быть излишеством ... - person android developer; 30.01.2014
comment
давайте продолжим это обсуждение в чате - person ; 30.01.2014
comment
извините, у меня нет времени болтать. этот вопрос написан, пока я работаю в офисе... - person android developer; 30.01.2014
comment
Я думаю, что проблема с этим подходом заключается в том, что вам нужно, чтобы ваше приложение работало постоянно. Одним из преимуществ широковещательной рассылки является то, что при необходимости она разбудит ваше приложение. - person parkerfath; 14.03.2015
comment
если вам нужно отслеживать подкаталоги, вы можете использовать этот класс RecursiveFileObserver collimator.googlecode.com/svn-history/r22/trunk/src/com/ - person HendraWD; 03.03.2016
comment
@parkerfath действительно, но может жить и в фоновом режиме с обслуживанием. Я могу добиться этого, создав фоновую службу для хранения ссылки на FileObserver, поэтому FileObserver не будет собирать мусор. И в фоновой службе я использую флаг START_STICKY в StartCommand, поэтому он будет воссоздан, если будет убит системой Android, например, когда устройство имеет нехватку памяти. - person HendraWD; 03.03.2016