Having Issue in FusedApi

孤人 提交于 2019-12-11 09:09:06

问题


My app is working fine but sometimes its start toasting "Location not detected" and after some hours,app itself start showing the user location latitude and longitude.I knew already there are many answers for getting "user location".But in my scenario I'am achieving what I want but for some hours sometimes even for half day it didn't get the location and get corrected itself.

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:


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

I have set the priority of location request , please make sure that device has location on and priority is high let me know if you need any help in that too. Please use the above service



来源:https://stackoverflow.com/questions/54550770/having-issue-in-fusedapi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!