在FusedApi中有问题 [英] Having Issue in FusedApi

查看:108
本文介绍了在FusedApi中有问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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


推荐答案

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

这篇关于在FusedApi中有问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆