Search code examples
firebasekotlingoogle-maps-markersandroid-canvasandroid-bitmap

How to convert an image string into integer on Android?


I want to retrieve an image from Firebase and place it in a canvas so that I use it to place in the custom google marker. I get an error when I use the .toInt() method. Maybe that's a wrong way of doing it.

The code:

var loggedInUser : User = User()

                            mFireStore.collection(Constants.USERS)
                                    .document(FirestoreClass().getCurrentUserId())
                                    .get()
                                    .addOnSuccessListener { document ->
                                        loggedInUser = document.toObject(User::class.java)!!
                                    }
                            canvas1.drawBitmap(BitmapFactory.decodeResource(resources,loggedInUser.image.toInt()), 0F, 0F, color)
                            canvas1.drawText("User Name!", 30F, 40F, color)




                            // add marker to Map

                            // add marker to Map
                            markerOptions
                                    .position(LatLng(mLastLocation!!.latitude, mLastLocation!!.longitude))
                                    .title("Current Location")
                                    /*.snippet(address)*/
                                    .icon(BitmapDescriptorFactory.fromBitmap(bmp))

                            mCurrentMarker = googleMap.addMarker(markerOptions)

The logcat where I get error:

2021-07-06 19:33:54.839 10676-10676/com.example.aroundyouapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.aroundyouapp, PID: 10676
java.lang.NumberFormatException: For input string: ""
    at java.lang.Integer.parseInt(Integer.java:627)
    at java.lang.Integer.parseInt(Integer.java:650)
    at com.example.aroundyouapp.activities.MainActivity$getCurrentLocation$1.onLocationResult(MainActivity.kt:394)
    at com.google.android.gms.internal.location.zzau.notifyListener(Unknown Source:4)
    at com.google.android.gms.common.api.internal.ListenerHolder.notifyListenerInternal(com.google.android.gms:play-services-base@@17.1.0:17)
    at com.google.android.gms.common.api.internal.ListenerHolder$zaa.handleMessage(com.google.android.gms:play-services-base@@17.1.0:6)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at com.google.android.gms.internal.base.zar.dispatchMessage(com.google.android.gms:play-services-base@@17.1.0:8)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

How can I convert the Image that is in string format(i.e, loggedInUser.image) to Int so that the image is placed on the canvas? Maybe this is a stupid question but I'm new to this so yeah.

Thank you in advance

Edit 1:

The code that I use to display the profile picture of the user in the navigation menu:

fun loadUserData(activity: Activity){
    //This function is called in MainActivity in the onCreate method.
    mFireStore.collection(Constants.USERS)
        .document(getCurrentUserId())
        .get()
        .addOnSuccessListener { document ->
            val loggedInUser = document.toObject(User::class.java)

            when(activity){
                is MyProfileActivity -> {
                    activity.setUserDataInUI(loggedInUser!!)
                }
                is MainActivity -> {
                    activity.updateNavigationUserDetails(loggedInUser!!)
                }
            }
        }
}

fun updateNavigationUserDetails(user: User){
    hideProgressDialog()
    mUserName = user.name
    Glide
            .with(this)
            .load(user.image)
            .centerCrop()
            .placeholder(R.drawable.ic_user_place_holder)
            .into(nav_user_image)

    tv_username.text = user.name
}

Edit 2:

I tried Ragu's answer. The app crashed after trying it.

This is the error in the logcat.

2021-07-14 19:07:04.779 18663-18663/com.example.aroundyouapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.aroundyouapp, PID: 18663
java.lang.NumberFormatException: For input string: "https://firebasestorage.googleapis.com/v0/b/aroundyou-5f1d2.appspot.com/o/USER_IMAGE1624282533208.jpg?alt=media&token=731ea81d-32a0-4378-aa7b-0d7764260e41"
    at java.lang.Integer.parseInt(Integer.java:615)
    at java.lang.Integer.parseInt(Integer.java:650)
    at com.example.aroundyouapp.activities.MainActivity$getCurrentLocation$1$onLocationResult$1.onSuccess(MainActivity.kt:374)
    at com.example.aroundyouapp.activities.MainActivity$getCurrentLocation$1$onLocationResult$1.onSuccess(MainActivity.kt:349)
    at com.google.android.gms.tasks.zzn.run(Unknown Source:4)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

I got the same error last time but this time the link of the image is shown in the logcat

Edit 3

Got this error after trying updated answer 2 by Ragu

2021-07-14 20:05:57.399 20234-20234/com.example.aroundyouapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.aroundyouapp, PID: 20234
android.os.NetworkOnMainThreadException
    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1565)
    at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:115)
    at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:103)
    at java.net.InetAddress.getAllByName(InetAddress.java:1152)
    at com.android.okhttp.Dns$1.lookup(Dns.java:41)
    at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:178)
    at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:144)
    at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:86)
    at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:176)
    at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
    at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
    at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
    at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:248)
    at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:211)
    at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:30)
    at com.example.aroundyouapp.activities.MainActivity$getCurrentLocation$1$onLocationResult$1.onSuccess(MainActivity.kt:379)
    at com.example.aroundyouapp.activities.MainActivity$getCurrentLocation$1$onLocationResult$1.onSuccess(MainActivity.kt:352)
    at com.google.android.gms.tasks.zzn.run(Unknown Source:4)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Solution

  • Let us assume you are trying to display the image which is in Base64 format.

    Decode the incoming Base64 string to ByteArray

    val imageByteArray = Base64.decode(user.image, Base64.DEFAULT)
    

    Then load imageByteArray to the Glide as below.

    Glide
       .with(this)
       .asBitmap()
       .load(imageByteArray)  // ==> Pass the ByteArray here  
       .into(nav_user_image)
    

    EDIT 1 : Updated Answer

    From your code I can see that, drawing to canvas code is placed outside the addOnSuccessListener from snapshots. But you are accessing the fields of loggedInUser before the completion of addOnSuccessListener where the data is assigned.

    addOnSuccessListener is async operation and will not be executed in sequence like you written in your existing code.

    Move the following code inside the addOnSuccessListener.

    canvas1.drawBitmap(BitmapFactory.decodeResource(resources,loggedInUser.image.toInt()), 0F, 0F, color)
    canvas1.drawText("User Name!", 30F, 40F, color)
    

    Your existing code.

     mFireStore.collection(Constants.USERS)
                                        .document(FirestoreClass().getCurrentUserId())
                                        .get()
                                        .addOnSuccessListener { document ->
                                            loggedInUser = document.toObject(User::class.java)!!
                                        }
                                canvas1.drawBitmap(BitmapFactory.decodeResource(resources,loggedInUser.image.toInt()), 0F, 0F, color)
                                canvas1.drawText("User Name!", 30F, 40F, color)
    

    Updated Answer 2 :

    Based on the error log, the image is retrieved as an remote url which can be directly loaded in the ImageView. But when you are trying to draw it in the canvas you need to decode the file from the remote url as stream and then set it in the Canvas.

    Something like below

    URL url = new URL(<PASS YOUR URL from FIREBASE>);
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
     ....
    Bitmap receivedImageasBitmap = BitmapFactory.decodeStream(connection .getInputStream());
    .. 
    canvas1.drawBitmap(receivedImageasBitmap)