Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin & Android Studio - Unresolved reference: FirebaseInstanceId

Hello to all in community. I get message from title of this post during executing RUN command in my app.

First .kt file (MyTaxiApplication.kt):

package com.innomalist.taxi.common

import android.app.Activity
import android.app.Application
import androidx.appcompat.app.AppCompatDelegate
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ProcessLifecycleOwner
import com.google.firebase.FirebaseApp
import com.google.firebase.iid.FirebaseInstanceId
import com.innomalist.taxi.common.components.BaseActivity
import com.innomalist.taxi.common.networking.socket.interfaces.ConnectionError
import com.innomalist.taxi.common.networking.socket.interfaces.RemoteResponse
import com.innomalist.taxi.common.networking.socket.interfaces.SocketNetworkDispatcher
import com.innomalist.taxi.common.utils.AlertDialogBuilder
import com.innomalist.taxi.common.utils.LoadingDialog
import com.innomalist.taxi.common.utils.MyPreferenceManager
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

class MyTaxiApplication: Application(), LifecycleObserver {
    private var currentActivity: BaseActivity? = null

    override fun onCreate() {
        FirebaseApp.initializeApp(applicationContext)
        val nightMode = AppCompatDelegate.MODE_NIGHT_NO
        AppCompatDelegate.setDefaultNightMode(nightMode)
        ProcessLifecycleOwner.get().lifecycle.addObserver(this)
        super.onCreate()
    }


    fun getCurrentActivity(): Activity {
        return currentActivity!!
    }

    fun setCurrentActivity(mCurrentActivity: BaseActivity?) {
        currentActivity = mCurrentActivity
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onMoveToForeground() {
        if(currentActivity is BaseActivity && !(currentActivity as BaseActivity).shouldReconnect) return
        val token = MyPreferenceManager.getInstance(this).token ?: return
        if(SocketNetworkDispatcher.currentNamespace == null)  return
        if(currentActivity != null) LoadingDialog.display(currentActivity!!)
        FirebaseInstanceId.getInstance().instanceId.addOnCompleteListener { fb ->
            SocketNetworkDispatcher.instance.connect(SocketNetworkDispatcher.currentNamespace!!, token, fb.result!!.token) {
                when(it) {
                    is RemoteResponse.Success -> {
                        LoadingDialog.hide()
                        currentActivity?.onReconnected()
                    }

                    is RemoteResponse.Error -> {
                        GlobalScope.launch(Main) {
                            if(it.error == ConnectionError.TokenVerificationError)
                                return@launch
                            AlertDialogBuilder.show(currentActivity!!, getString(R.string.error_message_reconnection_failed, it.error.rawValue),AlertDialogBuilder.DialogButton.OK) {
                                currentActivity!!.finishAffinity()
                            }
                        }
                    }
                }
            }
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onMoveToBackground() {
        SocketNetworkDispatcher.instance.disconnect()
    }
}

Second .kt file (SocketNetworkDispatcher.kt):

package com.innomalist.taxi.common.networking.socket.interfaces

import android.content.Context
import android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR
import android.util.Log
import com.google.android.gms.maps.model.LatLng
import com.innomalist.taxi.common.Config
import com.innomalist.taxi.common.models.ChatMessage
import com.innomalist.taxi.common.models.Request
import com.innomalist.taxi.common.utils.Adapters
import com.innomalist.taxi.common.utils.AlertDialogBuilder
import com.squareup.moshi.Json
import io.socket.client.IO
import io.socket.client.Manager.EVENT_ERROR
import io.socket.client.Socket
import io.socket.engineio.client.Socket.EVENT_ERROR
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.json.JSONObject

class SocketNetworkDispatcher : NetworkDispatcher {
    companion object {
        var instance = SocketNetworkDispatcher()
        var currentNamespace: Namespace? = null
    }
    var socket: Socket? = null
    var onNewMessage: ((ChatMessage) -> Unit)? = null
    var onArrived: ((Int) -> Unit)? = null
    var onStarted: ((Request) -> Unit)? = null
    var onTravelInfo: ((LatLng) -> Unit)? = null
    var onNewRequest: ((Request) -> Unit)? = null
    var onFinished: ((FinishResult) -> Unit)? = null
    var onCancel: ((Int) -> Unit)? = null
    var onCancelRequest: ((Int) -> Unit)? = null
    var onDriverAccepted: ((Request) -> Unit)? = null
    var onPaid: ((Int) -> Unit)? = null

    override fun dispatch(event: String, params: Array<Any>?, completionHandler: (RemoteResponse<Any, SocketClientError>) -> Unit) {
        if(socket == null) {
            return
        }
        socket!!.emit(event, params) {
            if ((it.size > 1)) {
                completionHandler(RemoteResponse.createError(SocketClientError.InvalidAckParamCount))
                return@emit
            }
            if ((it.isEmpty())) {
                GlobalScope.launch(Dispatchers.Main) {
                    completionHandler(RemoteResponse.createSuccess(EmptyClass()))
                }
                return@emit
            }
            completionHandler(RemoteResponse.createSuccess(it[0]))
        }
    }

    fun connect(namespace: Namespace, token: String, notificationId: String, completionHandler: (RemoteResponse<Boolean, ConnectionError>) -> Unit) {
        val options = IO.Options()
        currentNamespace = namespace
        options.reconnection = true
        options.query = "token=$token&os=android&ver=60&not=$notificationId"
        socket = IO.socket("${Config.Backend}${namespace.rawValue}", options)
        socket!!.on(Socket.EVENT_CONNECT) {
            completionHandler(RemoteResponse.createSuccess(true))
        }
        val on = socket!!.on(Socket.EVENT_ERROR) {
            //socket!!.disconnect()
            if (it.isEmpty()) {
                completionHandler(RemoteResponse.createError(ConnectionError.ErrorWithoutData))
            } else if (it[0] is JSONObject) {
                Log.e("Error message", (it[0] as JSONObject)["message"] as String)
                completionHandler(RemoteResponse.createError(ConnectionError.TokenVerificationError))
            } else if (it[0] is String) {
                val knownError = ConnectionError(rawValue = it[0] as String)
                if (knownError != null) {
                    completionHandler(RemoteResponse.createError(knownError))
                } else {
                    completionHandler(RemoteResponse.createError(ConnectionError.Unknown))
                }
            } else {
                completionHandler(RemoteResponse.createError(ConnectionError.NotDecodableError))
            }
        }
        socket!!.on("cancelRequest") { item ->
                GlobalScope.launch(Dispatchers.Main) {
                    onCancelRequest?.invoke(item[0] as Int)
                }
            }
        // Driver Events
        socket!!.on("requestReceived") { item ->
            val travel = Adapters.moshi.adapter(Request::class.java).fromJson(item[0].toString())
            GlobalScope.launch(Dispatchers.Main) {
                onNewRequest?.invoke(travel!!)
            }
        }
        socket!!.on("messageReceived") { item ->
            val message = Adapters.moshi.adapter<ChatMessage>(ChatMessage::class.java).fromJson(item[0].toString())
            onNewMessage?.invoke(message!!)
        }
        socket!!.on("cancelTravel") {
            GlobalScope.launch(Dispatchers.Main) {
                onCancel?.invoke(0)
            }
        }
        socket!!.on("paid") {
            GlobalScope.launch(Dispatchers.Main) {
                onPaid?.invoke(0)
            }
        }
        socket!!.on("arrived") {
            GlobalScope.launch(Dispatchers.Main) {
                onArrived?.invoke(0)
            }
        }
        socket!!.on("started") { item ->
            val travel = Adapters.moshi.adapter<Request>(Request::class.java).fromJson(item[0].toString())
            GlobalScope.launch(Dispatchers.Main) {
                onStarted?.invoke(travel!!)
            }
        }
        socket!!.on("travelInfoReceived") { item ->
            val json = item[0] as JSONObject
            val lng = json.getDouble("x")
            val lat = json.getDouble("y")
            val loc = LatLng(lat, lng)
            GlobalScope.launch(Dispatchers.Main) {
                onTravelInfo?.invoke(loc)
            }
        }
        socket!!.on("Finished") { item ->
            GlobalScope.launch(Dispatchers.Main) {
                if(item[1] is Int) {
                    onFinished?.invoke(FinishResult(item[0] as Boolean, (item[1] as Int).toDouble()))
                } else {
                    onFinished?.invoke(FinishResult(item[0] as Boolean, item[1] as Double))

                }
            }
        }
        socket!!.on("driverAccepted") { item ->
            val travel = Adapters.moshi.adapter<Request>(Request::class.java).fromJson(item[0].toString())
            GlobalScope.launch(Dispatchers.Main) {
                onDriverAccepted?.invoke(travel!!)
            }
        }
        socket!!.connect()
    }

    fun disconnect() {
        socket?.disconnect()
    }
}

enum class Namespace(val rawValue: String) {
    Driver("drivers"), Rider("riders")
}

enum class ConnectionError(val rawValue: String) {
    @Json(name = "VersionOutdated")
    VersionOutdated("VersionOutdated"),
    @Json(name="NotFound")
    NotFound("NotFound"),
    @Json(name="NotFound")
    Blocked("Blocked"),
    @Json(name="RegistrationIncomplete")
    RegistrationIncomplete("RegistrationIncomplete"),
    @Json(name="TokenVerificationError")
    TokenVerificationError("TokenVerificationError"),
    @Json(name="NotDecodableError")
    NotDecodableError("NotDecodableError"),
    @Json(name="Unknown")
    Unknown("Unknown"),
    @Json(name="ErrorWithoutData")
    ErrorWithoutData("ErrorWithoutData");

    fun showAlert(context: Context) {
        AlertDialogBuilder.show(context, this.toString(), AlertDialogBuilder.DialogButton.OK, null)
    }

    companion object {
        operator fun invoke(rawValue: String) = values().firstOrNull { it.rawValue == rawValue }

    }
}

data class FinishResult(
        val paid: Boolean,
        val remainingAmount: Double
)

enum class SocketClientError(val rawValue: String) {
    InvalidAckParamCount("InvalidAckParamCount"), RequestTimeout("RequestTimeout");

    companion object {
        operator fun invoke(rawValue: String) = values().firstOrNull { it.rawValue == rawValue }
    }

    val localizedDescription: String
        get() {
            return when (this) {
                InvalidAckParamCount -> "Result parameter count is more than one. It's unexpected."
                RequestTimeout -> "Request Timeout"
            }
        }
}

DEBUG - ERROR Screeenshoot:

Debugger error message

app-level build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    ext.kotlin_version = '1.4.31'
    repositories {
        maven { url "https://maven.google.com" }
        jcenter()
        google()
        maven { url 'https://plugins.gradle.org/m2/'}
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.3'
        classpath 'com.google.gms:google-services:4.3.8'
        classpath 'com.google.firebase:firebase-crashlytics-gradle:2.6.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

allprojects {
    repositories {
        maven { url "https://maven.google.com" }
        jcenter()
        mavenCentral()
        google()
        maven { url "https://jitpack.io" }
        maven {
            url "https://cardinalcommerce.bintray.com/android"
            credentials {
                username 'braintree-team-sdk@cardinalcommerce'
                password '220cc9476025679c4e5c843666c27d97cfb0f951'
            }
        }
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}

I know this is depreciated, and that I need to replace depreciated with Firebase Installation or Messaging - but I really don't have a clue from where to strat, because this is not my code, I bought this and developers just vanished and left me with this.

I'm not good in Android/Kotlin development, but I'm web developer - so any guidance will do me good.

Thank you very much all...

EDIT

I tried import of dependencies related to firebase messaging and installation and tried to replace obsolete code with suggestions from Firebase documentation, but every time I get another, new error.

like image 663
Eager2Learn Avatar asked May 13 '26 22:05

Eager2Learn


1 Answers

FirebaseInstanceId is depricated, you can read more here

Firebase Instance ID has been replaced with FirebaseInstallations for app instance identifiers and FirebaseMessaging.getToken() for FCM registration tokens.

That said, replace this FirebaseInstanceId.getInstance().instanceId with FirebaseInstallations.getInstance().id. Your First.kt will be updated to:


    @OnLifecycleEvent(Lifecycle.Event.ON_START)
        fun onMoveToForeground() {
            if(currentActivity is BaseActivity && !(currentActivity as BaseActivity).shouldReconnect) return
            val token = MyPreferenceManager.getInstance(this).token ?: return
            if(SocketNetworkDispatcher.currentNamespace == null)  return
            if(currentActivity != null) LoadingDialog.display(currentActivity!!)
// Replace FirebaseInstanceId with FirebaseInstallations
            FirebaseInstallations.getInstance().id.addOnCompleteListener { fb ->
    
     if (!fb.isSuccessful){
                return@addOnCompleteListener
            }
                SocketNetworkDispatcher.instance.connect(SocketNetworkDispatcher.currentNamespace!!, token, fb.result) {
                    when(it) {
                        is RemoteResponse.Success -> {
                            LoadingDialog.hide()
                            currentActivity?.onReconnected()
                        }
    
                        is RemoteResponse.Error -> {
                            GlobalScope.launch(Main) {
                                if(it.error == ConnectionError.TokenVerificationError)
                                    return@launch
                                AlertDialogBuilder.show(currentActivity!!, getString(R.string.error_message_reconnection_failed, it.error.rawValue),AlertDialogBuilder.DialogButton.OK) {
                                    currentActivity!!.finishAffinity()
                                }
                            }
                        }
                    }
                }
            }
        }

To get the token FirebaseInstallations.getInstance().getToken(false).result.token

like image 83
Edward Muturi Avatar answered May 17 '26 10:05

Edward Muturi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!