secondubly
secondubly

Reputation: 1032

Struggling with trying to get image from camera to upload to Firebase - java.lang.IllegalStateException: uri must not be null

I've been reading through every post on here relating (as well as the documentation) to this topic and for some reason I just can't get it working. I get to the point where the user takes a photo, hits the checkmark to continue, and then the app crashes.

Specifically at this line:

val filepath = mFirebaseStorage.child("Users").child(prefs.UID).child(uri.lastPathSegment)

My code looks something like this:

onLaunchCamera - called when user selects "Camera" from alert box

private fun onLaunchCamera() {
    val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    //Ensure there's a camera activity to handle the intent
    if (takePictureIntent.resolveActivity(packageManager) != null) {
        var photoFile: File? = null
        try {
            photoFile = createImageFile()
        } catch (e: IOException) {
            //log error
            Log.e(TAG, e.toString())
        }
        //continue only if file was successfully created!
        if (photoFile != null) {
            val photoURI = FileProvider.getUriForFile(this,
                    "com.android.projectrc.fileprovider",
                    photoFile)
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
        }
    }
}

onActivityResult

override protected fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    super.onActivityResult(requestCode, resultCode, data)

    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
        val progressDialog = indeterminateProgressDialog("Uploading...")
        progressDialog.show()
        Log.d(TAG,"URI:: ${photoURI}")
        val uri = data.data

        val filePath = mFirebaseStorage.child("Users").child(prefs.UID)
                .child("ProfileImage").child(uri.lastPathSegment)
        filePath.putFile(photoURI!!).addOnSuccessListener(OnSuccessListener <UploadTask.TaskSnapshot >() {
            fun onSuccess(taskSnapshot : UploadTask.TaskSnapshot) {
                toast("Upload Successful!")
                progressDialog.dismiss()
            }
        }).addOnFailureListener(OnFailureListener () {
            fun onFailure(e : Exception) {
                Log.e(TAG, e.toString())
                toast("Upload Failed!")
            }
        });
        //val bundle = data.extras
    }
}

createImageFile

private fun createImageFile(): File {
    // Create an image file name
    val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US)
    val imageFileName = "JPEG_" + timeStamp + "_";
    val storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
    val image = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    mCurrentPhotoPath = image.absolutePath;
    return image
}

AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="ANDROID.PERMISSION.READ_EXTERNAL_STORAGE" />

<application
    android:name=".App"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.android.projectrc.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>

files_path.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="Android/data/com.android.projectrc/files/Pictures" />
</paths>

Even photoURI shows up null when the console outputs it - I'm at quite a loss and would appreciate any help!

Upvotes: 0

Views: 501

Answers (1)

Bob Snyder
Bob Snyder

Reputation: 38309

The answer to this related question explains that when a URI is passed as EXTRA_OUTPUT on the ACTION_IMAGE_CAPTURE intent, the URI is not returned as data on the intent parameter to onActivityResult().

This means you must save the URI in a class variable when it is generated so that it is available in onActivityResult(). It appears you already have photoURI declared as a class variable and that you intended to define it's value with this code in onLaunchCamera():

        val photoURI = FileProvider.getUriForFile(this,
                "com.android.projectrc.fileprovider",
                photoFile)

But the val is creating a new instance of photoURI and the value is not stored in the class field as you want. Remove val.

Upvotes: 1

Related Questions