我正试图编写一个应用程序来跟踪背景中的位置,并将数据发送到服务器--例如,监视我的家人在哪里。
目前,我正在使用https://github.com/android/location-samples,特别是LocationUpdatesBackgroundKotlin,这似乎是接收位置更新的最佳方式,但是
在收到背景中的8-10个位置更新后,状态栏上的gps图标在没有通知应用程序的情况下死亡(这里是android/phone信息,但我希望该应用程序与Android5.1兼容)。
我想知道是否是活着地接收位置更新,如果它死了就重新启动它(用fusedLocationClient.requestLocationUpdates重新启动MyLocationManager的第105行可以帮助接收进一步的更新,但是我必须用眼睛监视状态)。
有没有什么出路,或者更可靠的方法?谢谢。
P.S.已经为android写了一个星期了。
发布于 2020-10-30 17:45:59
对于Android5Lolliop来说,使用第三方库(更稳定得多)接收基站位置(即io.nlopez.smartlocation.SmartLocation from 'io.nlopez.smartlocation:library:3.3.3' )和前台服务(如Rudrik Patel所提到的)是更好的(更稳定的)。就像一种魅力。
发布于 2020-10-09 06:55:11
为了不断地从应用程序中获取位置,您必须使用前台服务,您可以在其中初始化位置管理器,并根据已设置的参数不断地获取位置更新。另外,确保您有背景位置权限,因为它是在API级别29之后的要求。以下是如何实现这一目标的基本流程。请确保在获得“位置”权限后启动此服务:
public class MyCustomService extends Service implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private GoogleApiClient mGoogleApiClient;
private PowerManager.WakeLock mWakeLock;
private LocationRequest mLocationRequest;
private boolean mInProgress;
private Boolean servicesAvailable = false;
@Override
public IBinder onBind(Intent arg0) {
return null;
}
private static final int UPDATE_INTERVAL_IN_SECONDS = 120;
private static final int MILLISECONDS_PER_SECOND = 1000;
public static final long UPDATE_INTERVAL = MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
private static final int FASTEST_INTERVAL_IN_SECONDS = 60;
public static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
@Override
public void onCreate() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService();
}
mInProgress = false;
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setSmallestDisplacement(100);
servicesAvailable = servicesConnected();
/*
* Create a new location client, using the enclosing class to
* handle callbacks.
*/
setUpLocationClientIfNeeded();
super.onCreate();
}
private void setUpLocationClientIfNeeded() {
if (mGoogleApiClient == null)
buildGoogleApiClient();
}
/*
* Create a new location client, using the enclosing class to
* handle callbacks.
*/
protected synchronized void buildGoogleApiClient() {
this.mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
private boolean servicesConnected() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
return true;
} else {
return false;
}
}
/* Used to build and start foreground service. */
private void startForegroundService() {
Intent notificationIntent = new Intent(this, HomeActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
String CHANNEL_ID = "1";
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.noti_icon)
.setPriority(Notification.PRIORITY_LOW)
.setOngoing(true)
.setAutoCancel(false)
.setContentTitle("ServiceTitle")
.setContentText("Service Reason text")
.setTicker("TICKER")
.setChannelId(CHANNEL_ID)
.setVibrate(new long[]{0L})
.setContentIntent(pendingIntent);
Notification notification = builder.build();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", NotificationManager.IMPORTANCE_HIGH);
channel.setDescription("NOTIFICATION_CHANNEL_DESC");
channel.enableVibration(false);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
notificationManager.createNotificationChannel(channel);
}
startForeground(123, notification);
}
@Override
public void onDestroy() {
super.onDestroy();
this.mInProgress = false;
if (this.servicesAvailable && this.mGoogleApiClient != null) {
this.mGoogleApiClient.unregisterConnectionCallbacks(this);
this.mGoogleApiClient.unregisterConnectionFailedListener(this);
this.mGoogleApiClient.disconnect();
// Destroy the current location client
this.mGoogleApiClient = null;
}
if (this.mWakeLock != null) {
this.mWakeLock.release();
this.mWakeLock = null;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService();
}
setUpLocationClientIfNeeded();
if (!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting() && !mInProgress) {
mInProgress = true;
mGoogleApiClient.connect();
}
return START_STICKY;
}
@Override
public void onConnected(@Nullable Bundle bundle) {
Intent intent = new Intent(this, LocationReceiver.class);
PendingIntent pendingIntent = PendingIntent
.getBroadcast(this, 54321, intent, PendingIntent.FLAG_CANCEL_CURRENT);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (this.mGoogleApiClient != null)
LocationServices.FusedLocationApi.requestLocationUpdates(this.mGoogleApiClient,
mLocationRequest, pendingIntent);
}
@Override
public void onConnectionSuspended(int i) {
// Turn off the request flag
mInProgress = false;
// Destroy the current location client
mGoogleApiClient = null;
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
mInProgress = false;
/*
* Google Play services can resolve some errors it detects.
* If the error has a resolution, try sending an Intent to
* start a Google Play services activity that can resolve
* error.
*/
if (connectionResult.hasResolution()) {
// If no resolution is available, display an error dialog
} else {
}
}
}以下是您需要在Android清单文件中注册的Location接收器类
public class LocationReceiver extends BroadcastReceiver {
private String TAG = "LOCATION RECEIVER";
private LocationResult mLocationResult;
private Context context;
Location mLastLocation;
@Override
public void onReceive(Context context, Intent intent) {
// Need to check and grab the Intent's extras like so
this.context = context;
if (LocationResult.hasResult(intent)) {
this.mLocationResult = LocationResult.extractResult(intent);
if (mLocationResult.getLocations().get(0).getAccuracy() < 100) {
// DO WHATEVER YOU WANT WITH LOCATION
}
}
}
}所需许可:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>注意:上述代码中的一些方法(如FusedLocationApi和isGooglePlayServicesAvailable )是不推荐的。
https://stackoverflow.com/questions/64275072
复制相似问题