-2

I want to get location from background and submit it to server so which is the best option to do the same like Job scheduler or Service. and why ?. I also want to know about battery saved by job scheduler while continuously we make web apicall.

Akshay More
  • 359
  • 2
  • 13

2 Answers2

0

This is my implementation, I don't use Job Scheduler or Service because it's not necessary. I use the Application class so you will be able to get the location of user in all your app.

First, you need to create a LocationHelper class, that will do all the work for you:

public class LocationHelper implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener, LocationListener {

    private static final int REQUEST_LOCATION_PERMISSION = 0;
    private static final int REQUEST_RESOLVE_ERROR = 1;

    private static GoogleApiClient mGoogleApiClient;
    private Fragment mFragment;
    private final Activity mActivity;
    private final Callback mCallback;

    private Location mLastLocation;
    private boolean mResolvingError;
    private LocationRequest mLocationRequest;
    private boolean mRegisterLocationUpdates;

    public interface Callback {
        void onLastLocation(Location userLocation);
    }

    public LocationHelper(Fragment fragment, Callback callback) {
        this(fragment.getActivity(), callback);
        mFragment = fragment;
    }

    public LocationHelper(Activity activity, Callback callback) {
        mActivity = activity;
        mCallback = callback;

        mLocationRequest = new LocationRequest();

        mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }


    @Override
    public void onConnected(@Nullable Bundle bundle) {
        obtainLastLocation();
    }

    private void obtainLastLocation() {

        // Verifies if user give us permission to obtain its suggestionLocationV2.
        if (ActivityCompat.checkSelfPermission(mActivity,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(mActivity,
                Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity,
                    Manifest.permission.ACCESS_COARSE_LOCATION)) {

                // Show an explanation to the user why we need its suggestionLocationV2.
                requestPermissionRationale();

            } else {

                requestPermission();
            }

            // We don't have user permission to get its geo suggestionLocationV2, abort mission.
            return;
        }

        if (!mGoogleApiClient.isConnected()) {
            mGoogleApiClient.connect();
            return;
        }

        Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if (lastLocation != null) {
            onLocationChanged(lastLocation);
        } else {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            mRegisterLocationUpdates = true;
        }
    }

    @Override
    public void onLocationChanged(Location location) {
        if (location == null) return;

        removeLocationUpdatesIfNeed();

        mLastLocation = location;
        DirectoryApp.getInstance().setLastLocation(mLastLocation);

        if (mCallback != null) {
            mCallback.onLastLocation(mLastLocation);
        }
    }

    private void removeLocationUpdatesIfNeed() {
        if (mRegisterLocationUpdates && mGoogleApiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
            mRegisterLocationUpdates = false;
        }
    }

    private void requestPermission() {
        // Lets ask suggestionLocationV2 permission to user.
        if (mFragment != null) {
            mFragment.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                    REQUEST_LOCATION_PERMISSION);
        } else {
            ActivityCompat.requestPermissions(mActivity,
                    new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                    REQUEST_LOCATION_PERMISSION);
        }
    }

    private void requestPermissionRationale() {
        new AlertDialog.Builder(mActivity)
                .setMessage("We need the suggestionLocationV2 to provide you best results.")
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        requestPermission();
                    }
                })
                .show();
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult result) {

        // If not already attempting to resolve an error.
        if (!mResolvingError) {

            if (result.hasResolution()) {

                try {
                    mResolvingError = true;
                    result.startResolutionForResult(mActivity, REQUEST_RESOLVE_ERROR);
                } catch (IntentSender.SendIntentException e) {
                    // There was an error with the resolution intent. Try again.
                    mGoogleApiClient.connect();
                }

            } else {
                GooglePlayServicesUtil.showErrorDialogFragment(result.getErrorCode(), mActivity,
                        null, REQUEST_RESOLVE_ERROR, null);
                mResolvingError = true;
            }
        }
    }


    // The follow methods should be called in Activity or Fragment.
    public void onStart() {
        mGoogleApiClient.connect();
    }

    public void onStop() {
        removeLocationUpdatesIfNeed();
        mGoogleApiClient.disconnect();
    }

    public void onRequestPermissionResult(int requestCode, String[] permissions,
                                          int[] grantResults) {
        if (requestCode == REQUEST_LOCATION_PERMISSION
                && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

            // Permission granted. Uhull lets get its suggestionLocationV2 now.
            obtainLastLocation();
        }
    }
}

Note that when the location is changed, we call the Application class to set the new location, so in your Application class you have to create the methods :

public class Application extends MultiDexApplication {

    private static App instance;

    private Location mLastLocation;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
   }

    public void setLastLocation(Location lastLocation) {
        mLastLocation = lastLocation;
    }

    public Location getLastLocation() {
        return mLastLocation;
   }

And finally, when you have to use the location, on Fragment or Activity, just start and stop it using the right method`s.

  @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        locationHelper = new LocationHelper(this, this);
    }

    @Override
    public void onStart() {
        super.onStart();
        locationHelper.onStart();
    }

    @Override
    public void onStop() {
        super.onStop();
        locationHelper.onStop();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        locationHelper.onRequestPermissionResult(requestCode, permissions, grantResults);
    }
Luiz Fernando Salvaterra
  • 4,192
  • 2
  • 24
  • 42
0

if you define "best option" as "most battery efficient way": try to minimize calls that activly connects the internet to read or transfer data.

Instead implement a broadcast receiver that tells your app that there is already internet-traffic going on. when you app receives the broadcast notification it can add ist own internet traffic. this way your app can avoid the battery overhead of connecting to the internet which is is very battery expensive.

For detail see "bundled tranfer" at https://developer.android.com/training/efficient-downloads/efficient-network-access.html

k3b
  • 14,517
  • 7
  • 53
  • 85