2

Я пытаюсь обнаружить снимок экрана в приложении для Android. Я использую contentObserver, чтобы обнаружить изменения в каталоге СМИ, не используя FileObserver из known issue с ней на Android M.Android | contentObserver | Content URI не содержит идентификатор ресурса

Вот фрагмент кода:

handlerThread = new HandlerThread("content_observer"); 
    handlerThread.start(); 
    final Handler handler = new Handler(handlerThread.getLooper()) { 
     @Override 
     public void handleMessage(Message msg) { 
      super.handleMessage(msg); 
     } 
    }; 

    getContentResolver().registerContentObserver(
      MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
      true, 
      new ContentObserver(handler) { 
       @Override 
       public void onChange(boolean selfChange, Uri uri) { 
        Log.d(TAG, "URL : " + uri.toString()); 

        //Code to query using content resolver 
        if (uri.toString().matches(MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString())) { 

         Cursor cursor = null; 
         try { 
          cursor = getContentResolver().query(uri, new String[] { 
            MediaStore.Images.Media.DISPLAY_NAME, 
            MediaStore.Images.Media.DATA 
          }, null, null, null); 
          if (cursor != null && cursor.moveToFirst()) {   
          //Logic to filter if it is a screenshot file 
          } 
         } finally { 
          if (cursor != null) { 
           cursor.close(); 
          } 
         } 
        } 
        super.onChange(selfChange, uri); 
       } 
      } 
    ); 

Когда OnChange вызывается (после того, как скриншот/любые другие изменения в папке с носителями) URI является «content: // media/external/images/media», а не весь URI, содержащий идентификатор ресурса, например: content: // media/внешний/images/media/12345, это случается для большинства устройств, которые я пробовал - Moto G3 (Androi d 6.0.1), Nexus 5 (Android 6.0), где as, я получаю весь URI (включая ID) на Samsung S5, работающий 6.0.1.

Это известная проблема?

Как я могу получить идентификатор?

Это не оптимизированное решение для итерации по всему медиа-каталогу и поиск, если был сделан снимок экрана, когда приложение было активным, а получение идентификатора ресурса в URI содержимого решит проблему, поскольку мы можем напрямую извлечь файл путь и определить, является ли это файлом скриншота, наблюдатель все еще наблюдает за изменениями медиаконтента, хотя (например, он также наблюдает за загрузкой изображений WhatsApp в фоновом режиме).

ответ

2

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

Это является источником MediaProvider#insert() метода для Android 5.1.1 (взято из here):

@Override 
public Uri insert(Uri uri, ContentValues initialValues) { 
    int match = URI_MATCHER.match(uri); 

    ArrayList<Long> notifyRowIds = new ArrayList<Long>(); 
    Uri newUri = insertInternal(uri, match, initialValues, notifyRowIds); 
    notifyMtp(notifyRowIds); 

    // do not signal notification for MTP objects. 
    // we will signal instead after file transfer is successful. 
    if (newUri != null && match != MTP_OBJECTS) { 
     getContext().getContentResolver().notifyChange(uri, null); 
    } 
    return newUri; 
} 

Примечания этой строки: getContext().getContentResolver().notifyChange(uri, null).

Вышеуказанное означает, что при вставке в MediaProvider, уведомления будут отправлены для Uri, указанных для вставки, которая всегда является «справочником» Uri. Вероятно, это ошибка: если вместо uri они будут использовать newUri - она ​​будет работать точно так, как вы ожидали, что она сработает.

Если это работает на Samsung с Marshmallow, то либо это было исправлено в Android 6+, либо Samsung исправил его в своей конструкции AOSP. Но я не думаю, что вы действительно можете рассчитывать на это, чтобы работать надёжно.

Смежные вопросы