android - Kotlin 和 Android Studio - Unresolved reference : FirebaseInstanceId

标签 android firebase kotlin

大家好社区。在我的应用程序中执行 RUN 命令时,我从这篇文章的标题中收到消息。

第一个 .kt 文件 (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()
    }
}

第二个 .kt 文件 (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 截图:

Debugger error message

应用级 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
}

我知道这是折旧的,我需要用 Firebase 安装或消息传递替换折旧 - 但我真的不知道从哪里开始,因为这不是我的代码,我买了这个,开发人员就消失了,把这个留给我。

我不擅长 Android/Kotlin 开发,但我是网络开发人员 - 所以任何指导都会对我有帮助。

非常感谢大家...

编辑

我尝试导入与 firebase 消息传递和安装相关的依赖项,并尝试用 Firebase 文档中的建议替换过时的代码,但每次我都会遇到另一个新错误。

最佳答案

FirebaseInstanceId 已删除,您可以阅读更多 here

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

就是说,替换这个 FirebaseInstanceId.getInstance().instanceIdFirebaseInstallations.getInstance().id。您的 First.kt 将更新为:


    @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()
                                }
                            }
                        }
                    }
                }
            }
        }

获取 token FirebaseInstallations.getInstance().getToken(false).result.token

关于android - Kotlin 和 Android Studio - Unresolved reference : FirebaseInstanceId,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67813561/

相关文章:

kotlin - Micronaut 和 kotin 中的 Mockito 不起作用

java - 从 Kotlin 到 Java 的原始转换

java - 错误与removeAt java arraylist android

android - 如何在 AVD Eclipse 上运行和编译 Android 应用程序

android - 使用缓慢的 onDraw 在 Android 上平滑滚动

ios - 设备上未验证的电子邮件 (Firebase)

javascript - Firebase如何基于多个条件进行查询?

android - 动画 Sprite 动画在 AndEngine 中不止一次

android - 从父级的样式定义中获取子级的样式属性

javascript - Firebase Cloud Functions 超时的效率