0

I read this so that upon clicking the button, the Camera intent is opened, and returned the saved picture file and path to the activity that called it, but I got my app crashed and restarted without opening the camera intent.

Manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:dist="http://schemas.android.com/apk/distribution"
          package="com.oryx.geoop">

<uses-feature android:name="android.hardware.camera"
                  android:required="true" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA"/>

<application android:theme="@style/AppTheme">
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths">
        </meta-data>
     </provider>

     <activity android:name=".AnotherActivity">
        <intent-filter>
            <action android:name="android.media.action.IMAGE_CAPTURE" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
     </activity>
</application>
</manifest>

The xml/file_paths

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

Activity

class AnotherActivity : AppCompatActivity() {

    val REQUEST_TAKE_PHOTO = 1
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_another)
        // Grant permissions
        Dexter.withActivity(this)
            .withPermissions(
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.CAMERA
            )
            .withListener(object : MultiplePermissionsListener {
                override fun onPermissionRationaleShouldBeShown(
                    permissions: MutableList<PermissionRequest>?,
                    token: PermissionToken?
                ) {
                    /* ... */
                }
            })

        save_local.setOnClickListener { captureFromCamera(this) }
    }

    @Throws(IOException::class)
    private fun createImageFile(): File {
        val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
        val dir =
       """${getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)}/geoOp/"""
       val storageDir = File(dir)
        storageDir.mkdirs()

        return File.createTempFile(
            "JPEG_${timeStamp}_", /* prefix */
            ".jpg", /* suffix */
            storageDir /* directory */
        ).apply {
            // Save a file: path for use with ACTION_VIEW intents
            val currentPhotoPath = absolutePath
        }

    }

    private fun captureFromCamera(context: Context) {
        Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
            // Ensure that there's a camera activity to handle the intent
            takePictureIntent.resolveActivity(context.packageManager)?.also {
                // Create the File where the photo should go
                val photoFile: File? = try {
                    createImageFile()
                } catch (ex: IOException) {
                    // Error occurred while creating the File
                    null
                }
                // Continue only if the File was successfully created
                photoFile?.also {
                    val photoURI: Uri = FileProvider.getUriForFile(
                        this,
                        "com.oryx.geoop.fileprovider",
                        it
                    )
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
                    startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO)
                }
            }
        }
    }

    public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        // Result code is RESULT_OK only if the user captures an Image
        if (resultCode == Activity.RESULT_OK && resultCode == RESULT_OK) {
            Toast.makeText(this, "pic saved", Toast.LENGTH_SHORT).show()
            println("pic saved")
        }
    }
}

UPDATE As getExternalStoragePublicDirectory is deprecated in Android Q, and to be replaced by below code, as shown here:

Kotlin
val resolver = context.contentResolver
val contentValues = ContentValues().apply {
    put(MediaStore.MediaColumns.DISPLAY_NAME, "CuteKitten001")
    put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
    put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/PerracoLabs")
}

val uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)

      resolver.openOutputStream(uri).use {
        // TODO something with the stream
      }

How can I use it in my code above, noting that this update return Uri, while original code returnfile` for image location:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
       // return Uri
} else {
       // return file
}
Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203
  • Regarding your update, presumably you can pass `uri` to the camera app in `EXTRA_STREAM`, though I have not tried this. – CommonsWare Aug 05 '19 at 19:20
  • @CommonsWare How can I use it in my code above, noting that this update return `Uri, while original code return `file` for image location, kindly see my update! – Hasan A Yousef Aug 05 '19 at 19:25

0 Answers0