Android Studio-Kotlin-如何使对服务的引用为空?

Android Studio-Kotlin-如何使对服务的引用为空?,kotlin,service,nullpointerexception,Kotlin,Service,Nullpointerexception,我正在尝试将Google的LocationSupdatesForgroundService示例改编为Kotlin,以便在我的应用程序中使用。现在,一切都很顺利,直到我需要引用一个等于null的服务。这不会在其源代码的Java代码中产生任何问题,但是,当我尝试在Kotlin中实现它时,即使使用null!!,当我尝试运行应用程序时,我收到KotlinNullPointerException,应用程序崩溃。我不太确定如何避免这种情况或以不同的方式设置它。我花了几个小时在这上面,有时浏览StackOve

我正在尝试将Google的LocationSupdatesForgroundService示例改编为Kotlin,以便在我的应用程序中使用。现在,一切都很顺利,直到我需要引用一个等于null的服务。这不会在其源代码的Java代码中产生任何问题,但是,当我尝试在Kotlin中实现它时,即使使用null!!,当我尝试运行应用程序时,我收到KotlinNullPointerException,应用程序崩溃。我不太确定如何避免这种情况或以不同的方式设置它。我花了几个小时在这上面,有时浏览StackOverFlow,却没有真正找到解决方案。如果有人能帮助我,我将不胜感激。我已经附上了我要离开这里的代码的链接:

…以及我在下面使用的必要代码

我的主要活动的相关代码:

private var lservice : LocService = null!! // A reference to the service to get location updates
private var bound = false // Tracks the bound state of the service

// Monitors the state of the connection to the service.
private val mServiceConnection = object:ServiceConnection {
    override fun onServiceConnected(name:ComponentName, service: IBinder) {
        val binder : LocService.LocalBinder = service as LocService.LocalBinder
        lservice = binder.getService()
        bound = true
    }

    override fun onServiceDisconnected(name: ComponentName) {
        lservice = null!!
        bound = false
    }
}
My service类,它可能是或可能不是帮助调试此错误所必需的:

class LocService : Service() {

private val PACKAGE_NAME = "com.example.localization"

private val TAG = LocService::class.java!!.getSimpleName()

val ACTION_BROADCAST = PACKAGE_NAME + ".broadcast"

private val EXTRA_STARTED_FROM_NOTIFICATION = PACKAGE_NAME + ".started_from_notification"

// To return a current instance of the service
private val binder = LocalBinder()

// To check if the bounded activity has actually gone away
// and not unbound as part of an orientation change
private var changingConfig = false

private lateinit var fusedLocClient: FusedLocationProviderClient // For FusedLocationProvider API
private lateinit var locRequest : LocationRequest // Parameters for FusedLocationProvider
// Callback for changes in location
private lateinit var locCallback: LocationCallback
private lateinit var serviceHandler : Handler

private lateinit var notificationManager : NotificationManager // Notification Manager
private lateinit var loc : Location // The current location

// The identifier for the notification displayed for the foreground service
private val NOTIFICATION_ID = 12345678

// Set up when the service is created
override fun onCreate()
{
    // An instance of Fused Location Provider Client
    fusedLocClient = LocationServices.getFusedLocationProviderClient(this)

    // Obtains location callback
    locCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult?) {
            super.onLocationResult(locationResult)
            loc = locationResult!!.getLastLocation() // Obtains last location

            // Send location information to any broadcast receivers
            val intention = Intent(ACTION_BROADCAST)
            intention.putExtra("Coordinates", locationResult!!.getLastLocation())
            intention.putExtra("Address", getAddress(locationResult))
            intention.putExtra("Time", SimpleDateFormat("MM/dd/yyyy 'at' HH:mm").format(Date()))
            LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intention)

            // Change notification content if the service is running in the foreground
            if (serviceIsRunningInForeground(this@LocService))
            {
                notificationManager.notify(NOTIFICATION_ID, getNotification())
            }
        }
    }

    // Create location request and get the last location
    getLastLocation()
    buildLocReq()

    // Creates a HandlerThread, which is an extension of Thread and works
    // with a Looper, meaning it's meant to handle multiple jobs in the background
    // thread. The Looper is what keeps the thread alive. Notification Manager
    // is there to notify the user of the notification service
    val handlerThread = HandlerThread(TAG)
    handlerThread.start()
    serviceHandler = Handler(handlerThread.getLooper())
    notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
}

// Called whenever the client starts the service using startService()
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    val startedFromNotification = intent!!.getBooleanExtra(EXTRA_STARTED_FROM_NOTIFICATION, false)

    return START_NOT_STICKY // Don't recreate the service after it's killed
}

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    changingConfig = true
}

// Called when the client comes to the foreground and binds
// with this service. The service will stop being a foreground
// service when that happens
override fun onBind(intent: Intent): IBinder {
    stopForeground(true)
    changingConfig = false
    return binder
}

// Called when the client returns to the foreground
// and binds once again with this service. The service will
// stop being a foreground service when that happens
override fun onRebind(intent: Intent?) {
    stopForeground(true)
    changingConfig = false
    super.onRebind(intent)
}

// Called when the client unbinds with the service. If it's called
// with a configuration change, do nothing. Otherwise, make the service
// a foreground service
override fun onUnbind(intent: Intent?): Boolean {
    if (!changingConfig && requestingLocationUpdates(this))
    {
        startForeground(NOTIFICATION_ID, getNotification())
    }

    return true
}

// Called when service is destroyed
override fun onDestroy() {
    serviceHandler.removeCallbacksAndMessages(null)
}

inner class LocalBinder : Binder()
{
    fun getService() : LocService
    {
        return this@LocService
    }
}

// For obtaining location request
private fun buildLocReq()
{
    // Create a location request to store parameters for the requests
    locRequest = LocationRequest.create()

    // Sets priority, interval, and --smallest displacement-- for requests
    locRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
    locRequest.interval = 5000
    // locRequest.smallestDisplacement = 10f
}

private fun getLastLocation() {
    try
    {
        fusedLocClient.getLastLocation()
            .addOnCompleteListener(object:OnCompleteListener<Location>
            {
                override fun onComplete(@NonNull task:Task<Location>) {
                    if (task.isSuccessful() && task.getResult() != null)
                    {
                        loc = task.getResult() as Location
                    }
                    else
                    {
                        Log.w(TAG, "Failed to get location.")
                    }
                }
            })
    }
    catch (unlikely:SecurityException) {
        Log.e(TAG, "Lost location permission." + unlikely)
    }
}

fun requestLocationUpdates()
{
    setRequestingLocationUpdates(this, true)
    startService(Intent(getApplicationContext(), LocService::class.java))

    try
    {
        fusedLocClient.requestLocationUpdates(locRequest, locCallback, Looper.myLooper())
    } catch (unlikely:SecurityException)
    {
        setRequestingLocationUpdates(this, false)
        Log.e(TAG, "Lost location permission. Couldn't request updates. " + unlikely)
    }
}

// Obtain address via GeoCoder class
private fun getAddress(locResult: LocationResult?): String {
    var address = ""
    var geoCoder = Geocoder(this, Locale.getDefault())

    var loc1 = locResult!!.locations.get(locResult.locations.size-1)

    try {
        var addresses:ArrayList<Address> = geoCoder.getFromLocation(loc1.latitude, loc1.longitude, 1) as ArrayList<Address>
        address = addresses.get(0).getAddressLine(0)
    } catch (e: IOException) {
        e.printStackTrace()
    }

    return address
}

private fun getNotification(): Notification {
    val intent = Intent(this, LocService::class.java)

    val text = getLocationText(loc)

    val builder = NotificationCompat.Builder(this)
        .setContentText(text)
        .setOngoing(true)
        .setPriority(Notification.PRIORITY_HIGH)
        .setTicker(text)
        .setWhen(System.currentTimeMillis())

    return builder.build()
}

// Checks to see if the service is running in the foreground or not
fun serviceIsRunningInForeground(context: Context) : Boolean
{
    val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager

    for (service in manager.getRunningServices(Integer.MAX_VALUE))
    {
        if (javaClass.getName().equals(service.service.getClassName()))
        {
            if (service.foreground)
            {
                return true
            }
        }
    }

    return false
}

val KEY_REQUESTING_LOCATION_UPDATES = "requesting_locaction_updates"

// Returns true if the requesting location updates, else false
fun requestingLocationUpdates(context: Context): Boolean {
    return PreferenceManager.getDefaultSharedPreferences(context)
        .getBoolean(KEY_REQUESTING_LOCATION_UPDATES, false)
}

// Stores the location updates state in SharedPreferences
fun setRequestingLocationUpdates(context: Context, requestingLocationUpdates: Boolean)
{
    PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(KEY_REQUESTING_LOCATION_UPDATES, requestingLocationUpdates).apply()
}

// Returns the coordinates as a string for the notifications
fun getLocationText(loc: Location) : String
{
    if (loc == null) {
        return "Unknown Location"
    } else {
        return "Latitude: " + loc.longitude.toString() + " | Longitude: " + loc.longitude.toString()
    }
}
}
class-LocService:Service(){
private val PACKAGE_NAME=“com.example.localization”
private val TAG=LocService::class.java!!.getSimpleName()
val ACTION_BROADCAST=包名称+“.BROADCAST”
private val EXTRA_从_通知启动=包名称+“。从_通知启动”
//返回服务的当前实例
private val binder=LocalBinder()
//检查有界活动是否已实际消失
//而不是作为方向更改的一部分解除绑定
私有变量changingConfig=false
私有lateinit var fusedLocationClient:FusedLocationProviderClient//For fusedLocationProviderAPI
私有lateinit var locRequest:LocationRequest//FusedLocationProvider的参数
//位置更改的回调
私有lateinit var locCallback:LocationCallback
私有lateinit var serviceHandler:处理程序
私有lateinit var notificationManager:notificationManager//notificationManager
私有lateinit var loc:位置//当前位置
//为前台服务显示的通知的标识符
私人val通知_ID=12345678
//在创建服务时设置
重写fun onCreate()
{
//融合位置提供程序客户端的实例
FusedLocationClient=LocationServices.getFusedLocationProviderClient(此)
//获取位置回调
locCallback=object:LocationCallback(){
覆盖趣味onLocationResult(locationResult:locationResult?){
super.onLocationResult(位置结果)
loc=locationResult!!.getLastLocation()//获取最后一个位置
//向任何广播接收器发送位置信息
val意向=意向(行动和广播)
intention.putExtra(“坐标”,locationResult!!.getLastLocation())
意向。putExtra(“地址”,getAddress(locationResult))
intention.putExtra(“时间”,SimpleDateFormat(“MM/dd/yyyy”at'HH:MM”)。格式(Date())
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(意图)
//如果服务在前台运行,请更改通知内容
如果(服务正在运行前台)(this@LocService))
{
notificationManager.notify(NOTIFICATION\u ID,getNotification())
}
}
}
//创建位置请求并获取最后一个位置
getLastLocation()
buildLocReq()
//创建HandlerThread,它是Thread和works的扩展
//带有活套,意味着它可以在后台处理多个作业
//线程。循环器是保持线程活动的工具。通知管理器
//是否有通知服务通知用户
val handlerThread=handlerThread(标记)
handlerThread.start()
serviceHandler=Handler(handlerThread.getLooper())
notificationManager=getSystemService(通知服务)作为notificationManager
}
//每当客户端使用startService()启动服务时调用
覆盖启动命令(intent:intent?,标志:Int,startId:Int):Int{
val startedFromNotification=intent!!.getBooleanExtra(从通知开始的额外内容,false)
return START\u NOT\u STICKY//停止服务后不要重新创建服务
}
覆盖配置更改(newConfig:Configuration){
super.onConfigurationChanged(newConfig)
changingConfig=true
}
//当客户端到达前台并绑定时调用
//使用此服务。该服务将不再是前台
//发生这种情况时提供服务
覆盖有趣的onBind(意图:意图):IBinder{
停止前景(真)
changingConfig=false
回程活页夹
}
//当客户端返回前台时调用
//并再次绑定此服务。该服务将
//当这种情况发生时,停止成为前台服务
覆盖重新绑定的乐趣(意图:意图?){
停止前景(真)
changingConfig=false
super.onRebind(意图)
}
//当客户端与服务解除绑定时调用。如果调用
//在配置更改时,不执行任何操作。否则,请创建服务
//前台服务
重写onUnbind(意图:意图?):布尔值{
如果(!changingConfig&&RequestingLocationUpdate(此))
{
startForeground(通知\u ID,getNotification())
}
返回真值
}
//当服务被破坏时调用
重写onDestroy(){
serviceHandler.removeCallbacksAndMessages(空)
}
内部类LocalBinder:Binder()
{
fun getService():LocService
{
返回this@LocService
}
}
//用于获取位置请求
私人娱乐buildLocReq()
{
//创建位置请求以存储请求的参数
locRequest=LocationRequest.create()
//设置请求的优先级、间隔和最小位移
locRequest.priority=LocationRequest.priority\u高精度
locRequest.interval=5000
//locRequest.smallestDisplacement=10f
}
私人娱乐getLastLocation(){
尝试
{
fusedLocClient.getLas
11-01 00:27:36.923 15995-15995/com.example.localization E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.localization, PID: 15995
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.localization/com.example.localization.MainActivity}: kotlin.KotlinNullPointerException
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2327)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
    at android.app.ActivityThread.-wrap11(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5417)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
 Caused by: kotlin.KotlinNullPointerException
    at com.example.localization.MainActivity.<init>(MainActivity.kt:40)
    at java.lang.Class.newInstance(Native Method)
    at android.app.Instrumentation.newActivity(Instrumentation.java:1067)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2317)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
    at android.app.ActivityThread.-wrap11(ActivityThread.java) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:5417) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
private var lservice: LocService
private var lservice: LocService?