0

I'm trying to build an Instagram-like app, an issue occurs when I try to save taken photo to user's folder "images" on Firebase database. It keeps saving something like "com.google.firebase.storage.UploadTask@62873ce"

Instead of link like this: "https://firebasestorage.googleapis.com/v0/b/gramgram-1b3f9.appspot.com/o/users%2F7q3pqR6GnHMx7NSdgoBqZETkrS32%2Fphoto?alt=media&token=bbcbe556-1de5-4176-aba2-599f829e65"

here is my Share Activity.kt

class ShareActivity : BaseActivity(2) {
    private val TAG = "ShareActivity"
    private lateinit var mCamera: CameraHelper
    private lateinit var mFirebase: FirebaseHelper


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_share)
        Log.d(TAG, "onCreate")

        mFirebase =FirebaseHelper(this)

        mCamera = CameraHelper(this)
        mCamera.takeCameraPicture()

        back_image.setOnClickListener{finish()}
        share_text.setOnClickListener{share()}
    }


    @SuppressLint("MissingSuperCall")
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (requestCode == mCamera.REQUEST_CODE){
            if (resultCode == RESULT_OK){
                GlideApp.with(this).load(mCamera.imageUri).centerCrop().into(post_image)
            } else{
                finish()
            }
        }
    }

    private fun share(){
        val imageUri = mCamera.imageUri
        if (imageUri != null){
            val uid = mFirebase.auth.currentUser!!.uid
            mFirebase.storage.child("users").child(uid).child("images")
                .child(imageUri.lastPathSegment!!).putFile(imageUri).addOnCompleteListener {
                    if (it.isSuccessful){
                        mFirebase.database.child("images").child(uid).push()
                            .setValue(it.toString())
                            .addOnCompleteListener{
                                if (it.isSuccessful){
                                    startActivity(Intent(this,
                                        ProfileActivity::class.java))
                                    finish()
                                } else {
                                    showToast(it.exception!!.message!!)
                                }
                            }
                    } else {
                        showToast(it.exception!!.message!!)
                    }
                }
        }
    }
}

here are my uploadUserPhoto and updateUsePhoto functions in FirebaseHelper.kt

fun uploadUserPhoto(photo: Uri, onSuccess: (String) -> Unit) {
    val uTask = storage.child("users/${auth.currentUser!!.uid}/photo").putFile(photo)
        storage.child("users/${auth.currentUser!!.uid}/photo").putFile(photo)
            .addOnCompleteListener {
        if (it.isSuccessful) {
            uTask.continueWithTask { _ ->
                storage.child("users/${auth.currentUser!!.uid}/photo").downloadUrl
            }.addOnCompleteListener{
                if (it.isSuccessful && it.result != null) {
                    onSuccess(it.result.toString())
                } else {
                    activity.showToast(it.exception!!.message!!)
                }
            }
        }
    }
}


fun updateUserPhoto( photoUrl: String, onSuccess: () -> Unit){
    database.child("users/${auth.currentUser!!.uid}/photo").setValue(photoUrl)
        .addOnCompleteListener {
            if (it.isSuccessful) {
                onSuccess()
            } else {
                activity.showToast(it.exception!!.message!!)
            }
        }
}

I am not sure how to set my private fun share() to upload correct URL to User's "images" folder

and here is my CameraHelper.kt

class CameraHelper(private val activity: Activity){
var imageUri: Uri? = null
val REQUEST_CODE = 1
private val simpleDateFormat = SimpleDateFormat(
    "yyyyMMdd_HHmmss",
    Locale.US
)

fun takeCameraPicture() {
    val intent =
        Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    if (intent.resolveActivity(activity.packageManager) != null) {
        val imageFile = createImageFile()
        imageUri = FileProvider.getUriForFile(
            activity,
            "com.example.homeactivity.fileprovider",
            imageFile
        )
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
        activity.startActivityForResult(intent, REQUEST_CODE)
    }
}

private fun createImageFile(): File {
    val storageDir: File? = activity.getExternalFilesDir(
        Environment.DIRECTORY_PICTURES
    )
    return File.createTempFile(
        "JPEG_${simpleDateFormat.format(Date())}_",
        ".jpg",
        storageDir
    )
}

}

Renato Lulic
  • 200
  • 2
  • 18
  • `setValue(it.toString())` -- `it` here I think is your `UploadTask`. I haven't used Firebase Realtime Database in about a year, but I doubt that you call `toString()` on the `UploadTask` to get the URL. – CommonsWare Jan 11 '20 at 21:57
  • Where are you calling uploadUserPhoto? – Doug Stevenson Jan 11 '20 at 22:03
  • Tried that, it crashes the app and gives com.google.firebase.database.DatabaseException: Found conflicting getters for name: getResult @CommonsWare – Renato Lulic Jan 11 '20 at 22:04
  • @DougStevenson I'm calling it in another function for uploading profile picture, but I shared this code just for you guys to see the code that works correctly and I don't know how to set my Private fun share() to work like this – Renato Lulic Jan 11 '20 at 22:05

2 Answers2

1

You're not using the result from putFile(imageUri) correctly. You have:

putFile(imageUri).addOnCompleteListener {
    if (it.isSuccessful){
        mFirebase.database.child("images").child(uid).push()
            .setValue(it.toString())

That it.toString() is not the URL. it is the UploadTask object returned by putFile(). You can't just turn that into a string - it's a Task that you need to observe to get the result.

You seem to be fetching a download URL correctly in uploadUserPhoto using downloadUrl to fetch the URL to write. You're going to have to do it that way instead.

See also the documentation and this question.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • Tried that,removing toString() - it crashes the app and gives com.google.firebase.database.DatabaseException: Found conflicting getters for name: getResult – Renato Lulic Jan 11 '20 at 22:10
  • Tried what exactly? This answer explains why what you have now doesn't work. You're not fetching the download URL at all, except in `uploadUserPhoto`, which you're not even calling. If you have other code that's not working, and it generates a whole a new error, I think that should go in a new question. – Doug Stevenson Jan 11 '20 at 22:12
  • I'm new to programming so, I can't just follow the documentation you provided to me. I removed toString() leaving only "it", and after I click on share photo, it crashes the app. Also, I just wrote the "updateUserPhoto" in the hope that someone will tell me how to fix my private fun share() the way "updateUserPhoto" is fixed – Renato Lulic Jan 11 '20 at 22:14
  • That wasn't my recommended solution. You need to use downloadUrl to fetch the download URL from a reference in the same way that you're using in `uploadUserPhoto` and both links that I provided. – Doug Stevenson Jan 11 '20 at 22:21
  • Doug, thanks for pointing that out, but I'm new to programming so, I can't just follow the documentation you provided to me. I asked for help because I don't know how to do that myself.. :/ – Renato Lulic Jan 11 '20 at 22:24
  • 1
    I pointed out that you already know how to fetch the download URL - you are doing it in the `uploadUserPhoto` you posted in your question. The linked question also gives code samples. You can adapt these to fit your situation. – Doug Stevenson Jan 11 '20 at 22:52
0

I managed to solve it. In case anyone needs it, here is working function share():

private fun share(){
    val imageUri = mCamera.imageUri
    if (imageUri != null){
        val uid = mFirebase.auth.currentUser!!.uid
        val uTask = mFirebase.storage.child("users").child(uid).child("images").child(imageUri.lastPathSegment!!).putFile(imageUri)
        mFirebase.storage.child("users").child(uid).child("images").child(imageUri.lastPathSegment!!).putFile(imageUri)
            .addOnCompleteListener {
                if (it.isSuccessful) {
                    uTask.continueWithTask { _ ->
                        mFirebase.storage.child("users").child(uid).child("images")
                            .child(imageUri.lastPathSegment!!).downloadUrl
                    }.addOnCompleteListener {
                        if (it.isSuccessful && it.result != null)
                            mFirebase.database.child("images").child(uid).push()
                                .setValue(it.result.toString())
                                .addOnCompleteListener {
                                    if (it.isSuccessful) {
                                        startActivity(
                                            Intent(
                                                this,
                                                ProfileActivity::class.java
                                            )
                                        )
                                        finish()
                                    } else {
                                        showToast(it.exception!!.message!!)
                                    }
                                }
                    }
                } else {
                    showToast(it.exception!!.message!!)
                }
            }
    }
}
Renato Lulic
  • 200
  • 2
  • 18