位置更新接收器没有得到位置更新android

问题描述 投票:0回答:0

我已经使用挂起的意图来启动广播接收器获取位置更新。

app 之前运行良好。

但从最近几个月开始它停止工作了。

我检查并发现LocationReceiver.kt没有得到任何更新

class LocationReceiver : BroadcastReceiver() {
private var locationRepository: LocationRepository? = null
private var lastLocation: Location? = null
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
if (Utility.currentApiVersion \>= Build.VERSION_CODES.O) NotificationHandler.getInstance(context).updateNotification(action)
Log.d("locationslog",""+action)
Utility.appToastShort(context, "onReceive: "+action)
if (ACTION_LOCATION_UPDATES == action) {
val result = LocationResult.extractResult(intent)
if (result != null) {
val locations = result.locations
if (locationRepository == null) locationRepository =
LocationRepository.getInstance(context.applicationContext, Executors.newSingleThreadExecutor())
if (locations.size \> 0) {
if (locations.size == 1 && lastLocation != null && lastLocation!!.latitude == locations\[0\].latitude && lastLocation!!.latitude == locations\[0\].longitude) {
//already saved location
} else {
for (i in locations.indices) {
if (i == locations.size - 1) lastLocation = locations\[i\]
val curntLoc = locations\[i\]
//LatLng curntLatLng = new LatLng(curntLoc.getLatitude(), curntLoc.getLongitude());
locationRepository!!.insertLocation(
LocationPoint(
curntLoc.latitude,
curntLoc.longitude
)
)
}
if (Utility.currentApiVersion \>= Build.VERSION_CODES.O) NotificationHandler.getInstance( context).updateNotification(
Utils.getLocationText(lastLocation)
)
}
}
}
}
}

    companion object {
        const val ACTION_LOCATION_UPDATES = "ACTION_LOCATION_UPDATE"
    }

}
public class LocationUpdatesService extends Service {
private static final String PACKAGE_NAME = "dk.invoiceportal.mileage";
public static final String EXTRA_LOCATION = PACKAGE_NAME + ".location";
public static final String LAST_LOCATION = PACKAGE_NAME + ".lastlocation";
public static final String STOP_LOCATION = PACKAGE_NAME + ".stop";
private static final String TAG = LocationUpdatesService.class.getSimpleName();
private static final String EXTRA_STARTED_FROM_NOTIFICATION = PACKAGE_NAME + ".started_from_notification";
private static final int NOTIFICATION_ID = 2123;
private final IBinder mBinder = new LocalBinder();
private boolean mChangingConfiguration = false, tracking = false;
private Location mLocation;
private Context mContext;
private Activity activity;

    private LocationRepository locationRepository;
    private Thread thread;
    private NotificationHandler notificationHandler = null;
    public LocationUpdatesService() {
    }
    
    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public void onCreate() {
        getLocationRepository();
        notificationHandler = NotificationHandler.getInstance(this);
    
    }
    
    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "Service started");
        boolean startedFromNotification = false;
        if (intent != null)
            startedFromNotification = intent.getBooleanExtra(EXTRA_STARTED_FROM_NOTIFICATION,
                    false);
    
        // We got here because the user decided to remove location updates from the notification.
        if (startedFromNotification) {
            removeLocationUpdates();
            stopSelf();
        } else {
            getLocationRepository();
            if (notificationHandler == null)
                notificationHandler = NotificationHandler.getInstance(this);
            notificationHandler.activity = activity;
            startForeground(NOTIFICATION_ID, notificationHandler.getNotification(Utils.getLocationText(mLocation)));
        }
        // Tells the system to not try to recreate the service after it has been killed.
        return START_STICKY;
    }
    
    private void startWorkOnNewThread(GoogleMap mGoogleMap, final int start, final String event) {
        if (start == 1)
            locationRepository.startLocationUpdates();
        else if (start == 0) {
            locationRepository.stopLocationUpdates();
            tracking = false;
            if (notificationHandler != null)
                notificationHandler.cancelNotification();
            if (event.equalsIgnoreCase("stopself"))
                stopSelf();
        } else if (start == 2)
            locationRepository.getLastLocation(mGoogleMap, event);
    
        stopThread();
       /* thread = new Thread(new Runnable() {
            public void run() {
                if(start == 1)
                    locationRepository.startLocationUpdates(getApplicationContext());
               else if(start == 0)
                {
                    locationRepository.stopLocationUpdates(getApplicationContext());
                    if(event.equalsIgnoreCase("stopself"))
                        stopSelf();
                }
               else if(start ==2)
                    locationRepository.getLastLocation(event);
            }
        });
    
        thread.start();*/
    }
    
    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public void onTaskRemoved(Intent rootIntent) {
    
        //When remove app from background then start it again
        if (tracking)
            startForegroundService(new Intent(getApplicationContext(), LocationUpdatesService.class));
    
        super.onTaskRemoved(rootIntent);
    }
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mChangingConfiguration = true;
    }
    
    @Override
    public IBinder onBind(Intent intent) {
        // Called when a client (MapActivity in case of this sample) comes to the foreground
        // and binds with this service. The service should cease to be a foreground service
        // when that happens.
        Log.i(TAG, "in onBind()");
    
        stopForeground(true);
        mChangingConfiguration = false;
        return mBinder;
    }
    
    @Override
    public void onRebind(Intent intent) {
        // Called when a client (MapActivity in case of this sample) returns to the foreground
        // and binds once again with this service. The service should cease to be a foreground
        // service when that happens.
        Log.i(TAG, "in onRebind()");
    
        stopForeground(true);
        mChangingConfiguration = false;
        super.onRebind(intent);
    }
    
    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public boolean onUnbind(Intent intent) {
        Log.i(TAG, "Last client unbound from service");
    
        // Called when the last client (MapActivity in case of this sample) unbinds from this
        // service. If this method is called due to a configuration change in MapActivity, we
        // do nothing. Otherwise, we make this service a foreground service.
        if (!mChangingConfiguration && Utils.requestingLocationUpdates(this)) {
            Log.i(TAG, "Starting foreground service");
            if (notificationHandler == null) {
                notificationHandler = NotificationHandler.getInstance(this);
                notificationHandler.setNotificationManager();
            }
            notificationHandler.activity = activity;
            startForeground(NOTIFICATION_ID, notificationHandler.getNotification(Utils.getLocationText(mLocation)));
        }
        return true; // Ensures onRebind() is called when a client re-binds.
    }
    
    @RequiresApi(api = Build.VERSION_CODES.O)
    public void requestLocationUpdates() {
        Log.i(TAG, "Requesting location updates");
        tracking = true;
    
        startForegroundService(new Intent(getApplicationContext(), LocationUpdatesService.class));
    
        try {
            startWorkOnNewThread(null, 1, "");
        } catch (SecurityException unlikely) {
            Utils.setRequestingLocationUpdates(this, false);
            Log.e(TAG, "Lost location permission. Could not request updates. " + unlikely);
        }
    }
    
    public void getLastLocation(GoogleMap mGoogleMap, String event) {
    
        try {
            startWorkOnNewThread(mGoogleMap, 2, event);
    
        } catch (SecurityException unlikely) {
            Utils.setRequestingLocationUpdates(this, false);
            Log.e(TAG, "Lost location permission. Could not remove updates. " + unlikely);
        }
    }
    
    public void removeLocationUpdates() {
        Log.i(TAG, "Removing location updates");
        try {
            startWorkOnNewThread(null, 0, "stopself");
            //stopSelf();
        } catch (SecurityException unlikely) {
            Utils.setRequestingLocationUpdates(this, true);
            Log.e(TAG, "Lost location permission. Could not remove updates. " + unlikely);
        }
    }
    
    private LocationRepository getLocationRepository() {
        if (locationRepository == null)
            locationRepository = LocationRepository.Companion.getInstance(getApplicationContext(), Executors.newSingleThreadExecutor());
        return locationRepository;
    }
    
    private void stopThread() {
        if (thread != null)
            thread.interrupt();
    
        thread = null;
    }
    
    @Override
    public void onDestroy() {
    
        Utils.setRequestingLocationUpdates(this, false);
        if (notificationHandler != null)
            notificationHandler.destroy();
        notificationHandler = null;
        stopThread();
    }
    
    public class LocalBinder extends Binder {
        public LocationUpdatesService getService(Context context) {
            mContext = context;
            activity = (Activity) context;
            return LocationUpdatesService.this;
        }

}
}
class LocationHandler private constructor(private val context: Context ) {
private var mLocationRequest: LocationRequest? = null
private var mFusedLocationClient: FusedLocationProviderClient? = null
private val _receivingLocationUpdates: MutableLiveData<Boolean> = MutableLiveData<Boolean>(false)
val receivingLocationUpdates: LiveData<Boolean>
get() = _receivingLocationUpdates

    @SuppressLint("MissingPermission")
    fun startLocationUpdates() {
        if (!AppPermissions.checkPermissions(context, true)) {
            Utility.appToast(context, "Location permission not given or GPS is OFF")
            return
        } else {
            _receivingLocationUpdates.value = true
            if (mLocationRequest == null) createLocationRequest()
            Utils.setRequestingLocationUpdates(context, true)
            if (mFusedLocationClient == null) mFusedLocationClient =
                LocationServices.getFusedLocationProviderClient(
                    context
                )
            mFusedLocationClient!!.requestLocationUpdates(mLocationRequest!!, pendingIntent)
            Log.d("locationslog","startLocationUpdates")
            Utility.appToastShort(context, "startLocationUpdates")
        }
    }
    
    fun stopLocationUpdate() {
        if (mLocationRequest == null) createLocationRequest()
        if ( mFusedLocationClient != null) {
            mFusedLocationClient!!.removeLocationUpdates(pendingIntent)
        }
        Log.d("locationslog","stopLocationUpdate")
        Utils.setRequestingLocationUpdates(context, false)
        _receivingLocationUpdates.value = false
        Utility.appToastShort(context, "stopLocationUpdate")
    }
    
    private fun createLocationRequest() {
        mLocationRequest = LocationRequest.Builder(
            Priority.PRIORITY_HIGH_ACCURACY,
            UPDATE_INTERVAL_IN_MILLISECONDS
        )
            .setMinUpdateDistanceMeters(SMALLEST_DISTANCE_IN_METER)
            .setIntervalMillis(UPDATE_INTERVAL_IN_MILLISECONDS)
            .setMinUpdateIntervalMillis(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS)
            .setMaxUpdateDelayMillis(MAX_WAIT_TIME).setWaitForAccurateLocation(false)
            .setPriority(Priority.PRIORITY_HIGH_ACCURACY).build()
        displayGpsMessage()
    }
    
    // Note: for apps targeting API level 25 ("Nougat") or lower, either
    // PendingIntent.getService() or PendingIntent.getBroadcast() may be used when requesting
    // location updates. For apps targeting API level O, only
    // PendingIntent.getBroadcast() should be used. This is due to the limits placed on services
    // started in the background in "O".
    private val pendingIntent: PendingIntent
        get() {
            // Note: for apps targeting API level 25 ("Nougat") or lower, either
            // PendingIntent.getService() or PendingIntent.getBroadcast() may be used when requesting
            // location updates. For apps targeting API level O, only
            // PendingIntent.getBroadcast() should be used. This is due to the limits placed on services
            // started in the background in "O".
            val intent = Intent(LocationReceiver.ACTION_LOCATION_UPDATES)
            //intent.action = LocationReceiver.ACTION_LOCATION_UPDATES
            Utility.appToastShort(context, "intent:"+intent.action)
            Log.d("locationslog",""+intent.action)
            var p_intent = PendingIntent.getBroadcast(
                context,
                32,
                intent,
                PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
            )
            p_intent.send();
            return p_intent;
        }
    
    fun getLastLocation(mGoogleMap: GoogleMap?, event: String) {
        try {
            if (mLocationRequest == null) createLocationRequest()
            if (mFusedLocationClient == null) mFusedLocationClient =
                LocationServices.getFusedLocationProviderClient(
                    context
                )
            // _receivingLocationUpdates = true;
            Utils.setRequestingLocationUpdates(context, true)
            mFusedLocationClient!!.lastLocation
                .addOnCompleteListener { task ->
                    if (task.isSuccessful && task.result != null) {
                        val mLocation = task.result
                        if (mLocation != null) {
                            if (event.equals(
                                    LocationUpdatesService.LAST_LOCATION,
                                    ignoreCase = true
                                )
                            ) {
                                if (mGoogleMap != null) Utility.setMapCammera(
                                    mGoogleMap,
                                    LatLng(mLocation.latitude, mLocation.longitude)
                                )
                            } else {
                                val loc = LocationPoint(mLocation.latitude, mLocation.longitude)
                                LocationRepository.getInstance(
                                    context.applicationContext,
                                    Executors.newSingleThreadExecutor()
                                ).insertLocation(loc)
                                if (Utility.currentApiVersion >= Build.VERSION_CODES.O) NotificationHandler.getInstance(
                                    context
                                ).updateNotification(Utils.getLocationText(mLocation))
                            }
                            stopLocationUpdate()
                        } else Log.i("TAG", "Last location not null")
                    } else Log.i("TAG", "Last location not received")
                }.addOnFailureListener { e ->
                    e.printStackTrace()
                    Log.i("TAG", e.message!!)
                    stopLocationUpdate()
                }
        } catch (unlikely: SecurityException) {
            Log.e("TAG", "Lost location permission.$unlikely")
        }
    }
    
    fun displayGpsMessage() {
        if ( mLocationRequest != null) {
            val builder = LocationSettingsRequest.Builder()
            builder.addLocationRequest(mLocationRequest!!)
            val locationSettingsRequest = builder.build()
            val settingsClient = LocationServices.getSettingsClient(context)
            settingsClient.checkLocationSettings(locationSettingsRequest).addOnFailureListener(Utility.curentActivity
            ) { e ->
                val statusCode = (e as ApiException).statusCode
                when (statusCode) {
                    LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> try {
                        // Show the dialog by calling startResolutionForResult(), and check the
                        // result in onActivityResult().
                        val rae = e as ResolvableApiException
                        rae.startResolutionForResult(Utility.curentActivity , 1000)
                    } catch (sie: SendIntentException) {
                        Log.i("location", "PendingIntent unable to execute request.")
                    }
                    LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
                        val errorMessage = "Location settings are inadequate, and cannot be " +
                                "fixed here. Fix in Settings."
                        Log.e("location", errorMessage)
                    }
                }
            }
        }
    }
    
    companion object {
        private const val SMALLEST_DISTANCE_IN_METER = 5f//35f
        private const val UPDATE_INTERVAL_IN_MILLISECONDS = (9 * 1000).toLong()
    
        //private final Context mContext;
        private const val FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = (1 * 1000).toLong()
        private const val MAX_WAIT_TIME = (6000 * 3).toLong()//(60000 * 3).toLong()
        @Volatile private var INSTANCE: LocationHandler? = null
    
        fun getInstance(context: Context): LocationHandler {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: LocationHandler(context).also { INSTANCE = it }
            }
        }
    }

}
class LocationRepository private constructor(
    private val myDataBase: MyLocationDatabase,
    private val locationHandler: LocationHandler,
    private val executor: ExecutorService
) {
    // Database related fields/methods:
    private val locationDao = myDataBase.locationDao()

    fun insertLocation(location: LocationPoint?) {
        executor.execute { locationDao.insertLocation(location) }
    }
    fun fetchAllLocation(): LiveData<List<LocationPoint?>?>? {
         return locationDao.fetchAllLocation()
    }
    fun fetchAllLAddresses(): LiveData<List<SavedAddress?>?>? {
        return locationDao.fetchAllLAddresses()
    }
    fun insertSaveAddress(savedAddress: SavedAddress?) {
        executor.execute { locationDao.insertAddress(savedAddress) }
    }

    val locationsCount: Unit
        get() {
            executor.execute { locationDao.locationsCount }
        }
    val savedAddressCount: Unit
        get() {
            executor.execute { locationDao.savedAddressCount }
        }

    fun deleteLocation(locationPoint: LocationPoint?) {
        executor.execute { locationDao.deleteLocation(locationPoint) }
    }

    fun deleteSavedAddress(savedAddress: SavedAddress?) {
        executor.execute {locationDao.deleteSavedAddress(savedAddress) }
    }

    fun deleteSavedAddress(id: Int) {
        executor.execute { locationDao.deleteSavedAddress(id) }
    }

    fun deleteSavedAddress(address: String?) {
        executor.execute { locationDao.deleteSavedAddress(address) }
    }

    fun deleteAll() {
        executor.execute { locationDao.delete() }
    }

    fun getLastLocation(mGoogleMap: GoogleMap?, event: String?) { locationHandler.getLastLocation(mGoogleMap, event!!)
    }

    fun startLocationUpdates() {locationHandler.startLocationUpdates()
    }


    val receivingLocationUpdates: LiveData<Boolean> = locationHandler.receivingLocationUpdates

    @MainThread
    fun stopLocationUpdates() {
       locationHandler.stopLocationUpdate()
    }

    companion object {
        @Volatile private var INSTANCE: LocationRepository? = null

        fun getInstance(context: Context, executor: ExecutorService): LocationRepository {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: LocationRepository(
                    MyLocationDatabase.getInstance(context),
                    LocationHandler.getInstance(context),executor)
                    .also { INSTANCE = it }
            }
        }
    }
}

清单文件

<service
            android:name=".services.LocationUpdatesService"
            android:enabled="true"
            android:exported="true"
            android:foregroundServiceType="location" /\>

        <receiver
            android:name=".services.LocationReceiver"
            android:enabled="true"
            android:exported="true"
            android:permission="android.permission.ACCESS_BACKGROUND_LOCATION">
            <intent-filter>
                <action android:name="ACTION_LOCATION_UPDATE" />
            </intent-filter>
        </receiver>

我已经更新了库 gradle 和目标 sdk 是 33。minumm 是 24

android location broadcastreceiver location-updates live-tracking
© www.soinside.com 2019 - 2024. All rights reserved.