在FusedApi中出现问题

时间:2019-02-06 09:56:41

标签: android android-fusedlocation

我的应用程序运行正常,但有时会开始显示“未检测到位置”,几个小时后,应用程序本身开始显示用户位置的纬度和经度。我知道获取“用户位置”已有很多答案。我的情况是我达到了我想要的目标,但有时甚至几个小时,甚至是半天,它都没有找到位置并自行纠正。

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();
        }
    }
}

1 个答案:

答案 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;
    }
}

我已经设置了位置请求的优先级,请确保设备已在位置上并且优先级较高,如果您也需要任何帮助,请告诉我。请使用以上服务