GetExternalStoragePublicDirectory Проблема обновления Android 10+: попытка получить растровое изображение, созданное из внешнего приложения (OfficeLens), в мое приложение

Я новичок в мире Android, и у меня возникают проблемы с приложением, написанным в среде Xamarin Android Mono.

Мне нужно обновить Android Target API как минимум до 29 (лучше до 30), и я застрял на изменении объема хранилища. Хотя я смог управлять своими собственными снимками, сделанными камерой (представляя FileProvider), у меня все еще есть проблема с внешними изображениями, сделанными приложением Microsoft Office Lens (хранящимся в общей папке Pictures/Office Lens).

Подводя итог, я использую для вызова OfficeLens намерение из моего приложения:

StartActivity(Android.App.Application.Context.PackageManager.GetLaunchIntentForPackage("com.microsoft.office.officelens"))

проверка новых файлов с помощью устаревшего GetExternalStoragePublicDirectory, который все еще работает для моего porpouse (например, чтение списка файлов Office Lens, чтобы найти новые):

var TmpDir = new File(Environment.GetExternalStoragePublicDirectory(Environment.DirectoryPictures), "Office Lens");

Прочитайте NewFiles, сохранив пути в список:

var LstFilesNew = new List<string>();
... 
foreach (var I in TmpDir.ListFiles())
{
  if (I.IsFile == true)
  {
    LstFilesNew.Add(I.Path);
  }
 }

Раньше просто вызывали эту функцию, передавая FilePath для получения BitMap:

public static Bitmap LoadBitmap(this string fileName)
{
  var options = new BitmapFactory.Options();

  options.InJustDecodeBounds = false;

  return BitmapFactory.DecodeFile(fileName, options);
}

С хранилищем с областью действия я пытаюсь получить URI из URI, чтобы получить растровое изображение через MediaStore:

    foreach (var FileNew in LstFilesNew)
    {
      if (Build.VERSION.SdkInt >= BuildVersionCodes.Q)
        {
          ContentValues contentValues = new ContentValues();
          contentValues.Put(MediaStore.MediaColumns.DisplayName, FileNew);
          contentValues.Put(MediaStore.MediaColumns.MimeType, "image/jpg");
          contentValues.Put(MediaStore.MediaColumns.RelativePath, Environment.DirectoryPictures);
          Uri imageUri = Application.Context.ContentResolver.Insert(MediaStore.Images.Media.ExternalContentUri, contentValues);

          fos = Application.Context.ContentResolver.OpenOutputStream(imageUri); 
          Android.Graphics.Bitmap finalBitmap = MediaStore.Images.Media.GetBitmap(Application.Context.ContentResolver, imageUri);
          finalBitmap.Compress(Android.Graphics.Bitmap.CompressFormat.Jpeg, 100, fos);
          fos.Close();
        }
    }
  

Мой URI кажется в порядке (content://media/external/images/media/1563), но я получаю нулевое значение finalBitmap после вызова MediaStore.Images.Media.GetBitmap.

Думаю, я совершенно ошибаюсь в своем подходе, но я потратил несколько дней на попытки поиска в Google без каких-либо результатов.

Любая помощь в том, как получить растровое изображение из изображений, сделанных сторонним приложением в Pictures/xxx, будет очень признательна.

Заранее спасибо, здравствуйте


person MaxM83    schedule 28.01.2021    source источник
comment
Ваш код для получения uri не может работать. Вы используете insert() для получения uri. Затем вы используете этот uri для получения растрового изображения, а затем снова сжимаете это растровое изображение до того же uri. Эта последовательность не имеет смысла. А до этого у вас вместо растрового изображения было null.   -  person blackapps    schedule 28.01.2021
comment
Whether before simply used to call this function passing the FilePath to get the BitMap Хорошо. А если вы используете его на устройстве Android 11? Тогда это работает? Вы не сказали нам. А на устройстве Android 10? Я думаю, что если вы можете перечислить эти файлы, вы также можете их загрузить. Но может и нет...   -  person blackapps    schedule 28.01.2021
comment
public static Bitmap LoadBitmap(this string fileName) Только имя файла не подойдет. public static Bitmap LoadBitmap(string path)   -  person blackapps    schedule 28.01.2021
comment
IЕсли вы хотите использовать MediaStore, вы должны запросить в MediaStore изображения с RELATIVE_PATH Pictures/Office Lens. Вы получите курсор/список с идентификаторами/идентификаторами для всех файлов изображений.   -  person blackapps    schedule 28.01.2021
comment
Привет @blackapps, большое спасибо за ваш ответ. Вернув свой код и проверив его еще раз, чтобы лучше описать исключения и ответить на ваши вопросы, я нашел, где я пошел неправильным путем. Когда я изменил реализацию для обработки изображений, захваченных с помощью намерения ActionImageCapture, переключившись с пути к файлу на URI для FileProvider, я хотел также управлять изображениями из OfficeLens через URI, которые мне не удалось получить.   -  person MaxM83    schedule 29.01.2021
comment
Когда я проверяю версию Android, FilePath работает, чтобы ответить на ваш вопрос, я обнаруживаю, что он все еще работает!   -  person MaxM83    schedule 29.01.2021


Ответы (1)


GetExternalStoragePublicDirectory все еще работает с таргетингом на Android 10 и Android 11, чтобы получить путь для изображений/xyz.

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

public static Bitmap LoadBitmap(this string filePath)
{
  var options = new BitmapFactory.Options();

  options.InJustDecodeBounds = false;

  return BitmapFactory.DecodeFile(fileName, options);
}

где filePath считываются из результата GetExternalStoragePublicDirectory методом ListFiles():

var TmpDir = new Java.IO.File(Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures), "xyz");

foreach (var I in TmpDir.ListFiles())
{
  if (I.IsFile == true)
  {
    var Bmp = LoadBitmap(I.Path);
  }
} 

Спасибо @blackapps за хиты!

person MaxM83    schedule 29.01.2021