MediaStore не возвращает результаты при запросе общедоступной папки загрузки (Android Q)

Я пытаюсь загрузить файл (apk) в папку "Загрузить" в корне SD-карты в проекте Android, ориентированном на Android Q (API 29) с помощью Xamarin.

Сначала я загружаю файл в личное хранилище приложения, расположенное по адресу sdcard/Android/data/com.my.app/files.

Затем я использую MediaStore API, чтобы скопировать файл в общую папку "Download". Это мой код:

private void SaveTest(string appPath, string fileName)
    {
        var contentValues = new ContentValues();
        contentValues.Put(MediaStore.MediaColumns.DisplayName, fileName);
        contentValues.Put(MediaStore.MediaColumns.MimeType, "application/vnd.android.package-archive");
        contentValues.Put(MediaStore.MediaColumns.RelativePath, Android.OS.Environment.DirectoryDownloads);

        var context = (Context)this;
        var resolver = context.ContentResolver;

        Stream stream = null;
        Android.Net.Uri uri = null;

        try
        {
            var contentUri = MediaStore.Downloads.ExternalContentUri;

            var cursor = resolver.Query(
                contentUri,
                new[] { MediaStore.MediaColumns.Id, MediaStore.MediaColumns.DisplayName, MediaStore.MediaColumns.MimeType, MediaStore.MediaColumns.RelativePath },
                $"{MediaStore.MediaColumns.DisplayName} = ? AND {MediaStore.MediaColumns.MimeType} = ? AND {MediaStore.MediaColumns.RelativePath} = ?",
                new[] { fileName, "application/vnd.android.package-archive", Android.OS.Environment.DirectoryDownloads },
                null
                );
            if(cursor != null && cursor.Count >= 1)
            {
                cursor.MoveToFirst();

                var id = cursor.GetLong(cursor.GetColumnIndexOrThrow(MediaStore.MediaColumns.Id));
                var displayName = cursor.GetString(cursor.GetColumnIndexOrThrow(MediaStore.MediaColumns.DisplayName));
                var relativePath = cursor.GetString(cursor.GetColumnIndexOrThrow(MediaStore.MediaColumns.MimeType));
                var lastModifiedDate = cursor.GetString(cursor.GetColumnIndexOrThrow(MediaStore.MediaColumns.RelativePath));

                uri = ContentUris.WithAppendedId(contentUri, id);
            }
            else
            {
                uri = resolver.Insert(contentUri, contentValues);
            }
            cursor?.Close();

            if (uri == null)
            {
                throw new Exception("Retrieving of creating MediaStore record failed.");
            }

            byte[] buffer = new byte[1024];
            stream = resolver.OpenOutputStream(uri);

            var fullPathAndFileName = Path.Combine(appPath, fileName);
            using (var inputstream = new FileStream(fullPathAndFileName, FileMode.Open))
            {
                CopyFile(inputstream, stream);
            }

        }
        catch
        {
            if (uri != null)
            {
                // Don't leave an orphan entry in the MediaStore
                resolver.Delete(uri, null, null);
            }

            throw;
        }
        finally
        {
            stream?.Close();
        }
    }

Вставка в MediaStore работает в первый раз, но когда я пытаюсь вставить второй раз, возвращаемый Uri равен нулю. Поэтому я добавил запрос ContentResolver, чтобы я мог обнаруживать существующие записи, но этот запрос не возвращает результатов. Он снова работает только тогда, когда я использую другое имя файла.

Когда я смотрю журнал устройства, я вижу следующую ошибку:

Имя устройства времени Тип PID Tag Сообщение 05-14 14:14:27.442 Ошибка 14571 SQLiteDatabase android.database.sqlite.SQLiteConstraintException: ошибка ограничения UNIQUE: files._data (код 2067 SQLITE_CONSTRAINT_UNIQUE) в android.database.sqlite.SQLiteConnection.nativeExecutetedF Method) в android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:879) в android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:790) в android.databaseInserted.sqliteStateStation.exe:88) в android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1599) в android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1468) в com.android.providers.media.MediaProvider.insertFile(MediaProvider.java:2776) на com.android.providers.media.MediaProvider.insertInternal(MediaProvider.java:3317) на com.android.providers.media.MediaProvider.insert(MediaProvider.java:2966) на android.content.ContentProvider$Transport.insert(ContentProvider.java:309) на android.content.ContentProviderNative.onTransact(ContentProviderNative.java:154) на android.os.Binder.execTransactInternal(Binder.java:1021) на android.os.Binder.execTransact(Binder.java:994) 05-14 14:14:27.442 Ошибка 14571 SQLiteDatabase Ошибка при вставке bucket_display_name= Загрузить имя_пакета владельца =com.my.app parent=8 имя_тома =external_primary date_modified=1589458467 _display_name=XXX.apk mime_type=application/vip.android.package-archive _data=/storage/emulated/0/Download/XXX.apk title=XXX.apk group_id=102105 is_download=true date_added=1589458467 primary_directory= Загрузить bucket_id=540528482 media_type=0 relative_path= Загрузить /

Даже при выполнении запроса к медиа-хранилищу без каких-либо фильтров счетчик результатов равен 0. Как я могу получить правильный Uri?

0 ответов

Другие вопросы по тегам