无法在我的Service类中使用MainActivity的方法。

huangapple go评论56阅读模式
英文:

Not able to use a method of MainActivity in my Service Class in Android Kotlin

问题

我在制作一个SOS应用程序,在其中我在MainActivity类中定义了一个函数(sendSOS())来获取用户位置并发送短信给保存的联系人。现在我创建了一个传感器服务类,用于检测摇晃事件并在前台运行,当发生摇晃时,它应该再次调用(sendSOS())方法。但它没有正常工作。
以下是错误和代码。如何实现它的任何指导都将不胜感激。

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
    at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:135)
    at com.google.android.gms.common.api.GoogleApi.<init>(com.google.android.gms:play-services-base@@18.1.0:7)
    at com.google.android.gms.common.api.GoogleApi.<init>(com.google.android.gms:play-services-base@@18.1.0:1)
    at com.google.android.gms.internal.location.zzbp.<init>(com.google.android.gms:play-services-location@@21.0.1:1)
    at com.google.android.gms.location.LocationServices.getFusedLocationProviderClient(com.google.android.gms:play-services-location@@21.0.1:1)
    at com.chrizlove.helpapp.MainActivity.sendSOS(MainActivity.kt:142)
    at com.chrizlove.helpapp.SensorService$onCreate$1.onShake(SensorService.kt:67)
    at com.chrizlove.helpapp.ShakeDetector.onSensorChanged(ShakeDetector.kt:51)

将在设备摇晃时用于调用MainActivity的sendSOS()的SensorService代码部分。

override fun onShake(count: Int) {
    // 检查用户是否连续摇晃手机3次
    if (count == 3) {

        // 震动手机
        vibrate()

        // 在这里我想调用MainActivity中的sendSos方法
        val mActivity = MainActivity()
        mActivity.sendSOS(applicationContext)
        Toast.makeText(applicationContext, "Shaken", Toast.LENGTH_SHORT).show()
    }
}

MainActivity中的sendSOS()方法以及用于其运行的其他方法。

fun sendSOS(context: Context) {
    fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
    getCurrentLocationAndSendSMS(context)
}

private fun sendSMS() {
    // 发送短信
    // ...
}

private fun requestSMSPermission() {
    // 请求短信权限
    // ...
}

private fun checkSMSPermission(context: Context): Boolean {
    // 检查短信权限
    // ...
}

fun getCurrentLocationAndSendSMS(context: Context) {
    // 获取当前位置并发送短信
    // ...
}

companion object {
    private const val PERMISSION_REQUEST_ACCESS_LOCATION = 100
    private const val PERMISSION_REQUEST_SMS = 99
}

private fun requestLocationPermission() {
    // 请求位置权限
    // ...
}

private fun locationEnabled(): Boolean {
    // 检查位置是否启用
    // ...
}

private fun checkLocationPermission(context: Context): Boolean {
    // 检查位置权限
    // ...
}

如果需要其他信息,请提出,获取任何关于如何实现它的线索将非常有帮助。

此问题解释了并提供了解决此问题的解决方案:https://stackoverflow.com/questions/14896574/how-to-call-a-method-in-activity-from-a-service

英文:

I am making an SOS app, where I have defined a function in mainactivty ( sendSOS() ) class that gets user location and sends a sms to contacts saved. Now i have created a sensor service class that detects a shake event and runs in foreground, and when a shake happens it is supposed to again invoke the (sendSOS() ) method. But its not working properly.
Below is the error and code. Any guidance on how to implement it would be appreciated.

java.lang.NullPointerException: Attempt to invoke virtual method &#39;android.content.Context android.content.Context.getApplicationContext()&#39; on a null object reference
                                                                                                	at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:135)
                                                                                                	at com.google.android.gms.common.api.GoogleApi.&lt;init&gt;(com.google.android.gms:play-services-base@@18.1.0:7)
                                                                                                	at com.google.android.gms.common.api.GoogleApi.&lt;init&gt;(com.google.android.gms:play-services-base@@18.1.0:1)
                                                                                                	at com.google.android.gms.internal.location.zzbp.&lt;init&gt;(com.google.android.gms:play-services-location@@21.0.1:1)
                                                                                                	at com.google.android.gms.location.LocationServices.getFusedLocationProviderClient(com.google.android.gms:play-services-location@@21.0.1:1)
                                                                                                	at com.chrizlove.helpapp.MainActivity.sendSOS(MainActivity.kt:142)
                                                                                                	at com.chrizlove.helpapp.SensorService$onCreate$1.onShake(SensorService.kt:67)
                                                                                                	at com.chrizlove.helpapp.ShakeDetector.onSensorChanged(ShakeDetector.kt:51)

The SensorService code part which will be used to call the sendSOS() of MainActivty when device is shaken.

override fun onShake(count: Int) {
            // check if the user has shacked
            // the phone for 3 time in a row
            if (count == 3) {

                // vibrate the phone
                vibrate()

                //here i want to call the sendSos method that is in the mainActivity
                val mActivity = MainActivity()
                mActivity.sendSOS(applicationContext)
                Toast.makeText(applicationContext,&quot;Shaken&quot;, Toast.LENGTH_SHORT).show()
            }
        }

The MainActivity sendSOS() method along with rest of the methods used for its functioning.

public fun sendSOS(context: Context) {
        fusedLocationProviderClient=LocationServices.getFusedLocationProviderClient(this)
        getCurrentLocationAndSendSMS(context)
}

private fun sendSMS() {
    Log.d(TAG,&quot;2&quot;)
    if(checkSMSPermission(this)){
        val smsManager: SmsManager
        smsManager = SmsManager.getDefault()
        for (contact in contactViewModel.contacts.value!!){
            smsManager.sendTextMessage(contact.c_number, null,
                &quot;Hi, I am in an emergency! This is my location https://www.google.com/maps/?q=&quot;+location.latitude+&quot;,&quot;+location.longitude,
                null, null)
        }
        Toast.makeText(applicationContext,&quot;SMS Sent&quot;,Toast.LENGTH_SHORT).show()
    }
    else{
        requestSMSPermission()
    }
}

private fun requestSMSPermission() {
    ActivityCompat.requestPermissions(this,
        arrayOf(Manifest.permission.SEND_SMS), PERMISSION_REQUEST_SMS)
}

private fun checkSMSPermission(context: Context): Boolean {
    return ActivityCompat.checkSelfPermission(context,Manifest.permission.SEND_SMS)==PackageManager.PERMISSION_GRANTED
}

public fun getCurrentLocationAndSendSMS(context: Context) {
    Log.d(TAG,&quot;1&quot;)
    if(checkLocationPermission(context)){
       if(locationEnabled()){
            fusedLocationProviderClient.lastLocation.addOnCompleteListener(this) {task-&gt;
                location=task.result
                if(location==null){
                //do something later on
                }
                else{
                    //SEND sms when gotten location
                    sendSMS()
                }
            }
        }
        else{
            //send last known location
        }
    }
    else{
        //request permission
        requestLocationPermission()
    }
}

companion object{
    private const val PERMISSION_REQUEST_ACCESS_LOCATION=100
    private const val  PERMISSION_REQUEST_SMS=99
}

private fun requestLocationPermission() {
        ActivityCompat.requestPermissions(this,
            arrayOf( Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION),
            PERMISSION_REQUEST_ACCESS_LOCATION)

}

private fun locationEnabled(): Boolean {
    val locationManager: LocationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
    return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
}


private fun checkLocationPermission(context: Context): Boolean {
    if(ActivityCompat.checkSelfPermission(context,Manifest.permission.ACCESS_COARSE_LOCATION)==PackageManager.PERMISSION_GRANTED
        &amp;&amp; ActivityCompat.checkSelfPermission(context,Manifest.permission.ACCESS_FINE_LOCATION)==PackageManager.PERMISSION_GRANTED)
    {
        return true
    }
    return false
}

If anything else is needed just ask, it would be very helpful to get any sort of lead as to how to implement it.

This question explains and and provides the solution to this provlem:---https://stackoverflow.com/questions/14896574/how-to-call-a-method-in-activity-from-a-service

答案1

得分: 2

<strike>方法1:
要从MainActivity调用方法,您需要在SensorService的onShake()函数中编写如下代码:

(applicationContext as MainActivity).sendSOS(applicationContext)

</strike>
<br>

方法2:

您可以使用BroadcastReceiver从服务中获取数据。

在MainActivity中添加sosReceiver来调用sendSos函数:

private val sosReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        sendSOS(context)
    }
}

在MainActivity的onCreate函数中接收广播:

registerReceiver(sosReceiver, IntentFilter.create(SensorService.ACTION_SOS_SEND, null))

然后在MainActivity的onDestroy()函数中取消注册广播接收器:

override fun onDestroy() {
    super.onDestroy()
    unregisterReceiver(sosReceiver)
}

在SensorService中发送广播:

override fun onShake(count: Int) {
        if (count == 3) {
            // other code
            val sosIntent = Intent(ACTION_SOS_SEND)
            this.sendBroadcast(sosIntent)
        }
    }

companion object {
    const val ACTION_SOS_SEND = &quot;com.company.package.ACTION_SOS_SEND&quot;
}

注意:您不能创建Activities的实例,包括MainActivity。Android本身负责此任务

英文:

<strike>Method 1:
To call method from MainActivty you need to write this in SensorService in onShake():

(applicationContext as MainActivity).sendSOS(applicationContext)

</strike>
<br>

Method 2:

You can use BroadcastReceiver to get data from Services.

In your MainActivity add sosReceiver which calls sendSos function:

private val sosReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        sendSOS(context)
    }
}

To receive broadcasts in your MainActivity in onCreate function add:

registerReceiver(sosReceiver, IntentFilter.create(SensorService.ACTION_SOS_SEND, null))

And then in onDestroy() function in MainActivity unregister receiver:

override fun onDestroy() {
    super.onDestroy()
    unregisterReceiver(sosReceiver)
}

In SensorService to send a broadcast:

override fun onShake(count: Int) {
        if (count == 3) {
            // other code
            val sosIntent = Intent(ACTION_SOS_SEND)
            this.sendBroadcast(sosIntent)
        }
    }

companion object {
    const val ACTION_SOS_SEND = &quot;com.company.package.ACTION_SOS_SEND&quot;
}

NOTE: You can not create instance of Activities including MainActivity. Android itself is responsible for this task

huangapple
  • 本文由 发表于 2023年5月28日 17:44:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76350855.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定