Android Upload File to Cloud Storage for Firebase (Kotlin)

Add Firebase to Android (Setup Firebase on Android)

Setup Storage

Goto Firebase Console -> Storage -> Get started.

By default, your rules allow all reads and writes from authenticated users.

// Only authenticated users can read or write to the bucket
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

If you are not using Firebase Auth yet, you need to make the access public (I believe this is a security risk, and recommended to implement Firebase Auth as soon as possible).

// Anyone can read or write to the bucket, even non-users of your app.
// Because it is shared with Google App Engine, this will also make
// files uploaded via GAE public.
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write;
    }
  }
}

NOTE: Like Firestore, security rules only apply to client (Android, iOS, Web) while server-side code can access everything.

You might want to read up on storage classes and locations later.

Android

Dependecies

dependencies {
    // implementation 'com.google.firebase:firebase-storage:19.1.0'
    // using kotlin implementation
    implementation 'com.google.firebase:firebase-storage-ktx:19.1.0'
}

Upload

suspend fun uploadPhoto(uid: String?, file: File, name: String, mimeType: String?): String {    val storage = FirebaseStorage.getInstance()    val storageRef = storage.reference    val fileRef = if (uid == null)        storageRef.child("public/images/$name")    else        storageRef.child("user/$uid/images/$name")    var uri = Uri.fromFile(file)    // TODO: handle exception    // await - kotlinx-coroutines-play-services    val metadata = mimeType?.let {        StorageMetadata.Builder()            .setContentType(mimeType)            // .setCustomMetadata("ref", "test")            .build()    }    val task = if (metadata != null) {        fileRef.putFile(uri, metadata).await()    }    else {        fileRef.putFile(uri).await()    }    // val task = fileRef.putStream(stream).await()    // task.metadata.reference == fileRef    val url =  fileRef.downloadUrl.await().toString()    // url can be used to reconstruct StorageReference    // val ref = storage.getReferenceFromUrl(url)    // Timber.d("name=${ref.name}, path=${ref.path}, bucket=${ref.bucket}, same=${fileRef == ref}")    return url}

You might want to store the URI path to access the storage object.

val StorageReference.uriString: String    // gs://bucket/images/stars.jpg    get() = "gs://$bucket$path"val id = fileRef.uriStringval ref = storage.getReferenceFromUrl(id)

NOTE: Using Kotlin Coroutines and kotlinx-coroutines-play-services.

Security Rules

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    // by default, only authenticated user ca read and write
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }

    // anyone can read and write at /public
    match /public/{allPaths=**} {
      allow read, write;
    }

    // only owner can read and write at /user/{userId}
    // Files look like: "user/<UID>/path/to/file.txt"
    match /user/{userId}/{allPaths=**} {
      allow read, write: if request.auth.uid == userId;
    }
  }
}

NOTE: You might want to resize image before upload.

References:

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.