Location service in java


1.  Add  dependencies


dependencies {
   
    //location service    implementation 'com.google.android.gms:play-services-location:17.0.0'

    implementation 'com.google.android.material:material:1.0.0'}


2. Main activity

create new class MainActivity class

======================================


import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;

import android.Manifest;

import android.content.pm.PackageManager;

import android.net.Uri;

import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.google.android.material.snackbar.Snackbar;

public class MainActivity extends AppCompatActivity implements    SharedPreferences.OnSharedPreferenceChangeListener {
        private static final String TAG = MainActivity.class.getSimpleName();

        // Used in checking for runtime permissions.        private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;

        // The BroadcastReceiver used to listen from broadcasts from the service.        private MyReceiver myReceiver;

        // A reference to the service used to get location updates.        private LocationService mService = null;

        // Tracks the bound state of the service.        private boolean mBound = false;

        // UI elements.        private Button mRequestLocationUpdatesButton;
        private Button mRemoveLocationUpdatesButton;

        // Monitors the state of the connection to the service.        private final ServiceConnection mServiceConnection = new ServiceConnection() {

            @Override            public void onServiceConnected(ComponentName name, IBinder service) {
                LocationService.LocalBinder binder = (LocationService.LocalBinder) service;
                mService = binder.getService();
                mBound = true;
            }

            @Override            public void onServiceDisconnected(ComponentName name) {
                mService = null;
                mBound = false;
            }
        };


        @Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
            myReceiver = new MyReceiver();
        setContentView(R.layout.activity_main);
            // Check that the user hasn't revoked permissions by going to Settings.            if (Utils.requestingLocationUpdates(this)) {
                if (!checkPermissions()) {
                    requestPermissions();
                }
            }
    }

    @Override    protected void onStart() {
        super.onStart();
        PreferenceManager.getDefaultSharedPreferences(this)
                .registerOnSharedPreferenceChangeListener(this);

        mRequestLocationUpdatesButton = (Button) findViewById(R.id.request_location_updates_button);
        mRemoveLocationUpdatesButton = (Button) findViewById(R.id.remove_location_updates_button);

        mRequestLocationUpdatesButton.setOnClickListener(new View.OnClickListener() {
            @Override            public void onClick(View view) {
                if (!checkPermissions()) {
                    requestPermissions();
                } else {
                    mService.requestLocationUpdates();
                }
            }
        });

        mRemoveLocationUpdatesButton.setOnClickListener(new View.OnClickListener() {
            @Override            public void onClick(View view) {
                mService.removeLocationUpdates();
            }
        });

        // Restore the state of the buttons when the activity (re)launches.        setButtonsState(Utils.requestingLocationUpdates(this));

        // Bind to the service. If the service is in foreground mode, this signals to the service        // that since this activity is in the foreground, the service can exit foreground mode.        bindService(new Intent(this, LocationService.class), mServiceConnection,
                Context.BIND_AUTO_CREATE);
    }

    @Override    protected void onResume() {
        super.onResume();
        LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver,
                new IntentFilter(LocationService.ACTION_BROADCAST));
    }

    @Override    protected void onPause() {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
        super.onPause();
    }

    @Override    protected void onStop() {
        if (mBound) {
            // Unbind from the service. This signals to the service that this activity is no longer            // in the foreground, and the service can respond by promoting itself to a foreground            // service.            unbindService(mServiceConnection);
            mBound = false;
        }
        PreferenceManager.getDefaultSharedPreferences(this)
                .unregisterOnSharedPreferenceChangeListener(this);
        super.onStop();
    }

    /**     * Returns the current state of the permissions needed.     */    private boolean checkPermissions() {
        return  PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION);
    }

    private void requestPermissions() {
        boolean shouldProvideRationale =
                ActivityCompat.shouldShowRequestPermissionRationale(this,
                        Manifest.permission.ACCESS_FINE_LOCATION);

        // Provide an additional rationale to the user. This would happen if the user denied the        // request previously, but didn't check the "Don't ask again" checkbox.        if (shouldProvideRationale) {
            Log.i(TAG, "Displaying permission rationale to provide additional context.");
            Snackbar.make(
                    findViewById(R.id.activity_main),
                    R.string.permission_rationale,
                    Snackbar.LENGTH_INDEFINITE)
                    .setAction(R.string.ok, new View.OnClickListener() {
                        @Override                        public void onClick(View view) {
                            // Request permission                            ActivityCompat.requestPermissions(MainActivity.this,
                                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                    REQUEST_PERMISSIONS_REQUEST_CODE);
                        }
                    })
                    .show();
        } else {
            Log.i(TAG, "Requesting permission");
            // Request permission. It's possible this can be auto answered if device policy            // sets the permission in a given state or the user denied the permission            // previously and checked "Never ask again".            ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    REQUEST_PERMISSIONS_REQUEST_CODE);
        }
    }

    /**     * Callback received when a permissions request has been completed.     */    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        Log.i(TAG, "onRequestPermissionResult");
        if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
            if (grantResults.length <= 0) {
                // If user interaction was interrupted, the permission request is cancelled and you                // receive empty arrays.                Log.i(TAG, "User interaction was cancelled.");
            } else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission was granted.                mService.requestLocationUpdates();
            } else {
                // Permission denied.                setButtonsState(false);
                Snackbar.make(
                        findViewById(R.id.activity_main),
                        R.string.permission_denied_explanation,
                        Snackbar.LENGTH_INDEFINITE)
                        .setAction(R.string.settings, new View.OnClickListener() {
                            @Override                            public void onClick(View view) {
                                // Build intent that displays the App settings screen.                                Intent intent = new Intent();
                                intent.setAction(
                                        Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                Uri uri = Uri.fromParts("package",
                                        BuildConfig.APPLICATION_ID, null);
                                intent.setData(uri);
                                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                startActivity(intent);
                            }
                        })
                        .show();
            }
        }
    }

    /**     * Receiver for broadcasts sent by {@link LocationService}.     */    private class MyReceiver extends BroadcastReceiver {
        @Override        public void onReceive(Context context, Intent intent) {
            Location location = intent.getParcelableExtra(LocationService.EXTRA_LOCATION);
            if (location != null) {
                Toast.makeText(MainActivity.this, Utils.getLocationText(location),
                        Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
        // Update the buttons state depending on whether location updates are being requested.        if (s.equals(Utils.KEY_REQUESTING_LOCATION_UPDATES)) {
            setButtonsState(sharedPreferences.getBoolean(Utils.KEY_REQUESTING_LOCATION_UPDATES,
                    false));
        }
    }

    private void setButtonsState(boolean requestingLocationUpdates) {
        if (requestingLocationUpdates) {
            mRequestLocationUpdatesButton.setEnabled(false);
            mRemoveLocationUpdatesButton.setEnabled(true);
        } else {
            mRequestLocationUpdatesButton.setEnabled(true);
            mRemoveLocationUpdatesButton.setEnabled(false);
        }
    }
}

===============end acticity ======

3. Crearte Xml  activity_main


<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_height="match_parent"    android:layout_width="match_parent"    android:orientation="vertical"    android:id="@+id/activity_main"    tools:context=".MainActivity">
    <Button        android:id="@+id/request_location_updates_button"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="@string/request_location_updates" />

    <Button        android:id="@+id/remove_location_updates_button"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="@string/remove_location_updates" />

</LinearLayout>
 
=============end xml =================================
 
4. careat service calss  LocationService
 
import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.location.Location;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.google.android.gms.location.FusedLocationProviderClient;
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.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;

public class LocationService extends Service {

    private static final String PACKAGE_NAME =
            "com.nagraj.autocompletedemo";

    private static final String TAG = LocationService.class.getSimpleName();

    /**     * The name of the channel for notifications.     */    private static final String CHANNEL_ID = "channel_01";

    static final String ACTION_BROADCAST = PACKAGE_NAME + ".broadcast";

    static final String EXTRA_LOCATION = PACKAGE_NAME + ".location";
    private static final String EXTRA_STARTED_FROM_NOTIFICATION = PACKAGE_NAME +
            ".started_from_notification";

    private final IBinder mBinder = new LocalBinder();

    /**     * The desired interval for location updates. Inexact. Updates may be more or less frequent.     */    private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;

    /**     * The fastest rate for active location updates. Updates will never be more frequent     * than this value.     */    private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
            UPDATE_INTERVAL_IN_MILLISECONDS / 2;

    /**     * The identifier for the notification displayed for the foreground service.     */    private static final int NOTIFICATION_ID = 12345678;

    /**     * Used to check whether the bound activity has really gone away and not unbound as part of an     * orientation change. We create a foreground service notification only if the former takes     * place.     */    private boolean mChangingConfiguration = false;

    private NotificationManager mNotificationManager;

    /**     * Contains parameters used by {@link com.google.android.gms.location.FusedLocationProviderApi}.     */    private LocationRequest mLocationRequest;

    /**     * Provides access to the Fused Location Provider API.     */    private FusedLocationProviderClient mFusedLocationClient;

    /**     * Callback for changes in location.     */    private LocationCallback mLocationCallback;

    private Handler mServiceHandler;

    /**     * The current location.     */    private Location mLocation;

    public LocationService() {
    }

    @Override    public void onCreate() {
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        mLocationCallback = new LocationCallback() {
            @Override            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
                onNewLocation(locationResult.getLastLocation());
            }
        };

        createLocationRequest();
        getLastLocation();

        HandlerThread handlerThread = new HandlerThread(TAG);
        handlerThread.start();
        mServiceHandler = new Handler(handlerThread.getLooper());
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        // Android O requires a Notification Channel.        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = getString(R.string.app_name);
            // Create the channel for the notification            NotificationChannel mChannel =
                    new NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_DEFAULT);

            // Set the Notification Channel for the Notification Manager.            mNotificationManager.createNotificationChannel(mChannel);
        }
    }

    @Override    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "Service started");
        boolean startedFromNotification = intent.getBooleanExtra(EXTRA_STARTED_FROM_NOTIFICATION,
                false);

        // We got here because the user decided to remove location updates from the notification.        if (startedFromNotification) {
            removeLocationUpdates();
            stopSelf();
        }
        // Tells the system to not try to recreate the service after it has been killed.        return START_NOT_STICKY;
    }

    @Override    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mChangingConfiguration = true;
    }

    @Override    public IBinder onBind(Intent intent) {
        // Called when a client (MainActivity in case of this sample) comes to the foreground        // and binds with this service. The service should cease to be a foreground service        // when that happens.        Log.i(TAG, "in onBind()");
        stopForeground(true);
        mChangingConfiguration = false;
        return mBinder;
    }

    @Override    public void onRebind(Intent intent) {
        // Called when a client (MainActivity in case of this sample) returns to the foreground        // and binds once again with this service. The service should cease to be a foreground        // service when that happens.        Log.i(TAG, "in onRebind()");
        stopForeground(true);
        mChangingConfiguration = false;
        super.onRebind(intent);
    }

    @Override    public boolean onUnbind(Intent intent) {
        Log.i(TAG, "Last client unbound from service");

        // Called when the last client (MainActivity in case of this sample) unbinds from this        // service. If this method is called due to a configuration change in MainActivity, we        // do nothing. Otherwise, we make this service a foreground service.        if (!mChangingConfiguration && Utils.requestingLocationUpdates(this)) {
            Log.i(TAG, "Starting foreground service");

            startForeground(NOTIFICATION_ID, getNotification());
        }
        return true; // Ensures onRebind() is called when a client re-binds.    }

    @Override    public void onDestroy() {
        mServiceHandler.removeCallbacksAndMessages(null);
    }

    /**     * Makes a request for location updates. Note that in this sample we merely log the     * {@link SecurityException}.     */    public void requestLocationUpdates() {
        Log.i(TAG, "Requesting location updates");
        Utils.setRequestingLocationUpdates(this, true);
        startService(new Intent(getApplicationContext(), LocationService.class));
        try {
            mFusedLocationClient.requestLocationUpdates(mLocationRequest,
                    mLocationCallback, Looper.myLooper());
        } catch (SecurityException unlikely) {
            Utils.setRequestingLocationUpdates(this, false);
            Log.e(TAG, "Lost location permission. Could not request updates. " + unlikely);
        }
    }

    /**     * Removes location updates. Note that in this sample we merely log the     * {@link SecurityException}.     */    public void removeLocationUpdates() {
        Log.i(TAG, "Removing location updates");
        try {
            mFusedLocationClient.removeLocationUpdates(mLocationCallback);
            Utils.setRequestingLocationUpdates(this, false);
            stopSelf();
        } catch (SecurityException unlikely) {
            Utils.setRequestingLocationUpdates(this, true);
            Log.e(TAG, "Lost location permission. Could not remove updates. " + unlikely);
        }
    }

    /**     * Returns the {@link NotificationCompat} used as part of the foreground service.     */    private Notification getNotification() {
        Intent intent = new Intent(this, LocationService.class);

        CharSequence text = Utils.getLocationText(mLocation);

        // Extra to help us figure out if we arrived in onStartCommand via the notification or not.        intent.putExtra(EXTRA_STARTED_FROM_NOTIFICATION, true);

        // The PendingIntent that leads to a call to onStartCommand() in this service.        PendingIntent servicePendingIntent = PendingIntent.getService(this, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        // The PendingIntent to launch activity.        PendingIntent activityPendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, MainActivity.class), 0);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .addAction(R.mipmap.ic_launcher, getString(R.string.launch_activity),
                        activityPendingIntent)
                .addAction(R.mipmap.ic_launcher, getString(R.string.remove_location_updates),
                        servicePendingIntent)
                .setContentText(text)
                .setContentTitle(Utils.getLocationTitle(this))
                .setOngoing(true)
                .setPriority(Notification.PRIORITY_HIGH)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setTicker(text)
                .setWhen(System.currentTimeMillis());

        // Set the Channel ID for Android O.        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            builder.setChannelId(CHANNEL_ID); // Channel ID        }

        return builder.build();
    }

    private void getLastLocation() {
        try {
            mFusedLocationClient.getLastLocation()
                    .addOnCompleteListener(new OnCompleteListener<Location>() {
                        @Override                        public void onComplete(@NonNull Task<Location> task) {
                            if (task.isSuccessful() && task.getResult() != null) {
                                mLocation = task.getResult();
                            } else {
                                Log.w(TAG, "Failed to get location.");
                            }
                        }
                    });
        } catch (SecurityException unlikely) {
            Log.e(TAG, "Lost location permission." + unlikely);
        }
    }

    private void onNewLocation(Location location) {
        Log.i(TAG, "New location: " + location);

        mLocation = location;

        // Notify anyone listening for broadcasts about the new location.        Intent intent = new Intent(ACTION_BROADCAST);
        intent.putExtra(EXTRA_LOCATION, location);
        LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);

        // Update notification content if running as a foreground service.        if (serviceIsRunningInForeground(this)) {
            mNotificationManager.notify(NOTIFICATION_ID, getNotification());
        }
    }

    /**     * Sets the location request parameters.     */    private void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    /**     * Class used for the client Binder.  Since this service runs in the same process as its     * clients, we don't need to deal with IPC.     */    public class LocalBinder extends Binder {
        LocationService getService() {
            return LocationService.this;
        }
    }

    /**     * Returns true if this is a foreground service.     *     * @param context The {@link Context}.     */    public boolean serviceIsRunningInForeground(Context context) {
        ActivityManager manager = (ActivityManager) context.getSystemService(
                Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(
                Integer.MAX_VALUE)) {
            if (getClass().getName().equals(service.service.getClassName())) {
                if (service.foreground) {
                    return true;
                }
            }
        }
        return false;
    }
}
 
====================end service =====================
 
 5. add AndroidManifest  file 
 
 I. Permission
 
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
 <!-- Required for foreground services on P+. --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
 
 II. Service
 
<application    
    <!-- Foreground services in Q+ require type. -->    <service        android:name=".LocationService"        android:enabled="true"        android:exported="true"        android:foregroundServiceType="location" />
</application>
 
 ======================end manifest =======
 
6. create Utils class 
 

import android.content.Context;
import android.location.Location;
import android.preference.PreferenceManager;

import java.text.DateFormat;
import java.util.Date;

public class Utils {

    static final String KEY_REQUESTING_LOCATION_UPDATES = "requesting_locaction_updates";

    /**     * Returns true if requesting location updates, otherwise returns false.     *     * @param context The {@link Context}.     */    static boolean requestingLocationUpdates(Context context) {
        return PreferenceManager.getDefaultSharedPreferences(context)
                .getBoolean(KEY_REQUESTING_LOCATION_UPDATES, false);
    }

    /**     * Stores the location updates state in SharedPreferences.     * @param requestingLocationUpdates The location updates state.     */    static void setRequestingLocationUpdates(Context context, boolean requestingLocationUpdates) {
        PreferenceManager.getDefaultSharedPreferences(context)
                .edit()
                .putBoolean(KEY_REQUESTING_LOCATION_UPDATES, requestingLocationUpdates)
                .apply();
    }

    /**     * Returns the {@code location} object as a human readable string.     * @param location  The {@link Location}.     */    static String getLocationText(Location location) {
        return location == null ? "Unknown location" :
                "(" + location.getLatitude() + ", " + location.getLongitude() + ")";
    }

    static String getLocationTitle(Context context) {
        return context.getString(R.string.location_updated,
                DateFormat.getDateTimeInstance().format(new Date()));
    }
}

 =================end utils =======

7. String file

<string name="launch_activity">Launch activity</string>
<string name="location_unknown">Location unknown</string>
<string name="location_updates_label">Location Updates</string>

<string name="permission_rationale">Location permission is needed for core functionality</string>
<string name="permission_denied_explanation">Permission was denied, but is needed for core
    functionality.</string>
<string name="settings">Settings</string>
<string name="ok">OK</string>
<string name="request_location_updates">Request location updates</string>
<string name="remove_location_updates">Remove location updates</string>

<string name="location_updated">Location Updated: %1$s</string>
 
=====================end string ===== 

=============================

1.  MainActivity
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;
import android.view.View;

import com.google.android.material.snackbar.Snackbar;

public class MainActivity extends AppCompatActivity {


    String TAG = MainActivity.class.getSimpleName();
    // Used in checking for runtime permissions.    private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;


    // A reference to the service used to get location updates.    private LocationService mService = null;

    // Tracks the bound state of the service.    private boolean mBound = false;

    // Monitors the state of the connection to the service.    private final ServiceConnection mServiceConnection = new ServiceConnection() {

        @Override        public void onServiceConnected(ComponentName name, IBinder service) {
            LocationService.LocalBinder binder = (LocationService.LocalBinder) service;
            mService = binder.getService();
            mBound = true;
            mService.requestLocationUpdates();
        }

        @Override        public void onServiceDisconnected(ComponentName name) {
            mService = null;
            mBound = false;
            mService.removeLocationUpdates();
        }
    };

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

    @Override    protected void onStart() {
        super.onStart();
        // Bind to the service. If the service is in foreground mode, this signals to the service        // that since this activity is in the foreground, the service can exit foreground mode.        bindService(new Intent(this, LocationService.class), mServiceConnection,
                Context.BIND_AUTO_CREATE);

        // Check that the user hasn't revoked permissions by going to Settings.        if (!checkPermissions()) {
            requestPermissions();
        }
    }

    @Override    protected void onResume() {
        super.onResume();
    }

    @Override    protected void onStop() {
        super.onStop();
        if (mBound) {
            // Unbind from the service. This signals to the service that this activity is no longer            // in the foreground, and the service can respond by promoting itself to a foreground            // service.            unbindService(mServiceConnection);
            mBound = false;
        }
    }

    @Override    protected void onDestroy() {
        super.onDestroy();
        mService.removeLocationUpdates();
        if (mBound) {
            // Unbind from the service. This signals to the service that this activity is no longer            // in the foreground, and the service can respond by promoting itself to a foreground            // service.            unbindService(mServiceConnection);
            mBound = false;
        }
    }

    /**     * Returns the current state of the permissions needed.     */    private boolean checkPermissions() {
        return PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION);
    }

    private void requestPermissions() {
        boolean shouldProvideRationale =
                ActivityCompat.shouldShowRequestPermissionRationale(this,
                        Manifest.permission.ACCESS_FINE_LOCATION);

        // Provide an additional rationale to the user. This would happen if the user denied the        // request previously, but didn't check the "Don't ask again" checkbox.        if (shouldProvideRationale) {
            Log.i(TAG, "Displaying permission rationale to provide additional context.");
            Snackbar.make(
                    findViewById(R.id.activity_main),
                    R.string.permission_rationale,
                    Snackbar.LENGTH_INDEFINITE)
                    .setAction(R.string.ok, new View.OnClickListener() {
                        @Override                        public void onClick(View view) {
                            // Request permission                            ActivityCompat.requestPermissions(MainActivity.this,
                                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                    REQUEST_PERMISSIONS_REQUEST_CODE);
                        }
                    })
                    .show();
        } else {
            Log.i(TAG, "Requesting permission");
            // Request permission. It's possible this can be auto answered if device policy            // sets the permission in a given state or the user denied the permission            // previously and checked "Never ask again".            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    REQUEST_PERMISSIONS_REQUEST_CODE);
        }
    }

    /**     * Callback received when a permissions request has been completed.     */    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        Log.i(TAG, "onRequestPermissionResult");
        if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
            if (grantResults.length <= 0) {
                // If user interaction was interrupted, the permission request is cancelled and you                // receive empty arrays.                Log.i(TAG, "User interaction was cancelled.");
            } else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission was granted.                mService.requestLocationUpdates();
            } else {
                // Permission denied.                Snackbar.make(
                        findViewById(R.id.activity_main),
                        R.string.permission_denied_explanation,
                        Snackbar.LENGTH_INDEFINITE)
                        .setAction(R.string.settings, new View.OnClickListener() {
                            @Override                            public void onClick(View view) {
                                // Build intent that displays the App settings screen.                                Intent intent = new Intent();
                                intent.setAction(
                                        Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                Uri uri = Uri.fromParts("package",
                                        BuildConfig.APPLICATION_ID, null);
                                intent.setData(uri);
                                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                startActivity(intent);
                            }
                        })
                        .show();
            }
        }
    }
}

=================================

2.   LocationService

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.res.Configuration;
import android.location.Location;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.google.android.gms.location.FusedLocationProviderClient;
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.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;

import java.text.DateFormat;
import java.util.Date;

import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST;

public class LocationService extends Service {

    private static final String PACKAGE_NAME =
            "om.nagraj.ml";

    private static final String TAG = LocationService.class.getSimpleName();

    /**     * The name of the channel for notifications.     */    private static final String CHANNEL_ID = "channel_01";

    static final String ACTION_BROADCAST = PACKAGE_NAME + ".broadcast";

    static final String EXTRA_LOCATION = PACKAGE_NAME + ".location";
    private static final String EXTRA_STARTED_FROM_NOTIFICATION = PACKAGE_NAME +
            ".started_from_notification";

    private final IBinder mBinder = new LocalBinder();

    /**     * The desired interval for location updates. Inexact. Updates may be more or less frequent.     */    private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;

    /**     * The fastest rate for active location updates. Updates will never be more frequent     * than this value.     */    private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
            UPDATE_INTERVAL_IN_MILLISECONDS / 2;

    /**     * The identifier for the notification displayed for the foreground service.     */    private static final int NOTIFICATION_ID = 12345678;

    /**     * Used to check whether the bound activity has really gone away and not unbound as part of an     * orientation change. We create a foreground service notification only if the former takes     * place.     */    private boolean mChangingConfiguration = false;

    private NotificationManager mNotificationManager;

    /**     * Contains parameters used by {@link com.google.android.gms.location.FusedLocationProviderApi}.     */    private LocationRequest mLocationRequest;

    /**     * Provides access to the Fused Location Provider API.     */    private FusedLocationProviderClient mFusedLocationClient;

    /**     * Callback for changes in location.     */    private LocationCallback mLocationCallback;

    private Handler mServiceHandler;

    /**     * The current location.     */    private Location mLocation;

    public LocationService() {
    }

    @Override    public void onCreate() {
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        mLocationCallback = new LocationCallback() {
            @Override            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
                onNewLocation(locationResult.getLastLocation());
            }
        };

        createLocationRequest();
        getLastLocation();

        HandlerThread handlerThread = new HandlerThread(TAG);
        handlerThread.start();
        mServiceHandler = new Handler(handlerThread.getLooper());
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        // Android O requires a Notification Channel.        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = getString(R.string.app_name);
            // Create the channel for the notification            NotificationChannel mChannel =
                    new NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_DEFAULT);

            // Set the Notification Channel for the Notification Manager.            mNotificationManager.createNotificationChannel(mChannel);
        }
    }

    @Override    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "Service started");
        boolean startedFromNotification = intent.getBooleanExtra(EXTRA_STARTED_FROM_NOTIFICATION,
                false);

        // We got here because the user decided to remove location updates from the notification.        if (startedFromNotification) {
            removeLocationUpdates();
            stopSelf();
        }
        // Tells the system to not try to recreate the service after it has been killed.        return START_NOT_STICKY;
    }

    @Override    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mChangingConfiguration = true;
    }

    @Override    public IBinder onBind(Intent intent) {
        // Called when a client (MainActivity in case of this sample) comes to the foreground        // and binds with this service. The service should cease to be a foreground service        // when that happens.        Log.i(TAG, "in onBind()");
        stopForeground(true);
        mChangingConfiguration = false;
        return mBinder;
    }

    @Override    public void onRebind(Intent intent) {
        // Called when a client (MainActivity in case of this sample) returns to the foreground        // and binds once again with this service. The service should cease to be a foreground        // service when that happens.        Log.i(TAG, "in onRebind()");
        stopForeground(true);
        mChangingConfiguration = false;
        super.onRebind(intent);
    }

    @Override    public boolean onUnbind(Intent intent) {
        Log.i(TAG, "Last client unbound from service");

        // Called when the last client (MainActivity in case of this sample) unbinds from this        // service. If this method is called due to a configuration change in MainActivity, we        // do nothing. Otherwise, we make this service a foreground service.
        if (!mChangingConfiguration) {
            Log.i(TAG, "Starting foreground service");

            startForeground(NOTIFICATION_ID, getNotification());
            //startForeground(NOTIFICATION_ID, null,getServiceType());        }
        return true; // Ensures onRebind() is called when a client re-binds.    }

    @Override    public void onDestroy() {
        mServiceHandler.removeCallbacksAndMessages(null);
    }

    /**     * Makes a request for location updates. Note that in this sample we merely log the     * {@link SecurityException}.     */    public void requestLocationUpdates() {
        Log.i(TAG, "Requesting location updates");
        //Utils.setRequestingLocationUpdates(this, true);        startService(new Intent(getApplicationContext(), LocationService.class));
        try {
            mFusedLocationClient.requestLocationUpdates(mLocationRequest,
                    mLocationCallback, Looper.myLooper());
        } catch (SecurityException unlikely) {
           // Utils.setRequestingLocationUpdates(this, false);            Log.e(TAG, "Lost location permission. Could not request updates. " + unlikely);
        }
    }

    /**     * Removes location updates. Note that in this sample we merely log the     * {@link SecurityException}.     */    public void removeLocationUpdates() {
        Log.i(TAG, "Removing location updates");
        try {
            mFusedLocationClient.removeLocationUpdates(mLocationCallback);
            //Utils.setRequestingLocationUpdates(this, false);            stopSelf();
        } catch (SecurityException unlikely) {
           // Utils.setRequestingLocationUpdates(this, true);            Log.e(TAG, "Lost location permission. Could not remove updates. " + unlikely);
        }
    }

    /**     * Returns the {@link NotificationCompat} used as part of the foreground service.     */    private Notification getNotification() {
        Intent intent = new Intent(this, LocationService.class);

        String text = String.valueOf(mLocation.getLatitude() + mLocation.getLongitude());

        // Extra to help us figure out if we arrived in onStartCommand via the notification or not.        intent.putExtra(EXTRA_STARTED_FROM_NOTIFICATION, true);

        // The PendingIntent that leads to a call to onStartCommand() in this service.        PendingIntent servicePendingIntent = PendingIntent.getService(this, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        // The PendingIntent to launch activity.        PendingIntent activityPendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, MainActivity.class), 0);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .addAction(R.mipmap.ic_launcher, getString(R.string.launch_activity),
                        activityPendingIntent)
                .addAction(R.mipmap.ic_launcher, getString(R.string.remove_location_updates),
                        servicePendingIntent)
                .setContentText(text)
                .setContentTitle(getString(R.string.location_updated,DateFormat.getDateTimeInstance().format(new Date())))
                .setOngoing(true)
                .setPriority(Notification.PRIORITY_HIGH)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setTicker(text)
                .setWhen(System.currentTimeMillis());

        // Set the Channel ID for Android O.        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            builder.setChannelId(CHANNEL_ID); // Channel ID        }

        return builder.build();
    }

    private void getLastLocation() {
        try {
            mFusedLocationClient.getLastLocation()
                    .addOnCompleteListener(new OnCompleteListener<Location>() {
                        @Override                        public void onComplete(@NonNull Task<Location> task) {
                            if (task.isSuccessful() && task.getResult() != null) {
                                mLocation = task.getResult();
                            } else {
                                Log.w(TAG, "Failed to get location.");
                            }
                        }
                    });
        } catch (SecurityException unlikely) {
            Log.e(TAG, "Lost location permission." + unlikely);
        }
    }

    private void onNewLocation(Location location) {
        Log.i(TAG, "New location: " + location);

        mLocation = location;

         //Notify anyone listening for broadcasts about the new location.        Intent intent = new Intent(ACTION_BROADCAST);
        intent.putExtra(EXTRA_LOCATION, location);
        LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);

    }

    /**     * Sets the location request parameters.     */    private void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    /**     * Class used for the client Binder.  Since this service runs in the same process as its     * clients, we don't need to deal with IPC.     */    public class LocalBinder extends Binder {
        LocationService getService() {
            return LocationService.this;
        }
    }

    protected int getServiceType() {
        return FOREGROUND_SERVICE_TYPE_MANIFEST;
    }
}




==============*****================



Thanks all









Share:

No comments:

Post a Comment

Powered by Blogger.

Recent Posts

Unordered List

  • Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
  • Aliquam tincidunt mauris eu risus.
  • Vestibulum auctor dapibus neque.

Theme Support

Need our help to upload or customize this blogger template? Contact me with details about the theme customization you need.