Convert Map to Bundle in android

AndroidFirebaseBundleFirebase Cloud-Messaging

Android Problem Overview


Is there an easy way to convert a Map to a Bundle in android without explicit iteration?

Why?

Firebase returns a Map for Notification getData(). I need to pass the data to an intent. Formerly GCM gave me a bundle, so I didn't need to worry about this.

Android Solutions


Solution 1 - Android

I guess a good old fashioned for loop is the easiest way:

    Bundle bundle = new Bundle();
    for (Map.Entry<String, String> entry : getData().entrySet()) {
        bundle.putString(entry.getKey(), entry.getValue());
    }

Solution 2 - Android

Neat Kotlin solution using spread operator will look like that:

fun Map<String, Any?>.toBundle(): Bundle = bundleOf(*this.toList().toTypedArray())

Solution 3 - Android

Came across this same issue with firebase messaging and created a kotlin extension function for it. The gist is here, code below. Although I am using this method there are some caveats:

  • it doesn't cover all of the types that can be put into a bundle
  • it is still under development and hasn't been fully tested

With this in mind, please use it as a guide not a definitive solution. I will keep the gist up to date as it evolves.

import android.os.Bundle 
import android.os.IBinder
import android.os.Parcelable
import java.io.Serializable

fun <V> Map<String, V>.toBundle(bundle: Bundle = Bundle()): Bundle = bundle.apply {
  forEach {
    val k = it.key
    val v = it.value
    when (v) {
      is IBinder -> putBinder(k, v)
      is Bundle -> putBundle(k, v)
      is Byte -> putByte(k, v)
      is ByteArray -> putByteArray(k, v)
      is Char -> putChar(k, v)
      is CharArray -> putCharArray(k, v)
      is CharSequence -> putCharSequence(k, v)
      is Float -> putFloat(k, v)
      is FloatArray -> putFloatArray(k, v)
      is Parcelable -> putParcelable(k, v)
      is Serializable -> putSerializable(k, v)
      is Short -> putShort(k, v)
      is ShortArray -> putShortArray(k, v)

//      is Size -> putSize(k, v) //api 21
//      is SizeF -> putSizeF(k, v) //api 21

      else -> throw IllegalArgumentException("$v is of a type that is not currently supported")
//      is Array<*> -> TODO()
//      is List<*> -> TODO()
    }
  }
}

Solution 4 - Android

Nowadays you can use fun bundleOf(vararg pairs: Pair<String, Any?>)

Solution 5 - Android

You can use writeToParcel(Parcel out, int flags)to generate a Parcel that could be similarly useful, since it's a parent class of Bundle, and it's handily built into the Firebase framework as part of the RemoteMessage class. Documentation is https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/RemoteMessage.html#writeToParcel(android.os.Parcel, int)">here.

Solution 6 - Android

here is how I did it in Kotlin

val bundle = Bundle()

for (entry in data.entries)
    bundle.putString(entry.key, entry.value)

Solution 7 - Android

In Kotlin you can build a function extension to convert Map to Bundle without explicit iteration like so:

override fun onMessageReceived(remoteMessage: RemoteMessage) {
        val payload = remoteMessage.data.toBundle()
        Log.d(TAG, "Notification payload: $payload")
        // ...
}

where toBundle() is defined like so:

inline fun <reified T> Map<String, T>.toBundle(): Bundle = bundleOf(*toList<String, T?>().toTypedArray())

or again:

inline fun <reified T> Map<String, T>.toBundle(): Bundle = bundleOf(*map { it.key to it.value }.toTypedArray())

Solution 8 - Android

For future reference 

> Convert Map to String

  fun Map<String, String>.convertExtraMapToString(): String? {
    return keys.stream()
        .map { key: String -> "$key=" + this[key] }.collect(Collectors.joining(", ", "{", "}"))
}

> Convert String to Map then to Bundle

fun String.convertExtraMapToBundle(): Bundle {
    return Arrays.stream(split(",".toRegex()).toTypedArray())
        .map { entry: String -> entry.split("=".toRegex()).toTypedArray() }
        .collect(Collectors.toMap(
            { entry: Array<String> -> entry[0] }) { entry: Array<String> -> entry[1] }).let {
            bundleOf(*it.toList().toTypedArray())
        }
}

Solution 9 - Android

 private ArrayList<Bundle> convertMapToBundleList(ArrayList<HashMap<String, String>> mapList)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNouvel TravayView Question on Stackoverflow
Solution 1 - AndroidMarcin KozińskiView Answer on Stackoverflow
Solution 2 - AndroidbgplayaView Answer on Stackoverflow
Solution 3 - AndroidBulwinkelView Answer on Stackoverflow
Solution 4 - AndroidbakuaView Answer on Stackoverflow
Solution 5 - AndroidSQLiteNoobView Answer on Stackoverflow
Solution 6 - AndroidDan AlboteanuView Answer on Stackoverflow
Solution 7 - Androidvitiello.antonioView Answer on Stackoverflow
Solution 8 - AndroidAnoop M MaddasseriView Answer on Stackoverflow
Solution 9 - AndroidChetan SankhlaView Answer on Stackoverflow