gpt4 book ai didi

java - 如何在后台接收位置更新? (API 26)

转载 作者:行者123 更新时间:2023-11-29 08:27:39 26 4
gpt4 key购买 nike

我的应用程序需要从应用程序获取持续的位置更新。为此,我遵循了 Android Developer Guide获取位置更新。因为在 API 26 中无法在后台接收位置更新,所以我添加了一个前台服务 ( Background location limits )。但是,我仍然只在前台有其他请求位置更新的 Activity 时才收到更新。

定位服务:

public class LocationUpdateService extends Service {

private static final String TAG = LocationUpdateService.class.getSimpleName();

private static final String NOTIFICATION_CHANNEL_ID = "TrackNotification";
private static final int FOREGROUND_SERVICE_ID = 1;
private static final int NOTIFICATION_ID = 1;
public static final String STATUS_INTENT = "status";
private static final int CONFIG_CACHE_EXPIRY = 600;

private NotificationManager mNotificationManager;
private NotificationCompat.Builder mNotificationBuilder;

private DatabaseReference mDatabaseReference;

private FusedLocationProviderClient mFusedLocationProviderClient;
private LocationRequest mLocationRequest;

private FirebaseRemoteConfig mFirebaseRemoteConfig;

private String uid;

@Override
public void onCreate() {
super.onCreate();

uid = FirebaseAuth.getInstance().getUid();
if(uid == null)
stopSelf();

mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder().build();
mFirebaseRemoteConfig.setConfigSettings(configSettings);
mFirebaseRemoteConfig.setDefaults(R.xml.remode_config_defaults);
fetchRemoteConfig();

mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
mDatabaseReference = FirebaseDatabase.getInstance().getReference();

mLocationRequest = new LocationRequest()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setFastestInterval(mFirebaseRemoteConfig.getLong("LOCATION_REQUEST_INTERVAL"))
.setFastestInterval(mFirebaseRemoteConfig.getLong("LOCATION_REQUEST_INTERVAL_FASTEST"));

bindNotification();
setStatusMessage(R.string.connecting);


startLocationTracking();
}

private LocationCallback mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
Log.d(TAG,"Got location update!");
if(locationResult == null)
return;
for(Location location : locationResult.getLocations()) {

CustomLocation customLocation = LocationAdapter.toDatabaseLocation(location);
mDatabaseReference.child("locations").child(uid).setValue(customLocation);
}

}

@Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
locationAvailability.isLocationAvailable();
// TODO handle no location here
super.onLocationAvailability(locationAvailability);
}
};

@SuppressWarnings({"MissingPermission"})
private void startLocationTracking() {
mFusedLocationProviderClient.requestLocationUpdates(mLocationRequest,mLocationCallback, Looper.myLooper());
}


private void fetchRemoteConfig() {
mFirebaseRemoteConfig.fetch(CONFIG_CACHE_EXPIRY)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
Log.i(TAG,"Remote config fetched");
mFirebaseRemoteConfig.activateFetched();
}
});
}

@Override
public void onDestroy() {
setStatusMessage(R.string.not_tracking);
mNotificationManager.cancel(NOTIFICATION_ID);
mFusedLocationProviderClient.removeLocationUpdates(mLocationCallback);
super.onDestroy();
}

@Nullable
@Override
public IBinder onBind(Intent intent) { return null; }

private void bindNotification() {
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this,0,
new Intent(this, MainActivity.class),PendingIntent.FLAG_UPDATE_CURRENT);

mNotificationBuilder = new NotificationCompat.Builder(this,NOTIFICATION_CHANNEL_ID)
.setCategory(NotificationCompat.CATEGORY_STATUS)
.setShowWhen(false)
.setSmallIcon(R.drawable.ic_car)
// .setColor(getColor(R.color.colorPrimary))
.setContentTitle(getString(R.string.app_name))
.setOngoing(true)
.setContentIntent(resultPendingIntent);
startForeground(FOREGROUND_SERVICE_ID, mNotificationBuilder.build());
}

/**
*
* @param message Status message to display
*/
private void setStatusMessage(String message) {
mNotificationBuilder.setContentText(message);
mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build());

Intent intent = new Intent(STATUS_INTENT);
intent.putExtra(getString(R.string.status),message);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

private void setStatusMessage(int resID) {
setStatusMessage(getString(resID));
}
}

我开始了

startService(new Intent(this,LocationUpdateService.class));

Android list :

<service android:name=".LocationUpdateService" />

EDIT1: 我现在在较旧的 API 版本 (22) 上对其进行了测试,问题仍然相同:只要某些具有位置请求的应用程序在前台它有效,否则无效。也许这是 FusedLocationProviderClient 的问题,但我不知道是什么。我只找到了现在已弃用的旧 FusedLocationProvider API 的代码示例。

最佳答案

您是否尝试过调试以确保您的服务被命中?

这听起来可能很傻,但是您是否检查过您的服务是否已在您的 list 中注册?我知道我肯定遇到过这个问题。

<service android:name=".LocationService"
android:label="Location Service"
android:exported="true"
android:enabled="true"
android:process=":location_background_service"/>

为了获取位置,当我设置我的位置时,我创建了一个实现 android.location.LocationListener 的类。

private class LocationListener implements android.location.LocationListener {
Location mLastLocation;

public LocationListener(String provider) {
Log.e(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}

@Override
public void onLocationChanged(Location location) {
Log.e(TAG, "onLocationChanged: " + location);
mLastLocation.set(location);
}

@Override
public void onProviderDisabled(String provider) {
Log.e(TAG, "onProviderDisabled: " + provider);
}

@Override
public void onProviderEnabled(String provider) {
Log.e(TAG, "onProviderEnabled: " + provider);
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.e(TAG, "onStatusChanged: " + provider);
}
}

您可以为不同的提供商创建多个实例。就我而言,我最终使用了 2。

LocationListener[] mLocationListeners = new LocationListener[]{
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};

然后我初始化了一个 LocationManager,它可以为每个 LocationListener 设置轮询率。

private void initializeLocationManager() {
Log.e(TAG, "initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}

然后在您的服务 onCreate 函数中,初始化您的 LocationManager,并将其中一个监听器用作您的主要源,另一个用作后备。

try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
5 * 60 * 1000, //5 Minutes
1F /*METERS*/,
mLocationListeners[0]
);
} catch (java.lang.SecurityException ex) {
Log.e(TAG, "failed to request location update. Insufficient permissions. ", ex);
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
5 * 60 * 1000, //5 Minutes
1F /*METERS*/,
mLocationListeners[1]
);
} catch (java.lang.SecurityException e) {
Log.e(TAG, "failed to request location update. Insufficient permissions. ", e);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Network provider does not exist.", e);
}
} catch (IllegalArgumentException ex) {
Log.e(TAG, "Network provider does not exist.", ex);
}
}

(抱歉,如果这段代码很粗糙,这是一个快速而肮脏的例子。)

关于java - 如何在后台接收位置更新? (API 26),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51252743/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com