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, който все още работи за моята програма (като например да прочетете списъка с файлове на 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, за да получа Bitmap чрез 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 null след извикване на MediaStore.Images.Media.GetBitmap.

Предполагам, че съм напълно погрешен в подхода си, но прекарах няколко дни в опити и гугъл без никакъв резултат.

Всяка помощ за това как да получите растерно изображение от снимки, направени от приложение на трета страна в Pictures/xxx, ще бъде наистина оценено.

Благодаря ви предварително, наздраве


person MaxM83    schedule 28.01.2021    source източник
comment
Вашият код за получаване на URI не може да работи. Използвате insert(), за да получите uri. След това използвате този URI, за да получите растерно изображение и след това компресирате това растерно изображение отново до същия URI. Тази последователност няма смисъл. А преди това получихте нула вместо растерно изображение.   -  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
Ако искате да използвате MediaStore, трябва да потърсите в MediaStore снимки с RELATIVE_PATH Pictures/Office Lens. Ще получите курсор/списък с ids/uries за всички файлове с изображения.   -  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, за да извлече пътя за Images/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