Котлин: Как читать Uri в Android? - PullRequest
0 голосов
/ 01 июля 2019

Я застрял с этим почти неделю. Проиграйте почти любой ответ / учебник, который я нашел, но пока не повезло.

У меня есть приложение, которое использует камеру. После того, как пользователь сделает снимок и выберет кнопку проверки / OK в камере, камера возвращает, среди прочего, Uri, в котором было сохранено изображение. Он имеет вид: content://media/external/images/media/122 (это реальная картинка в телефоне), если я попрошу Uri.path, я получу в этом случае: /external/images/media/123

Теперь, с помощью объекта Uri, я могу назначить его для imageView как imageView.setImageURI(), и он работает, поэтому я вполне уверен, что изображения хранятся где-то .

Теперь, следующее, что должно сделать мое приложение - это сделать все снимки и отправить их в API.

Моя проблема в том, что когда я пытаюсь прочитать Uri любым методом, он дает мне FileNotFound Exception, независимо от того, использую ли я Uri или путь.

Так что я действительно не знаю, что делать. Что мне не хватает? Нужно ли явно сохранять изображение в рабочем каталоге? Если так, как это сделано? Если нет, как я могу получить полный путь, включая имя файла? Когда я смотрю на директорию DCIM в телефоне, я не вижу фото.

Заранее спасибо!

EDIT

Код для снимка:

    btnTomarFoto.setOnClickListener {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (checkSelfPermission(android.Manifest.permission.CAMERA) ==
          PackageManager.PERMISSION_DENIED || ContextCompat.checkSelfPermission(
            this,
            android.Manifest.permission.READ_EXTERNAL_STORAGE
          ) == PackageManager.PERMISSION_DENIED
        ) {
          // El permiso no fue concedido
          val permission = arrayOf(android.Manifest.permission.CAMERA,
                                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
          requestPermissions(permission, PERMISSION_CODE)
        } else {
          // El permiso ya estaba concedido
          openCamera()
        }
      } else {
        // El SO es menor que Marshmallow
      }
    }
  }

Код для открытия камеры:

  private fun openCamera() {
    val values = ContentValues()
    values.put(MediaStore.Images.Media.TITLE, "New Picture")
    values.put(MediaStore.Images.Media.DESCRIPTION, "From the camera")
    image_uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)

    val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri)
    startActivityForResult(cameraIntent, IMAGE_CAPTURE_CODE)
  }

Код для хранения Uri в базе данных:

  private fun guardarFoto() {
    var foto = FotografiaModel(actividad_id!!, image_uri.toString(), txtObservacion.text.toString())
    Log.w(tag, "URI: $image_uri PATH: " + image_uri!!.path + " Encoded Path: " + image_uri!!.encodedPath)
    fotografiaDBHelper.insertFoto(foto)
    visitaDBHelper.actualizaEstado(actividad_id!!, "INICIADO")
  }

Есть еще кое-что, что делает код, но это главное. Чтобы показать полученный Uri в режиме просмотра изображений, я использую:

  override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (resultCode == Activity.RESULT_OK) {
      imageView.setImageURI(image_uri)
      Log.v(tag, "Image URI: $image_uri")
    }
  }

1 Ответ

0 голосов
/ 01 июля 2019

Моя проблема в том, что когда я пытаюсь прочитать Uri любым методом, он выдает исключение FileNotFound, независимо от того, использую ли я Uri или путь.

То естьпотому что это не файл.Это Uri.

Например, /8695202/kotlin-kak-chitat-uri-v-android - это Uri.Ваш код предполагает, что путь /questions/56839478/kotlin-how-to-read-a-uri-in-android - единственное, что имеет значение в Uri.По вашему аргументу, каждый компьютер на планете (плюс те, которые находятся на орбите) имеют файл, расположенный по адресу /questions/56839478/kotlin-how-to-read-a-uri-in-android.Это не то, как работает Uri.Вам нужно использовать весь Uri, чтобы определить, как его использовать.В этом случае https как схема означает, что вы используете HTTPS в качестве протокола для связи с назначенным сервером (stackoverflow.com) для извлечения контента.

Аналогично, схема content в вашем Uri из insert() означает, что вы используете ContentResolver для работы с ним.В частности, вы можете использовать openInputStream(), чтобы получить InputStream для контента, обозначенного Uri, так же, как вы можете использовать HttpUrlConnection или OkHttp, чтобы получить InputStream для https Uri.

В частности, поскольку вы делегировали хранение данных в какое-то другое приложение (MediaStore), где хранится изображение, принадлежит кому-то другому, и оно не обязательно находится в файловой системе в месте, где вы можетедоступ к нему.Это особенно верно для Android Q и выше, где у вас ограниченный доступ к произвольным местоположениям на устройстве через API файловой системы.

Теперь, следующее, что должно сделать мое приложение, - это сделать все сделанные снимки,и отправить их в API.

Я собираюсь догадаться, что «отправить их в API» означает «загрузить их на сервер» (вместо «вызвать API, предоставляемый библиотекой на устройстве»)."или" вызвать метод в Android SDK ").В этом случае у вас есть код для общения с этим сервером.Это может быть код общего назначения (например, OkHttp, Retrofit) или специфичный для API код (например, Facebook SDK).

В любом случае вам нужно будет посмотреть, что этот код поддерживает для содержимого вашего изображения:

  • Если он поддерживает Uri, попробуйте использовать Uri

  • Если он поддерживает InputStream (или Reader некоторыхтип), используйте openInputStream() на ContentResolver

  • Если он поддерживает FileDescriptor или AssetFileDescriptor, используйте openFileDescriptor() на ContentResolver

  • Если он поддерживает только File, вместо использования contentResolver.insert() для получения Uri для отправки в приложение камеры, используйте FileProvider, чтобы вы могли сохранить изображения в файле, которыйВы контролируете (например, в getCacheDir())

  • и т. д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...