我已使用待定意图启动广播接收器获取位置更新。
应用程序之前工作正常。
但从最近几个月开始就不管用了。
我检查并发现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
1条答案
按热度按时间but5z9lq1#
已更改
获取广播(上下文,32,意图,挂起意图.标志_IMMUTABLE或挂起意图.标志_UPDATE_CURRENT)
到
获取广播(上下文,32,意图,挂起意图.标志_可修改或挂起意图.标志_更新_当前)