Wednesday 15 June 2016

GPS Tracker In Background.

In this Post Am going to show how to track the users Location with Fused Location API in Background using Service.

If you are new to Fused Location API go through this tutorial. http://www.androidwarriors.com/2015/10/fused-location-provider-in-android.html

Important : Your Project Requirement is to track Location in Real Time updates for each and Ever Coordinates means Continue my tutorial otherwise above link will helpful. Because this will drain your battery.

Add the 'com.google.android.gms:play-services-location:9.0.2' dependency in your app level gradle file.

Now add the location Permission and meta-data in you manifext.xml file.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.davy.gpstrackbackground">

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest> 

Now Create Service Class to Add the Fused Location API coding that Class. Am create the Class Name like GPSTracker.
public class GPSTracker extends Service implements GoogleApiClient.ConnectionCallbacks, 
                      GoogleApiClient.OnConnectionFailedListener, LocationListener {

    public static final String LOCATION_TRACKING = "LOCTRACKIN";

    private Location mLastLocation;
    private GoogleApiClient mGoogleApiClient;

    private LocationRequest mLocationRequest;

    public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000 * 2;
    public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;

    PendingResult result;
    Intent intent;

    SharedPreferences preferences;
    SharedPreferences.Editor editor;

    Set set = new HashSet<>();
    ArrayList arrayList = new ArrayList<>();

    @Override
    public void onCreate() {
        super.onCreate();

        preferences = getSharedPreferences("latLang", Context.MODE_PRIVATE);
        editor = preferences.edit();

        intent = new Intent(LOCATION_TRACKING);
        createLocationRequest();
        buildGoogleApiClient();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        if (mGoogleApiClient != null) {
            mGoogleApiClient.connect();
        }

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {

        if (mGoogleApiClient.isConnected()) {
            startLocationUpdates();
        }

        try {

            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(mLocationRequest);

            result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());

            result.setResultCallback(new ResultCallback() {
                @Override
                public void onResult(LocationSettingsResult result) {
                    final Status status = result.getStatus();
                    switch (status.getStatusCode()) {
                        case LocationSettingsStatusCodes.SUCCESS:
                            break;
                        case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                            break;
                        case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                            break;
                    }
                }
            });

            displayLocation();

        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

    //OnTaskRemove used to stop the Location Update while the App removed from Task Manger.
    @Override
    public void onTaskRemoved(Intent rootIntent) {
        Log.v("LOC_UPD", "STOPPED");
        if (mGoogleApiClient != null) {
            if (mGoogleApiClient.isConnected()) {
                stopLocationUpdates();
                mGoogleApiClient.disconnect();
            }
        }
        stopSelf();
        super.onTaskRemoved(rootIntent);
    }

    @Override
    public void onDestroy() {
        Log.v("LOC_UPD", "STOPPED");
        if (mGoogleApiClient != null) {
            if (mGoogleApiClient.isConnected()) {
                stopLocationUpdates();
                mGoogleApiClient.disconnect();
            }
        }
        super.onDestroy();
    }

    @Override
    public void onConnectionSuspended(int i) {
        mGoogleApiClient.connect();
    }

    @Override
    public void onLocationChanged(Location location) {
        mLastLocation = location;
        displayLocation();
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.i("Connection Failed", "" + connectionResult.getErrorCode());
    }

    protected void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setSmallestDisplacement(10);
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

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

    private void displayLocation() {

        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
                          == PackageManager.PERMISSION_GRANTED) {
            mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        }

        if (mLastLocation != null) {

            arrayList.add(mLastLocation.getLatitude() + "," + mLastLocation.getLongitude() + " @" + new SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(Calendar.getInstance().getTime()));
            set.clear();
            set.addAll(arrayList);
            editor.putStringSet("location", set);
            editor.apply();

            intent.putExtra("Latitude", mLastLocation.getLatitude());
            intent.putExtra("Longitude", mLastLocation.getLongitude());
            intent.putExtra("Provider", mLastLocation.getProvider());
            sendBroadcast(intent);

        }

    }

    protected void startLocationUpdates() {
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
                   == PackageManager.PERMISSION_GRANTED) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
    }

    protected void stopLocationUpdates() {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
    }
}


Add this service Class in Manifest.xml file.

<service android:name=".GPSTracker"/>

In GPSTracker service Class add sendBroadcast  can easily get the Broadcasted Latitude and Longitude in Any Activity or Fragment using Broadcast Receiver. Added the all latitude and Longitude into array and save it in SharePreference.

In this Tutorial am add it in MainActivity.Class.

public class MainActivity extends AppCompatActivity {

    TextView lat_lang;
    public static final int REQUEST_LOCATION = 8;
    SharedPreferences preferences;
    SharedPreferences.Editor editor;

    Button button, btn_log;
    ListView listView;
    ArrayAdapter adapter;
    ArrayList arrayList = new ArrayList<>();

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

        preferences = getSharedPreferences("latLang", Context.MODE_PRIVATE);
        editor = preferences.edit();

        lat_lang = (TextView) findViewById(R.id.textView);
        listView = (ListView)findViewById(R.id.listView);

        adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, arrayList);
        listView.setAdapter(adapter);

        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (isMyServiceRunning(GPSTracker.class)) {
                    Intent intent = new Intent(MainActivity.this, GPSTracker.class);
                    stopService(intent);
                    button.setText("Start Update");
                    editor.clear();
                    editor.apply();
                } else {
                    Intent intent = new Intent(MainActivity.this, GPSTracker.class);
                    startService(intent);
                    button.setText("Stop Update");
                }
            }
        });

        btn_log = (Button) findViewById(R.id.button2);
        btn_log.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Set set = preferences.getStringSet("location", null);
                if (set != null) {
                    arrayList.clear();
                    arrayList = new ArrayList<>(set);
                    adapter = new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1, arrayList);
                    listView.setAdapter(adapter);
                }
            }
        });

        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            if (!ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.ACCESS_FINE_LOCATION)) {
                Toast.makeText(this, "Allow Location Access Permission.", Toast.LENGTH_LONG).show();
            }
            ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION);

        } else {

            if (!isMyServiceRunning(GPSTracker.class)) {
                Intent intent = new Intent(MainActivity.this, GPSTracker.class);
                startService(intent);
            }

        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(receiver, new IntentFilter(GPSTracker.LOCATION_TRACKING));
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(receiver);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_LOCATION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if (!isMyServiceRunning(GPSTracker.class)) {
                    Intent intent = new Intent(MainActivity.this, GPSTracker.class);
                    startService(intent);
                }
            } else {
                Toast.makeText(this, "Allow Location Access Permission.", Toast.LENGTH_LONG).show();
            }
        }
    }

    private BroadcastReceiver receiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            Bundle bundle = intent.getExtras();
            if (bundle != null) {
                lat_lang.setText("Last Lat &  Lang : " + bundle.getDouble("Latitude", 0) + ", " + bundle.getDouble("Longitude", 0));
                Set set = preferences.getStringSet("location", null);
                if (set != null) {
                    arrayList.clear();
                    arrayList = new ArrayList<>(set);
                    adapter = new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1, arrayList);
                    listView.setAdapter(adapter);
                }
            }
        }
    };

    private boolean isMyServiceRunning(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;
    }

}

Sample Code Available in GitHub : https://github.com/yugeshdevaraja/GPSTrackBackground

No comments :

Post a Comment