Растровое изображение из файла изображения всегда является пустой строкой

#android #android-bitmap #android-11

#Android #android-растровое изображение #android-11

Вопрос:

Попробовав приведенные ниже способы преобразования изображения в растровое изображение за последние 3 дня, я начал сомневаться, что проблема не в моем коде. Это что-то другое, и мы перешли к примеру кода, предоставленного самим Google.

 BitmapFactory.decodeStream
BitmapFactory.decodeFile
BitmapFactory.decodeFileDescriptor

ImageDecoder.Source source = ImageDecoder.createSource(getContentResolver(), uri);
bitmap = ImageDecoder.decodeBitmap(source);
 

https://github.com/android/storage-samples/tree/main/ActionOpenDocument
https://developer.android.com/training/data-storage/shared/documents-files

Я загрузил этот образец в ACTION_OPEN_DOCUMENT, настроил, изменил тип PDF на файлы типа images для тестирования на моем мобильном Android 11, и я столкнулся с той же проблемой. Итак, я думаю, что есть что-то новое, что я пропустил, чтобы найти через Интернет.

Сценарий, используйте щелчки по кнопке для просмотра изображения. Событие будет программно запускать намерение.ACTION_OPEN_DOCUMENT.

 Intent fileBrowserIntent = null;
fileBrowserIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
fileBrowserIntent.setType("image/*");
fileBrowserIntent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(fileBrowserIntent, ActivityResultCode.IMAGE_TO_CONFIGURE);
 

После выбора файла в onActivityResult URI файла обрабатывается приведенным ниже кодом, а строка 138 всегда пуста. Я пробовал перегруженные методы, передавая BitmapFactory.Параметры также.

введите описание изображения здесь

** Чтобы подтвердить, что проблема не связана с обновлениями хранилища в Android 11, я поместил выбранное изображение в область видимости, а затем перенес его на свой ноутбук с помощью проводника файлов устройства. Сохраненные изображения являются правильными, поэтому, насколько я проверял, проблем, связанных с доступом, нет.

Есть мысли?

Полный код:

const val DOCUMENT_FRAGMENT_TAG = «com.example.android.actionopendocument.tags.DOCUMENT_FRAGMENT»

 /**
 * Simple activity to host [ActionOpenDocumentFragment].
 */
class MainActivity : AppCompatActivity() {

    private lateinit var noDocumentView: ViewGroup

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main_real)

        noDocumentView = findViewById(R.id.no_document_view)
        findViewById<Button>(R.id.open_file).setOnClickListener {
            openDocumentPicker()
        }

        getSharedPreferences(TAG, Context.MODE_PRIVATE).let { sharedPreferences ->
            if (sharedPreferences.contains(LAST_OPENED_URI_KEY)) {
                val documentUri =
                    sharedPreferences.getString(LAST_OPENED_URI_KEY, null)?.toUri()
                        ?: return@let
                openDocument(documentUri)
            }
        }
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.main, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.action_info -> {
                AlertDialog.Builder(this)
                    .setMessage(R.string.intro_message)
                    .setPositiveButton(android.R.string.ok, null)
                    .show()
                return true
            }
            R.id.action_open -> {
                openDocumentPicker()
                return true
            }
            else -> super.onOptionsItemSelected(item)
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
        super.onActivityResult(requestCode, resultCode, resultData)

        if (requestCode == OPEN_DOCUMENT_REQUEST_CODE amp;amp; resultCode == Activity.RESULT_OK) {
            resultData?.data?.also { documentUri ->

                /**
                 * Upon getting a document uri returned, we can use
                 * [ContentResolver.takePersistableUriPermission] in order to persist the
                 * permission across restarts.
                 *
                 * This may not be necessary for your app. If the permission is not
                 * persisted, access to the uri is granted until the receiving Activity is
                 * finished. You can extend the lifetime of the permission grant by passing
                 * it along to another Android component. This is done by including the uri
                 * in the data field or the ClipData object of the Intent used to launch that
                 * component. Additionally, you need to add FLAG_GRANT_READ_URI_PERMISSION
                 * and/or FLAG_GRANT_WRITE_URI_PERMISSION to the Intent.
                 *
                 * This app takes the persistable URI permission grant to demonstrate how, and
                 * to allow us to reopen the last opened document when the app starts.
                 */
                contentResolver.takePersistableUriPermission(
                    documentUri,
                    Intent.FLAG_GRANT_READ_URI_PERMISSION
                )
                openDocument(documentUri)
            }
        }
    }

    private fun openDocumentPicker() {
        val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
            /**
             * It's possible to limit the types of files by mime-type. Since this
             * app displays pages from a PDF file, we'll specify `application/pdf`
             * in `type`.
             * See [Intent.setType] for more details.
             */
            type = "image/*"

            /**
             * Because we'll want to use [ContentResolver.openFileDescriptor] to read
             * the data of whatever file is picked, we set [Intent.CATEGORY_OPENABLE]
             * to ensure this will succeed.
             */
            addCategory(Intent.CATEGORY_OPENABLE)
        }
        startActivityForResult(intent, OPEN_DOCUMENT_REQUEST_CODE)
    }

    private fun openDocument(documentUri: Uri) {
        /**
         * Save the document to [SharedPreferences]. We're able to do this, and use the
         * uri saved indefinitely, because we called [ContentResolver.takePersistableUriPermission]
         * up in [onActivityResult].
         */
        getSharedPreferences(TAG, Context.MODE_PRIVATE).edit {
            putString(LAST_OPENED_URI_KEY, documentUri.toString())
        }

        val parcelFileDescriptor: ParcelFileDescriptor? =
            contentResolver.openFileDescriptor(documentUri, "r")
        val fileDescriptor: FileDescriptor? = parcelFileDescriptor?.fileDescriptor
        val image: Bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor)
        parcelFileDescriptor?.close()


        //val fragment = ActionOpenDocumentFragment.newInstance(documentUri)
        // Document is open, so get rid of the call to action view.
       // noDocumentView.visibility = View.GONE
    }
}

private const val OPEN_DOCUMENT_REQUEST_CODE = 0x33
private const val TAG = "MainActivity"
private const val LAST_OPENED_URI_KEY =
    "com.example.android.actionopendocument.pref.LAST_OPENED_URI_KEY"
 

Комментарии:

1. Пожалуйста, отправьте весь код в виде текста. Удалите это изображение.

2. After trying out below ways to convert image into Bitmap Я думаю, что у вас нет изображения, но позвольте пользователю выбрать файл изображения. Пожалуйста, опубликуйте свой код onActivityResult, в котором вы пытаетесь создать растровое изображение из полученного uri.

3. Пример кода github для Android также терпит неудачу в той же ситуации. github.com/android/storage-samples/tree/main/ActionOpenDocument

4. Изображение фрагмента кода OpenDocument() вызывается в onActivityResult(). Uri uri = intentData.getData();

5. «и строка 138 всегда пуста» — что означает «пустой»? «Растровое изображение из файла изображения всегда является пустой строкой» — растровые изображения не являются строками. Что означает «пустая строка»? Вы ничего не делаете со своей image переменной.

Ответ №1:

После того, как CommonsWare указал, что я попробовал, сначала я взял bitmap как ByteArrayOutputStream и преобразовал в base64 и подтвердил, что bitmap не был пустым.

 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
qrImage.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
 

Затем, чтобы получить еще одно подтверждение, я использовал

 AppCompatImageView.setImageBitmap (Bitmap bm)
 

и проверил, что изображение действительно содержало правильное содержимое при визуализации.

Это было встроенное значение, которое заставило меня усомниться в моем коде. Надеюсь, это поможет избежать потери времени другим разработчиком. Вся проблема заключалась в том, что Android Studio перепутала встроенное значение отладки. Встроенные значения в режиме отладки Android Studio