oligazar
11/1/2017 - 4:51 AM

Upload / Delete picture from Firebase Storage

fun savePictures(contentResolver: ContentResolver, uris: Array<String>, onUploaded: (ArrayList<String>) -> Unit) {

        timeStart = System.currentTimeMillis() / 1000
        val storage = FirebaseStorage.getInstance()

        val resultUris = mutableMapOf<Int, String>()
        val tasks = mutableMapOf<Int, Task<Uri>>()
        uris.forEachIndexed { position, path ->
            if (isInStorageAlready(path)) {
                resultUris[position] = path
            } else {
                val uri = Uri.parse(path)
                val bytes = MediaStore.Images.Media.getBitmap(contentResolver, uri)
                        .scaleDown(800f, false)
                        .modifyOrientation(contentResolver, uri)
                        .compress(80)

                val imageRef = storage.getReference(filePath).child(uri.lastPathSegment)
                val uploadTask = imageRef.putStream(ByteArrayInputStream(bytes))

                val urlTask = uploadTask.continueWithTask<Uri> { task ->
                    task.exception?.let {
                        throw it
                    }
                    imageRef.downloadUrl
                }
                // one approach is to use this callback here to get result uris
                .addOnCompleteListener { task ->
                    if (task.isSuccessful) {
                        resultUris[position] = task.result?.toString() ?: ""
                        Log.d(_tag, "savePictures, onComplete, upload uri: ${task.result?.toString() ?: ""}")
                    } else {
                        task.exception?.printStackTrace()
                    }
                }
//                tasks[position] = uploadTask
                tasks[position] = urlTask
            }
        }

        Log.d(_tag, "savePictures, resultUris: $resultUris (size: ${resultUris.size}), tasks: $tasks")
        Tasks.whenAll(tasks.values).addOnCompleteListener { allTask ->
            if (allTask.isSuccessful) {
                tasks.entries.forEach { (index, task) ->
                
                // another one is to use this callback here to get result uris
//                    resultUris[index] = task.result.toString()
                    Log.d(_tag, "savePictures whenAll, upload uri: ${task.result?.toString() ?: ""}, index: $index")
                }
                val time = System.currentTimeMillis() / 1000 - timeStart

                val list = resultUris.toSortedMap().map { (_, value) -> value }
                Log.d(_tag, "savePictures, resultUris: $resultUris, list: $list, time: $time")
                onUploaded(ArrayList(list))
            } else {
                val e = allTask.exception
                e?.printStackTrace()
            }
        }
    }


    private fun removeOldPicFromFireStorage() {
        if (category.picPath.isEmpty()) return

        val picName = extractNameFromPath(category.picPath)
        val picPath = "categories/$site/$picName"
        val storageRef = storage.getReference(picPath)

        storageRef.delete().addOnSuccessListener {
            Log.d("Category", "onSuccess() removing file: ${category.picPath}")
        }.addOnFailureListener { ex ->
            val errorCode = (ex as? StorageException)?.errorCode
            val errorMessage = ex.message

            Log.d("Category", "onFailure() removing file: ${category.picPath}, errorCode: $errorCode, message: $errorMessage")
            Log.d("Category", "onFailure() fileName: $picName")
            Snackbar.make(root, R.string.error_message, Snackbar.LENGTH_SHORT).show()
        }
    }

    private fun extractNameFromPath(picPath: String): String {
        val decodedUrl = URLDecoder.decode(picPath, "UTF-8")
        val path = URL(decodedUrl).path
        return File(path).name
    }

    private fun uploadPicToFireStorage() {

        // show spinner
        val progressDialog = progressDialog(getString(R.string.dialog_saving))
        progressDialog.show()

        // optimize an image
        val bytes = MediaStore.Images.Media.getBitmap(this.contentResolver, selectedImageUri)
                .scaleDown(800f, false)
                .compress(80)

        // save image to Ferebase Storage
        val picName = "img_${UUID.randomUUID()}.jpg"
        val picPath = "categories/$site/$picName"
        val storageRef = storage.getReference(picPath)

        val uploadTask = storageRef.putBytes(bytes)
        uploadTask.addOnSuccessListener(this) { snap ->

            progressDialog.dismiss()
            category.picPath = snap.downloadUrl?.toString() ?: ""

            saveCategoryToFireDb()
        }.addOnFailureListener(this) { ex ->
            progressDialog.dismiss()

            val errorCode = (ex as? StorageException)?.errorCode
            val errorMessage = ex.message

            Log.d("Category", "onFailure() uploading file: $picPath, errorCode: $errorCode, message: $errorMessage")
            Snackbar.make(root, R.string.error_message, Snackbar.LENGTH_SHORT).show()
        }
    }