Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fatal Exception #180

Closed
ir4ever opened this issue Feb 7, 2023 · 7 comments
Closed

Fatal Exception #180

ir4ever opened this issue Feb 7, 2023 · 7 comments

Comments

@ir4ever
Copy link

ir4ever commented Feb 7, 2023

[log] LatLng(-21.134187, -41.6647957)
D/AndroidRuntime( 6087): Shutting down VM
E/AndroidRuntime( 6087): FATAL EXCEPTION: main
E/AndroidRuntime( 6087): Process: com.cbta.app, PID: 6087
E/AndroidRuntime( 6087): java.lang.IncompatibleClassChangeError: Found interface com.google.android.gms.location.FusedLocationProviderClient, but class was expected (declaration of 'com.google.android.gms.location.FusedLocationProviderClient' appears in /data/app/com.cbta.app-mNVxt2IYd1DX0ac4TRiGCQ==/base.apk)
E/AndroidRuntime( 6087): at com.almoullim.background_location.LocationUpdatesService.getLastLocation(LocationUpdatesService.kt:188)
E/AndroidRuntime( 6087): at com.almoullim.background_location.LocationUpdatesService.onCreate(LocationUpdatesService.kt:125)
E/AndroidRuntime( 6087): at android.app.ActivityThread.handleCreateService(ActivityThread.java:4400)
E/AndroidRuntime( 6087): at android.app.ActivityThread.access$1800(ActivityThread.java:274)
E/AndroidRuntime( 6087): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2118)
E/AndroidRuntime( 6087): at android.os.Handler.dispatchMessage(Handler.java:107)
E/AndroidRuntime( 6087): at android.os.Looper.loop(Looper.java:237)
E/AndroidRuntime( 6087): at android.app.ActivityThread.main(ActivityThread.java:8167)
E/AndroidRuntime( 6087): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 6087): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
E/AndroidRuntime( 6087): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
I/Process ( 6087): Sending signal. PID: 6087 SIG: 9
Lost connection to device.

@ir4ever
Copy link
Author

ir4ever commented Feb 8, 2023

Add this permission in manifest:

Change play-services-location for this version in build.gradlew:
implementation 'com.google.android.gms:play-services-location:21.0.0'

Change LocationUpdateService for this:

package com.almoullim.background_location

import android.annotation.SuppressLint
import android.app.*
import android.location.*
import android.location.LocationListener
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.*
import androidx.core.app.NotificationCompat
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.google.android.gms.location.*
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.common.*

class LocationUpdatesService : Service() {

private var forceLocationManager: Boolean = false

override fun onBind(intent: Intent?): IBinder {
    val distanceFilter = intent?.getDoubleExtra("distance_filter", 0.0)
    if (intent != null) {
        forceLocationManager = intent.getBooleanExtra("force_location_manager", false)
    }
    if (distanceFilter != null) {
        createLocationRequest(distanceFilter)
    } else {
        createLocationRequest(0.0)
    }
    return mBinder
}

private val mBinder = LocalBinder()
private var mNotificationManager: NotificationManager? = null
private var mLocationRequest: LocationRequest? = null
private var mFusedLocationClient: FusedLocationProviderClient? = null
private var mLocationManager: LocationManager? = null
private var mFusedLocationCallback: LocationCallback? = null
private var mLocationManagerCallback: LocationListener? = null
private var mLocation: Location? = null
private var isGoogleApiAvailable: Boolean = false
private var isStarted: Boolean = false

companion object {
    var NOTIFICATION_TITLE = "Background service is running"
    var NOTIFICATION_MESSAGE = "Background service is running"
    var NOTIFICATION_ICON = "@mipmap/ic_launcher"

    private const val PACKAGE_NAME = "com.google.android.gms.location.sample.locationupdatesforegroundservice"
    private val TAG = LocationUpdatesService::class.java.simpleName
    private const val CHANNEL_ID = "channel_01"
    internal const val ACTION_BROADCAST = "$PACKAGE_NAME.broadcast"
    internal const val EXTRA_LOCATION = "$PACKAGE_NAME.location"
    private const val EXTRA_STARTED_FROM_NOTIFICATION = "$PACKAGE_NAME.started_from_notification"
    var UPDATE_INTERVAL_IN_MILLISECONDS: Long = 1000
    var FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2
    private const val NOTIFICATION_ID = 12345678
    private lateinit var broadcastReceiver: BroadcastReceiver

    private const val STOP_SERVICE = "stop_service"
}


private val notification: NotificationCompat.Builder
    @SuppressLint("UnspecifiedImmutableFlag")
    get() {

        val intent = Intent(this, getMainActivityClass(this))
        intent.putExtra(EXTRA_STARTED_FROM_NOTIFICATION, true)
        intent.action = "Localisation"
        //intent.setClass(this, getMainActivityClass(this))
        val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
        } else {
            PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT)
        }


        val builder = NotificationCompat.Builder(this, "BackgroundLocation")
                .setContentTitle(NOTIFICATION_TITLE)
                .setOngoing(true)
                .setSound(null)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setSmallIcon(resources.getIdentifier(NOTIFICATION_ICON, "mipmap", packageName))
                .setWhen(System.currentTimeMillis())
                .setStyle(NotificationCompat.BigTextStyle().bigText(NOTIFICATION_MESSAGE))
                .setContentIntent(pendingIntent)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            builder.setChannelId(CHANNEL_ID)
        }

        return builder
    }

private var mServiceHandler: Handler? = null

override fun onCreate() {
    val googleAPIAvailability = GoogleApiAvailability.getInstance()
        .isGooglePlayServicesAvailable(applicationContext)
    
    isGoogleApiAvailable = googleAPIAvailability == ConnectionResult.SUCCESS
    

    if (isGoogleApiAvailable && !this.forceLocationManager) {
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
        
        mFusedLocationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult) {
                super.onLocationResult(locationResult!!)
                onNewLocation(locationResult!!.lastLocation!!)
            }
        }
    } else {
        mLocationManager = getSystemService(LOCATION_SERVICE) as LocationManager?

        mLocationManagerCallback = LocationListener { location ->
            println(location.toString())
            onNewLocation(location)
        }
    }

    getLastLocation()

    val handlerThread = HandlerThread(TAG)
    handlerThread.start()
    mServiceHandler = Handler(handlerThread.looper)

    mNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val name = "Application Name"
        val mChannel = NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_LOW)
        mChannel.setSound(null, null)
        mNotificationManager!!.createNotificationChannel(mChannel)
    }

    broadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            if (intent?.action == "stop_service") {
                removeLocationUpdates()
            }
        }
    }

    val filter = IntentFilter()
    filter.addAction(STOP_SERVICE)
    registerReceiver(broadcastReceiver, filter)

    updateNotification() // to start the foreground service
}


fun requestLocationUpdates() {
    Utils.setRequestingLocationUpdates(this, true)
    try {
        if (isGoogleApiAvailable && !this.forceLocationManager) {
            mFusedLocationClient!!.requestLocationUpdates(mLocationRequest!!,
                mFusedLocationCallback!!, Looper.myLooper())
        } else {
            mLocationManager?.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0L, 0f, mLocationManagerCallback!!)
        }
    } catch (unlikely: SecurityException) {
        Utils.setRequestingLocationUpdates(this, false)
    }
}

fun updateNotification() {
    if (!isStarted) {
        isStarted = true
        startForeground(NOTIFICATION_ID, notification.build())
    } else {
        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.notify(NOTIFICATION_ID, notification.build())
    }
}

fun removeLocationUpdates() {
    stopForeground(true)
    stopSelf()
}


private fun getLastLocation() {
    try {
        if(isGoogleApiAvailable && !this.forceLocationManager) {
            mFusedLocationClient!!.lastLocation
                    .addOnCompleteListener { task ->
                        if (task.isSuccessful && task.result != null) {
                            mLocation = task.result
                        }
                    }
        } else {
            mLocation = mLocationManager!!.getLastKnownLocation(LocationManager.GPS_PROVIDER)
        }
    } catch (unlikely: SecurityException) {
    }
}

private fun onNewLocation(location: Location) {
    mLocation = location
    val intent = Intent(ACTION_BROADCAST)
    intent.putExtra(EXTRA_LOCATION, location)
    LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(intent)
}


private fun createLocationRequest(distanceFilter: Double) {
    mLocationRequest = LocationRequest()
    mLocationRequest!!.interval = UPDATE_INTERVAL_IN_MILLISECONDS
    mLocationRequest!!.fastestInterval = FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS
    mLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
    mLocationRequest!!.smallestDisplacement = distanceFilter.toFloat()
}


inner class LocalBinder : Binder() {
    internal val service: LocationUpdatesService
        get() = this@LocationUpdatesService
}


override fun onDestroy() {
    super.onDestroy()
    isStarted = false
    unregisterReceiver(broadcastReceiver)
    try {
        if (isGoogleApiAvailable && !this.forceLocationManager) {
            mFusedLocationClient!!.removeLocationUpdates(mFusedLocationCallback!!)
        } else {
            mLocationManager!!.removeUpdates(mLocationManagerCallback!!)
        }

        Utils.setRequestingLocationUpdates(this, false)
        mNotificationManager!!.cancel(NOTIFICATION_ID)
    } catch (unlikely: SecurityException) {
        Utils.setRequestingLocationUpdates(this, true)
    }
}

private fun getMainActivityClass(context: Context): Class<*>? {
    val packageName = context.packageName
    val launchIntent = context.packageManager.getLaunchIntentForPackage(packageName)
    val className = launchIntent?.component?.className ?: return null

    return try {
        Class.forName(className)
    } catch (e: ClassNotFoundException) {
        e.printStackTrace()
        null
    }
}

}

@ir4ever
Copy link
Author

ir4ever commented Feb 8, 2023

Temporary solution:
set in app/build.gradle
implementation 'com.google.android.gms:play-services-location:21.0.0'

@rromaniz
Copy link

Temporary solution: set in app/build.gradle implementation 'com.google.android.gms:play-services-location:21.0.0'

it works, thank you

@opadasaeed
Copy link

Temporary solution: set in app/build.gradle implementation 'com.google.android.gms:play-services-location:21.0.0'

didn't work with me

@ir4ever
Copy link
Author

ir4ever commented Mar 8, 2023

Downgrade to version:
implementation 'com.google.android.gms:play-services-location:20.0.0'
Set in pubspec.yaml:
dependency_overrides:
geolocator_android: "4.1.4"

@bryanepoolm
Copy link

#180 (comment)

A mí me funcionó, llevaba horas en el problema.
En tu archivo android/app/build.gradle:

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.google.android.gms:play-services-location:21.0.0'
}

La ruta del archivo que menciona la solución que me funcionó a mí fue /Users/Bryan/Development/flutter/.pub-cache/hosted/pub.dartlang.org/background_location-0.8.1/android/src/main/kotlin/com/almoullim/background_location/LocationUpdatesService.kt

@MoralCode
Copy link
Collaborator

Change play-services-location for this version in build.gradlew:
implementation 'com.google.android.gms:play-services-location:21.0.0'

It appears as though this change was made in this line of PR #183: https://github.com/Almoullim/background_location/pull/183/files#diff-197b190e4a3512994d2cebed8aff5479ff88e136b8cc7a4b148ec9c3945bd65aL54

This leads me to believe this issue has been resolved as of release 0.10.0 which is on the master branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants