![](/img/trans.png)
[英]Stop location updates by using the last google play services api location
[英]Location Updates using google play services and FusedLocationProviderClient
我想使用最新的融合位置提供商客戶端在“后台服務”上獲取位置更新。我不想使用所有正在使用的位置監聽器和Google API客戶端。 我還需要使用谷歌播放服務提供的位置設置Api來檢查位置設置是否禁用或啟用“后台服務”。請幫助。
如果我們需要使用fusion location api,那么我們需要使用Google API客戶端,對於后台服務來說,使用它不是問題,以下是我用於在后台獲取位置更新的示例,但還有一件事是Google從6.0引入'DOZE'模式,所以當你的設備處於'DOZE'模式時,我無法給予保證更新,
import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
/**
* Created By Dhaval Solanki
*/
public class ConnectionService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
String TAG = "ConnectionService";
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private Location previousLocation;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / 2;
private Location mLastLocation;
private Context context;
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
context = getApplicationContext();
Log.i(TAG, "onStartCommand");
if (checkPermsion(context)) {
setupLocationService(context);
}
return Service.START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
ApplicationCLass.isServiceRunning = true;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind");
ApplicationCLass.isServiceRunning = false;
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
ApplicationCLass.isServiceRunning = false;
super.onDestroy();
}
private void setupLocationService(Context context) {
if (checkPlayServices()) {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
createLocationRequest();
}
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest().create();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mGoogleApiClient.connect();
}
public boolean checkPermsion(Context context) {
int MyVersion = Build.VERSION.SDK_INT;
if (MyVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return false;
} else if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return false;
} else {
return true;
}
} else {
return true;
}
}
private boolean checkPlayServices() {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int result = googleAPI.isGooglePlayServicesAvailable(this);
if (result != ConnectionResult.SUCCESS) {
return false;
}
return true;
}
private void startLocationUpdates() {
if (mGoogleApiClient.isConnected()) {
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 (Prefs.getUserLat(context).trim().length() > 0 && Prefs.getUserLong(context).trim().length() > 0) {
} else {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
Prefs.setUserLat(context, String.valueOf(mLastLocation.getLatitude()));
Prefs.setUserLong(context, String.valueOf(mLastLocation.getLongitude()));
}
}
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.i(TAG, "Connected to onConnected");
startLocationUpdates();
}
@Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Connected to onConnectionSuspended");
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.i(TAG, "Connected to onConnectionFailed");
}
@Override
public void onLocationChanged(Location location) {
try {
Logger.print("onLocationChanged", "latitued :" + location.getLatitude() + " ,, Longitude " + location.getLongitude());
} catch (Exception e) {
e.printStackTrace();
}
}
}
另一個alaram服務繼續運行或不運行
import android.app.ActivityManager;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class AlarmService extends IntentService {
@Override
protected void onHandleIntent(Intent intent) {
boolean isServiceRunning = false;
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (ConnectionService.class.getName().equals(service.service.getClassName())) {
isServiceRunning = true;
break;
}
}
Log.i("AlarmService", "Service is running " + isServiceRunning);
if(!isServiceRunning) {
startService(new Intent(getApplicationContext(),ConnectionService.class));
} else {
ConnectionService.checkConnectionAndConnect(getApplicationContext());
}
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*/
public AlarmService() {
super("AlaramService");
}
}
並最終開始服務
private void checkAndStartService() {
final ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
new AsyncTask<Void, Void, Boolean>() {
boolean isServiceRunning = false;
@Override
protected Boolean doInBackground(Void... params) {
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (ConnectionService.class.getName().equals(service.service.getClassName())) {
isServiceRunning = true;
break;
}
}
return isServiceRunning;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
Log.i("onPostExecute", "Service running = " + aBoolean);
if (!aBoolean) {
startService(new Intent(ActivitySplash.this, ConnectionService.class));
Intent i = new Intent(ActivitySplash.this, AlarmService.class);
PendingIntent pi = PendingIntent.getService(ActivitySplash.this, 0, i, 0);
AlarmManager am = (AlarmManager) ActivitySplash.this.getSystemService(Context.ALARM_SERVICE);
am.cancel(pi); // cancel any existing alarms
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 60000, pi);
}
}
}.execute();
}
您可以擴展服務類
public class BackgroundLocationService extends Service implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,
LocationListener
您可以在這里查看完整的源代碼BackgroundLocationService.java
用於啟用位置設置
private void displayLocationSettingsRequest() {
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API).build();
googleApiClient.connect();
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(10000 / 2);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(@NonNull LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
// Show the dialog by calling startResolutionForResult(), and check the result
// in onActivityResult().
status.startResolutionForResult(context, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException ignored) {
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
break;
}
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
// Check for the integer request code originally supplied to
startResolutionForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
//startLocationUpdates();
break;
case Activity.RESULT_CANCELED:
displayLocationSettingsRequest();//keep asking
showToast("Location permission needed");
break;
}
break;
}
}
您可以從服務檢查位置設置,如果位置關閉,
LocationManager lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
boolean gps_enabled = false;
boolean network_enabled = false;
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch(Exception ex) {}
try {
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch(Exception ex) {}
if(!gps_enabled && !network_enabled) {
// notify user
// Either you can display a Notification(Recommended way) or you can show dialog with
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
//It needs SYSTEM_ALERT_WINDOW permission. Add this permission in Manifest.
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
}
您可以編寫intentService的代碼,如下所示。 已經考慮過,因為它在后台運行,所以我們不會顯示權限對話框。
public class GetLocationService extends IntentService
implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
public static String TAG = GetLocationService.class.getSimpleName();
private GoogleApiClient mGoogleApiClient;
public GetLocationService() {
super(TAG);
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public GetLocationService(String name) {
super(name);
}
@Override
protected void onHandleIntent(Intent intent) {
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
Log.d(TAG, "disconnecting");
mGoogleApiClient.disconnect();
}
Log.d(TAG, "onHandleIntent");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
}
@Override
public void onConnected(@Nullable Bundle bundle) {
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationRequest locationRequestLow = LocationRequest.create();
locationRequestLow.setPriority(LocationRequest.PRIORITY_LOW_POWER);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this);
} else {
Log.d(TAG, "permission denied");
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Override
public void onLocationChanged(Location location) {
Log.d(TAG, location.toString());
}
}
嗨,我對位置服務有很好的理解,以及我們如何以完美的方式使用它。 看,我會給你關於融合apis的想法。
只需確保按照以下步驟操作即可。 它非常好而且簡單。 步驟1.制作此類GoogleLocationService.java
public class GoogleLocationService {
private GoogleServicesCallbacks callbacks = new GoogleServicesCallbacks();
LocationUpdateListener locationUpdateListener;
Context activity;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;
public GoogleLocationService(Context activity, LocationUpdateListener locationUpdateListener) {
this.locationUpdateListener = locationUpdateListener;
this.activity = activity;
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
//Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(activity)
.addConnectionCallbacks(callbacks)
.addOnConnectionFailedListener(callbacks)
.addApi(LocationServices.API)
.build();
createLocationRequest();
mGoogleApiClient.connect();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private class GoogleServicesCallbacks implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
@Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
@Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
if (connectionResult.getErrorCode() == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED) {
Toast.makeText(activity, "Google play service not updated", Toast.LENGTH_LONG).show();
}
locationUpdateListener.cannotReceiveLocationUpdates();
}
@Override
public void onLocationChanged(Location location) {
if (location.hasAccuracy()) {
if (location.getAccuracy() < 30) {
locationUpdateListener.updateLocation(location);
}
}
}
}
private static boolean locationEnabled(Context context) {
boolean gps_enabled = false;
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
ex.printStackTrace();
}
return gps_enabled;
}
private boolean servicesConnected(Context context) {
return isPackageInstalled(GooglePlayServicesUtil.GOOGLE_PLAY_STORE_PACKAGE, context);
}
private boolean isPackageInstalled(String packagename, Context context) {
PackageManager pm = context.getPackageManager();
try {
pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
}
public void startUpdates() {
/*
* Connect the client. Don't re-start any requests here; instead, wait
* for onResume()
*/
if (servicesConnected(activity)) {
if (locationEnabled(activity)) {
locationUpdateListener.canReceiveLocationUpdates();
startLocationUpdates();
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Unable to get your location.Please turn on your device Gps", Toast.LENGTH_LONG).show();
}
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Google play service not available", Toast.LENGTH_LONG).show();
}
}
//stop location updates
public void stopUpdates() {
stopLocationUpdates();
}
//start location updates
private void startLocationUpdates() {
if (checkSelfPermission(activity, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(activity, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, callbacks);
}
}
public void stopLocationUpdates() {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, callbacks);
}
}
public void startGoogleApi() {
mGoogleApiClient.connect();
}
public void closeGoogleApi() {
mGoogleApiClient.disconnect();
}
}
第2步。 創建此接口LocationUpdateListener.java
public interface LocationUpdateListener {
/**
* Called immediately the service starts if the service can obtain location
*/
void canReceiveLocationUpdates();
/**
* Called immediately the service tries to start if it cannot obtain location - eg the user has disabled wireless and
*/
void cannotReceiveLocationUpdates();
/**
* Called whenever the location has changed (at least non-trivially)
* @param location
*/
void updateLocation(Location location);
/**
* Called when GoogleLocationServices detects that the device has moved to a new location.
* @param localityName The name of the locality (somewhere below street but above area).
*/
void updateLocationName(String localityName, Location location);
}
步驟3.使此Location服務類LocationService.java
public class LocationService extends Service {
private GoogleLocationService googleLocationService;
@Override
public void onCreate() {
super.onCreate();
//start the handler for getting locations
//create component
updateLocation(getApplicationContext());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
//get current location os user
private void updateLocation(Context context) {
googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
@Override
public void canReceiveLocationUpdates() {
}
@Override
public void cannotReceiveLocationUpdates() {
}
//update location to our servers for tracking purpose
@Override
public void updateLocation(Location location) {
if (location != null ) {
Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());
}
}
@Override
public void updateLocationName(String localityName, Location location) {
googleLocationService.stopLocationUpdates();
}
});
googleLocationService.startUpdates();
}
IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
public LocationService getServerInstance() {
return LocationService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
//stop location updates on stopping the service
@Override
public void onDestroy() {
super.onDestroy();
if (googleLocationService != null) {
googleLocationService.stopLocationUpdates();
}
}
}
編輯答案:
如何使用服務,
在您的主要活動中啟動服務,如下所示
startService(new Intent(context, LocationService.class));
停止,
stopService(new Intent(context, LocationService.class));
並在清單中聲明,
<service
android:name=".service.location.LocationService"
android:enabled="true"></service>
注意:我這樣做是因為我在殺死app后需要位置。如果你不想要服務。那么,你可以直接在類中需要更新位置的代碼下面調用並刪除locationservice。
private GoogleLocationService googleLocationService;
googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
@Override
public void canReceiveLocationUpdates() {
}
@Override
public void cannotReceiveLocationUpdates() {
}
//update location to our servers for tracking purpose
@Override
public void updateLocation(Location location) {
if (location != null ) {
Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());
}
}
@Override
public void updateLocationName(String localityName, Location location) {
googleLocationService.stopLocationUpdates();
}
});
googleLocationService.startUpdates();
and call this onDestroy
if (googleLocationService != null) {
googleLocationService.stopLocationUpdates();
}
記住,Locationservice也應該在清單中聲明。 據我所知這是最好的解決方案。 謝謝希望這會對你有所幫助
這個問題似乎並不十分具體。 您似乎無法啟動使用位置服務。
最好的想法可能是查看Google樣本( https://github.com/googlesamples/android-play-location )以更好地理解這些機制。 我可能會從實現最簡單的例子( LocationUpdates )開始。 它使用FusedLocationProvider並檢查設置是否已啟用,因此它應該符合您的需求,或者至少可以幫助您入門。
如果您確實需要使用服務,可以查看LocationUpdatesForegroundService或LocationUpdatesPendingIntent 。 但我強烈建議您在執行此操作之前閱讀並理解第一個示例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.