0

After updated my app to support Android 7 the GPS listner no longer is invoked when the GPS on/off is triggerd. If I refresh my activity it works as expected on Android 6, but not in Android 7. Does anyone have any idea. I have added both my listner, and code releated to gps change in my activity.

I have if its difficult a theory to override the backpressed or activity resumed to recreate view, but havn't suceeded with that either .

GPSListner.java

public abstract class GPSListener implements LocationListener {

 private Context context;

public GPSListener(Context context) {
    this.context = context;
}

@Override
public void onProviderEnabled(String provider) {
    onGPSOn();
}

@Override
public void onProviderDisabled(String provider) {
    onGPSOff();
}

public abstract void onGPSOff();

public abstract void onGPSOn();

@Override
public void onLocationChanged(Location location) {

}


@Override
public void onStatusChanged(String provider, int status, Bundle extras) {

}

}

My class

gpsListener = new GPSListener(this) {
        @Override
        public void onGPSOff() {
            gpsImg.setImageResource(R.drawable.notok);
        }

        @Override
        public void onGPSOn() {
            gpsImg.setImageResource(R.drawable.ok);
        }
    };


   final LocationManager manager;
    manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    final ImageView gpsImg = (ImageView) findViewById(R.id.gpsstatus);
    if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
        gpsImg.setImageResource(R.drawable.ok);
    } else {
        gpsImg.setImageResource(R.drawable.notok);  //not ok
    }

This last method opens the gps settings.

   public View.OnClickListener onButtongpsClick = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent gpsOptionsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        startActivity(gpsOptionsIntent);
    }
};
datasmurfen
  • 324
  • 8
  • 25

3 Answers3

2

Obtaining location is a bit tricky itself. Only GPS can have line-of-sight issues and would vary depending on device too, not just Android version. Over the years Android location services have matured and using up-to-date standard practices does result in higher consistency with respect to results.

By the way, LocationClient is deprecated. FusedLocationProviderApi does not use it anymore.

It works through a GoogleApiClient and this part makes the GooglePlayServices mandatory. You have options if this does not suit your app.

Making your app location aware suggests:

The Google Play services location APIs are preferred over the Android framework location APIs (android.location) as a way of adding location awareness to your app. If you are currently using the Android framework location APIs, you are strongly encouraged to switch to the Google Play services location APIs as soon as possible.

You can break it into parts to understand it better, like;

Building the GoogleApiClient

protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this) //this = activity
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this) //interfaces implemented
                .addOnConnectionFailedListener(this)
                .build();
    }  

Requesting location,

  // Create the location request
        mLocationRequest = LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(UPDATE_INTERVAL)
                .setFastestInterval(FASTEST_INTERVAL);
        // Request location updates
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
                mLocationRequest, this);

Try the last known location, if that requirement works for you,

@Override
    public void onConnected(Bundle bundle) {

        Location mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
...}

onConnected() is the callback from GoogleApiClient... So there is more to location than initialising a client and implementing the listener. I recommend you go through a few questions or android docs to ensure you implement what suits your requirement.

Also, instead of

Intent gpsOptionsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);  ,  

use SettingsApi
can refer to Enabling location mode...

Some useful Q&As:

Community
  • 1
  • 1
Pararth
  • 8,114
  • 4
  • 34
  • 51
  • I think you deserve the 50 points, but you are not directly helping me. Just giving me some sample code. – datasmurfen Mar 25 '17 at 19:18
  • directly helping as in ? i would really want you to understand what you code and not just copy-paste a class, esp for a usecase like yours.. otherwise if you want, [basic location sample code](https://github.com/googlesamples/android-play-location/tree/master/BasicLocationSample) and other snippets are available online – Pararth Mar 26 '17 at 02:59
0

final LocationManager manager;

manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

Do i even have to comment on this one? Read it again and you will understand what is wrong with it.

Hint. Try:

final LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

Community
  • 1
  • 1
M.Penev
  • 9
  • 2
0

You can used fused location api to get the location

Fused Location Api : Fused Location Provider automatically decides best location from the available options for that it uses GPS and Network Provider, So if the device GPS is off we can still get the location from Network provider vice versa.

Why Fused Location Api ?

  1. Consumption of power while fetching location.
  2. It will give accurate location based on user priority.
  3. Piggyback which means you can get location every time when other application hits for location for you advantage is user not blame you for that you just getting those location which other application request.
  4. We don’t have to pick the provider(GPS or network provider)

please refer code for following for getting location. LocationService : We required these for getting continues location and these register as pending intent so whenever device got new location these service invoke.

public class LocationService extends IntentService {

    private String TAG = this.getClass().getSimpleName();
    public LocationService() {
        super("Fused Location");
    }

    public LocationService(String name) {
        super("Fused Location");
    }

    @Override
    protected void onHandleIntent(Intent intent) {

            Location location = intent.getParcelableExtra(LocationClient.KEY_LOCATION_CHANGED);
            if(location !=null){
                Log.i(TAG, "onHandleIntent " + location.getLatitude() + "," + location.getLongitude());
            // write your code here.

            }

    }

}

MainActivity : which register callbacks for it which tell us whether we are connected or disconnected with api.

public class MainActivity extends Activity implements GooglePlayServicesClient.ConnectionCallbacks,GooglePlayServicesClient.OnConnectionFailedListener,LocationListener {

    private String TAG = this.getClass().getSimpleName();
    private LocationClient locationclient;
    private LocationRequest locationrequest;
    private Intent mIntentService;
    private PendingIntent mPendingIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mIntentService = new Intent(this,LocationService.class);
        mPendingIntent = PendingIntent.getService(this, 1, mIntentService, 0);

        int resp =GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if(resp == ConnectionResult.SUCCESS){
            locationclient = new LocationClient(this,this,this);
            locationclient.connect();
        }
        else{
            Toast.makeText(this, "Google Play Service Error " + resp, Toast.LENGTH_LONG).show();

        }

    }

    public void buttonClicked(View v){
        if(v.getId() == R.id.btnLastLoc){
            if(locationclient!=null && locationclient.isConnected()){
                Location loc =locationclient.getLastLocation();
                Log.i(TAG, "Last Known Location :" + loc.getLatitude() + "," + loc.getLongitude());
                txtLastKnownLoc.setText(loc.getLatitude() + "," + loc.getLongitude());  
            }
        }
        if(v.getId() == R.id.btnStartRequest){
            if(locationclient!=null && locationclient.isConnected()){

                if(((Button)v).getText().equals("Start")){
                    locationrequest = LocationRequest.create();
                    locationrequest.setInterval(Long.parseLong(etLocationInterval.getText().toString()));
                    locationclient.requestLocationUpdates(locationrequest, this);
                    ((Button) v).setText("Stop");   
                }
                else{
                    locationclient.removeLocationUpdates(this);
                    ((Button) v).setText("Start");
                }

            }
        }
        if(v.getId() == R.id.btnRequestLocationIntent){
            if(((Button)v).getText().equals("Start")){

                locationrequest = LocationRequest.create();
                locationrequest.setInterval(100);
                locationclient.requestLocationUpdates(locationrequest, mPendingIntent);

                ((Button) v).setText("Stop");
            }
            else{
                locationclient.removeLocationUpdates(mPendingIntent);
                ((Button) v).setText("Start");
            }





        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(locationclient!=null)
            locationclient.disconnect();
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        Log.i(TAG, "onConnected");
        txtConnectionStatus.setText("Connection Status : Connected");

    }

    @Override
    public void onDisconnected() {
        Log.i(TAG, "onDisconnected");
        txtConnectionStatus.setText("Connection Status : Disconnected");

    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        Log.i(TAG, "onConnectionFailed");
        txtConnectionStatus.setText("Connection Status : Fail");

    }

    @Override
    public void onLocationChanged(Location location) {
        if(location!=null){
            Log.i(TAG, "Location Request :" + location.getLatitude() + "," + location.getLongitude());

        }

    }
}

For more reference refer below link

https://github.com/riteshreddyr/fused-location-provider https://github.com/kpbird/fused-location-provider-example

Hope these help you.

Jitesh Mohite
  • 31,138
  • 12
  • 157
  • 147
  • the KPBird example was a good one when LocationClient was introduced, for today.. the same is deprecated. – Pararth Mar 24 '17 at 05:47
  • for which api is deprecated – Jitesh Mohite Mar 24 '17 at 06:11
  • meaning ? `locationclient = new LocationClient(this,this,this);` is what i am referring to – Pararth Mar 24 '17 at 06:17
  • and [this](http://kpbird.blogspot.in/2013/06/fused-location-provider-example.html) is the KPBird article i was talking about – Pararth Mar 24 '17 at 06:19
  • even the IntentService isn't required, not recommended if not necessary.. just a sidenote, hoping to save you some time and if it helps anybody improve implementation – Pararth Mar 24 '17 at 06:26