Как загрузить изображение на сервер с камеры, используя новые API-интерфейсы Activity Contracts?

Я пытаюсь загрузить изображение на сервер, используя изображение камеры с новым методом контрактов активности, но получаю исключение, например: нет такого файла или каталога для моего выбранного пути.

Вот что я сделал до сих пор:

      private fun takeImage() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
        lifecycleScope.launchWhenStarted {
            getTmpFileUri().let { uri ->
                latestTmpUri = uri
                getImageResult.launch(uri)
            }
        }
    } else {
        requestCameraPermission.launch(Manifest.permission.CAMERA)
    }
}
      private fun getTmpFileUri(): Uri {
    val timeStamp: String = SimpleDateFormat("ddMMyyyy", Locale.getDefault()).format(Date())
    val tmpFile = File.createTempFile(timeStamp, ".png", cacheDir).apply {
        createNewFile()
        deleteOnExit()
    }

    return FileProvider.getUriForFile(applicationContext, "${BuildConfig.APPLICATION_ID}.provider", tmpFile)
}
      private val getImageResult = registerForActivityResult(ActivityResultContracts.TakePicture()) { isSuccess ->
    if (isSuccess) {
        latestTmpUri?.let {
            //loadImage(it, binding.imgProfile)
            image = File(it.path.toString())
            uploadImage()
        }
    }
}
       if (image != null) {
        profileImage = image.toMultipartBody("profile_image")
    } // and than code for api calls which use profileImage to upload
      fun File?.toMultipartBody(name: String): MultipartBody.Part? {
    this ?: return null
    return MultipartBody.Part.createFormData(
        name,
        this.name,
        RequestBody.create(getMimeType().toMediaTypeOrNull(), this)
    )
}

private fun File.getMimeType(): String {
    var type: String? = null
    val url = this.toURI().toURL().toString()
    val extension = url.substringAfterLast(".")
    return when (extension.lowercase(Locale.getDefault())) {
        "jpg", "jpeg", "png" -> "image/$extension"
        "mp4" -> "video/$extension"
        "pdf" -> "application/$extension"
        else -> "image/*"
    }
}

Любая помощь приветствуется!

1 ответ

Я решил эту проблему следующим образом:

Во-первых, при создании tempFile с использованием приватной функции getTmpFileUri(): Uri получает абсолютный путь к tempFile и сохраняет его в глобальной переменной, как показано ниже:

      private fun getTmpFileUri(): Uri {
    val timeStamp: String = SimpleDateFormat("ddMMyyyy", Locale.getDefault()).format(Date())
    val tmpFile = File.createTempFile(timeStamp, ".png", cacheDir).apply {
        createNewFile()
        deleteOnExit()
    }
    imagePath = tmpFile.absolutePath // store file path in variable

    return FileProvider.getUriForFile(applicationContext, "${BuildConfig.APPLICATION_ID}.provider", tmpFile)
}

теперь используйте этот путь для создания файла изображения, как показано ниже:

       private val getImageResult = registerForActivityResult(ActivityResultContracts.TakePicture()) { isSuccess ->
    if (isSuccess) {
        latestTmpUri?.let {
            image = File(imagePath)
            uploadImage()
        }
    }
}

Теперь вы можете использовать переменное изображение для загрузки файла изображения в методе uploadImage().

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