我的应用程序运行正常,但有时会开始显示“未检测到位置”,几个小时后,应用程序本身开始显示用户位置的纬度和经度。我知道获取“用户位置”已有很多答案。我的情况是我达到了我想要的目标,但有时甚至几个小时,甚至是半天,它都没有找到位置并自行纠正。
public class CampaignFormData extends BaseActivity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
private String latitude = "";
private String longitude = "";
private String mCurrentPhotoPath;
private GoogleApiClient mGoogleApiClient;
Location mLastLocation;
private LocationRequest mLocationRequest;
private UserSession mUserSession;
synchronized void buildGoogleApiClient() {
this.mGoogleApiClient = new Builder(this).addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).build();
}
@SuppressLint("UseSparseArrays")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_campaign_form_data);
this.mUserSession = new UserSession(this);
buildGoogleApiClient();
}
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
CampaignFormData.this.finish();
}
return super.onOptionsItemSelected(item);
}
public void onConnected(Bundle bundle) {
this.mLocationRequest = LocationRequest.create();
this.mLocationRequest.setPriority(100);
this.mLocationRequest.setInterval(20000);
if (ContextCompat.checkSelfPermission(this, "android.permission.ACCESS_FINE_LOCATION") == 0 || ContextCompat.checkSelfPermission(this, "android.permission.ACCESS_COARSE_LOCATION") == 0) {
LocationServices.FusedLocationApi.requestLocationUpdates(this.mGoogleApiClient, this.mLocationRequest, (LocationListener) this);
this.mLastLocation = LocationServices.FusedLocationApi.getLastLocation(this.mGoogleApiClient);
if (this.mLastLocation != null) {
this.latitude = String.valueOf(this.mLastLocation.getLatitude());
this.longitude = String.valueOf(this.mLastLocation.getLongitude());
return;
} else {
Toast.makeText(getApplicationContext(), "Location not Detected", Toast.LENGTH_LONG).show();
}
}
}
public void onConnectionSuspended(int i) {
}
public void onLocationChanged(Location location) {
this.mLastLocation = location;
this.latitude = String.valueOf(this.mLastLocation.getLatitude());
this.longitude = String.valueOf(this.mLastLocation.getLongitude());
}
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
try {
connectionResult.startResolutionForResult(this, HTTPStatusCode.MultipleChoices);
} catch (SendIntentException e) {
e.printStackTrace();
}
}
}
protected void onStart() {
super.onStart();
this.mGoogleApiClient.connect();
}
protected void onStop() {
super.onStop();
try {
LocationServices.FusedLocationApi.removeLocationUpdates(this.mGoogleApiClient, this);
this.mGoogleApiClient.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:1)
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationAvailability;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import java.util.Calendar;
import java.util.TimeZone;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static com.aip.bustracker.commonmodule.gpsservices.TrackLocationService.Channel.GENERAL_NOTIFICATION_CHANNEL_ID;
public class TrackLocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static final long UPDATE_INTERVAL = 1, FASTEST_INTERVAL = 5000; // = 5 seconds
private GoogleApiClient googleApiClient;
private LocationRequest locationRequest;
Context mContext;
private String ROUTE_START_SERVICE_DATA_KEY = "route_start_service_data";
private FusedLocationProviderClient mFusedLocationClient;
private static final int MIN_DISTANCE = 2;
private static final int BUS_NEAR_TO_PARENT_STOPPAGE = 5;
private static final int BUS_DRIVER = 4;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* used to create own channel in case of versions greater than or equal to oreo
* @param context
*/
private static void createServiceChannel(Context context){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel(context, GENERAL_NOTIFICATION_CHANNEL_ID);
}
}
private static void createNotificationChannel(Context context, Channel notificationChannel) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// Configure the notification channel.
NotificationChannel mChannel = null;
mChannel = new NotificationChannel(notificationChannel.name(), notificationChannel.getName(), notificationChannel.getImportance());
// The user-visible description of the channel.
mChannel.setDescription(notificationChannel.getDescription());
mChannel.enableLights(true);
// Sets the notification light color for notifications posted to this
// channel, if the device supports this feature.
mChannel.setLightColor(Color.RED);
mChannel.enableVibration(false);
mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
// Register the channel with the system
mNotificationManager.createNotificationChannel(mChannel);
}
}
public enum Channel {
GENERAL_NOTIFICATION_CHANNEL_ID("","", Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? NotificationManager.IMPORTANCE_DEFAULT : 0);
private String name;
private String description;
private @DrawableRes
int icon;
private int importance;
Channel(String name, String description, int importance, @DrawableRes int icon) {
this.setName(name);
this.setDescription(description);
this.setImportance(importance);
this.setIcon(icon);
}
Channel(String name, String description, int importance) {
this.setName(name);
this.setDescription(description);
this.setImportance(importance);
this.setIcon(R.mipmap.ic_launcher);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getIcon() {
return icon;
}
public void setIcon(int icon) {
this.icon = icon;
}
public int getImportance() {
return importance;
}
public void setImportance(int importance) {
this.importance = importance;
}
}
/**
* used to start foreground service
* @param service
* @param notificationChannel
* @param title
* @param mNotificationID
*/
public static void startForeGroundNotification(Service service, Channel notificationChannel,String title,int mNotificationID){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createServiceChannel(service);
Notification.Builder builder = new Notification.Builder(service, notificationChannel.getName())
.setContentTitle(title)
.setOngoing(true)
.setCategory(Notification.CATEGORY_SERVICE)
.setAutoCancel(true);
Notification notification = builder.build();
service.startForeground(mNotificationID, notification);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//startForeGroundNotification(this, GENERAL_NOTIFICATION_CHANNEL_ID,this.getClass().getSimpleName(), 1);
String CHANNEL_ONE_ID = "";
String CHANNEL_ONE_NAME = "";
NotificationChannel notificationChannel = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
notificationChannel = new NotificationChannel(CHANNEL_ONE_ID,
CHANNEL_ONE_NAME, IMPORTANCE_HIGH);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setShowBadge(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.createNotificationChannel(notificationChannel);
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
Notification notification = new Notification.Builder(getApplicationContext())
.setChannelId(CHANNEL_ONE_ID)
.setContentTitle("Trackify")
.setContentText("Best way to track vehicle")
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(icon)
.setAutoCancel(true)
.build();
startForeground(101, notification);
}
Log.e("onstartcommand", "onstart");
buildGoogleApiClient();
if (googleApiClient != null) {
googleApiClient.connect();
}
if (googleApiClient.isConnected()) {
startLocationUpdates();
}
return START_STICKY;
}
@Override
public void onCreate() {
mContext = this;
super.onCreate();
}
/**
* Build google api client
*/
private void buildGoogleApiClient() {
// we build google api client
googleApiClient = new GoogleApiClient.Builder(this).addApi(LocationServices.API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
createLocationRequest();
}
/**
* Determines whether one Location reading is better than the current Location fix
*
* @param currentBestLocation The current Location fix, to which you want to compare the new one
*/
protected boolean isBetterLocation(LocationModel locationModel, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
Location location = new Location(locationModel.getProvider());
location.setLatitude(locationModel.getLat());
location.setLongitude(locationModel.getLong());
location.setTime(locationModel.getTimeStamp());
location.setAccuracy(locationModel.getAccuracy());
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > UPDATE_INTERVAL;
boolean isSignificantlyOlder = timeDelta < -UPDATE_INTERVAL;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return true;
}
return false;
}
/**
* Checks whether two providers are the same
*/
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
public void getLastLocation() {
// Get last known recent location using new Google Play Services SDK (v11+)
FusedLocationProviderClient locationClient = mFusedLocationClient;
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_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.
return;
}
locationClient.getLastLocation()
.addOnSuccessListener(new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
// GPS location can be null if GPS is switched off
if (location != null) {
}
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.d("MapDemoActivity", "Error trying to get last GPS location");
e.printStackTrace();
}
});
}
/**
* Create location request
*/
private void createLocationRequest() {
locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(5000);
locationRequest.setFastestInterval(1000);
locationRequest.setSmallestDisplacement(2);
// Create LocationSettingsRequest object using location request
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(locationRequest);
LocationSettingsRequest locationSettingsRequest = builder.build();
// Check whether location settings are satisfied
// https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient
SettingsClient settingsClient = LocationServices.getSettingsClient(this);
settingsClient.checkLocationSettings(locationSettingsRequest)
.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
@Override
public void onComplete(@NonNull Task<LocationSettingsResponse> task) {
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
}
}).addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
}
});
}
@SuppressLint("MissingPermission")
@Override
public void onConnected(@Nullable Bundle bundle) {
startLocationUpdates();
}
/**
* Update current location
*/
@SuppressLint("MissingPermission")
private void startLocationUpdates() {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mFusedLocationClient.requestLocationUpdates(locationRequest, mLocationCallback, null);
getLastLocation();
}
private LocationCallback mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
Log.e("My lat long:", "Latitude : " + location.getLatitude() + "\nLongitude : " + location.getLongitude());
}
}
@Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
}
};
@Override
public void onConnectionSuspended(int i) {
Log.e("onConnectionSuspended", "onConnectionSuspended");
}
/**
* Determines if the current location is approximately the same as the location
* for a particular status. Used to check if we'll add a new status, or
* update the most recent status of we're stationary.
*/
private boolean locationIsAtStatus(Location location, LatLng latLng) {
Location locationForStatus = new Location(location.getProvider());
locationForStatus.setLatitude(latLng.latitude);
locationForStatus.setLongitude(latLng.longitude);
float distance = location.distanceTo(locationForStatus);
Log.e("distance=", distance + "");
return distance < MIN_DISTANCE;
}
/**
* Determines if the current location is approximately the same as the location
* for a particular status. Used to check if we'll add a new status, or
* update the most recent status of we're stationary.
*/
private boolean locationIsAtStatusForNotification(Location location, LatLng latLng) {
Location locationForStatus = new Location(location.getProvider());
locationForStatus.setLatitude(latLng.latitude);
locationForStatus.setLongitude(latLng.longitude);
float distance = location.distanceTo(locationForStatus);
Log.e("distance=", distance + "");
return distance < 2000;
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.e("onConnectionSuspended", "onConnectionSuspended");
}
@Override
public void onTaskRemoved(Intent rootIntent) {
Log.e("onTaskRemoved", "onTaskRemoved");
super.onTaskRemoved(rootIntent);
if (isServiceRunning(TrackLocationService.class)) {
stopService();
}
restartService();
}
@Override
public void onDestroy() {
Log.e("onDestroy", "onDestroy");
stopLocationUpdates();
super.onDestroy();
}
/**
* To stop location updates
*/
void stopLocationUpdates() {
// stop location updates
if (googleApiClient != null && googleApiClient.isConnected()) {
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
googleApiClient.disconnect();
}
}
/**
* To restart the service
*/
void restartService() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ContextCompat.startForegroundService(this,new Intent(this, TrackLocationService.class));
} else {
startService(new Intent(this, TrackLocationService.class));
}
}
/**
* To Stop the service if already running
*/
void stopService() {
stopService(new Intent(this, TrackLocationService.class));
//Stop to update location
stopLocationUpdates();
}
/**
* To check Service already running or not
*
* @param serviceClass
* @return
*/
private boolean isServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
我已经设置了位置请求的优先级,请确保设备已在位置上并且优先级较高,如果您也需要任何帮助,请告诉我。请使用以上服务