Get GPS location via Android service

I need to track user locations using a background service and then download them and show the path to the user.

Using activity, it was pretty easy to get the GPS addresses, but when I needed to do this through the service, I ran into a problem because it only works for looper threads (or something like that).

As I searched the Internet for a solution, I found out that many people have the same problem, but I did not find a working solution. Some people say you need to use prepare-> loop-> quit, and some say you need to use handlerThread, but still I can’t figure out exactly how to do this.

+59
android service gps location
Jan 12 2018-12-12T00:
source share
7 answers

Ok, I solved this by creating an onCreate service handler and calling gps functions there.

The code is so simple:

final handler=new Handler(Looper.getMainLooper()); 

And then, to make things work in the user interface, I call post about it.

-17
Jan 12 2018-12-12T00:
source share

I don’t understand what exactly is the problem with the implementation of the location listening function in the Service. It looks very similar to what you do in Activity. Simply locate the listener and register to receive location updates. You can refer to the following code as an example:

Manifest file:

 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:label="@string/app_name" android:name=".LocationCheckerActivity" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".MyService" android:process=":my_service" /> </application> 

Service file:

 import android.app.Service; import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationManager; import android.os.Bundle; import android.os.IBinder; import android.util.Log; public class MyService extends Service { private static final String TAG = "BOOMBOOMTESTGPS"; private LocationManager mLocationManager = null; private static final int LOCATION_INTERVAL = 1000; private static final float LOCATION_DISTANCE = 10f; private class LocationListener implements android.location.LocationListener { Location mLastLocation; public LocationListener(String provider) { Log.e(TAG, "LocationListener " + provider); mLastLocation = new Location(provider); } @Override public void onLocationChanged(Location location) { Log.e(TAG, "onLocationChanged: " + location); mLastLocation.set(location); } @Override public void onProviderDisabled(String provider) { Log.e(TAG, "onProviderDisabled: " + provider); } @Override public void onProviderEnabled(String provider) { Log.e(TAG, "onProviderEnabled: " + provider); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { Log.e(TAG, "onStatusChanged: " + provider); } } LocationListener[] mLocationListeners = new LocationListener[]{ new LocationListener(LocationManager.GPS_PROVIDER), new LocationListener(LocationManager.NETWORK_PROVIDER) }; @Override public IBinder onBind(Intent arg0) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "onStartCommand"); super.onStartCommand(intent, flags, startId); return START_STICKY; } @Override public void onCreate() { Log.e(TAG, "onCreate"); initializeLocationManager(); try { mLocationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE, mLocationListeners[1]); } catch (java.lang.SecurityException ex) { Log.i(TAG, "fail to request location update, ignore", ex); } catch (IllegalArgumentException ex) { Log.d(TAG, "network provider does not exist, " + ex.getMessage()); } try { mLocationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE, mLocationListeners[0]); } catch (java.lang.SecurityException ex) { Log.i(TAG, "fail to request location update, ignore", ex); } catch (IllegalArgumentException ex) { Log.d(TAG, "gps provider does not exist " + ex.getMessage()); } } @Override public void onDestroy() { Log.e(TAG, "onDestroy"); super.onDestroy(); if (mLocationManager != null) { for (int i = 0; i < mLocationListeners.length; i++) { try { mLocationManager.removeUpdates(mLocationListeners[i]); } catch (Exception ex) { Log.i(TAG, "fail to remove location listners, ignore", ex); } } } } private void initializeLocationManager() { Log.e(TAG, "initializeLocationManager"); if (mLocationManager == null) { mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE); } } } 
+53
Jan 12 2018-12-12T00
source share
 public class GPSService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener { private LocationRequest mLocationRequest; private GoogleApiClient mGoogleApiClient; private static final String LOGSERVICE = "#######"; @Override public void onCreate() { super.onCreate(); buildGoogleApiClient(); Log.i(LOGSERVICE, "onCreate"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(LOGSERVICE, "onStartCommand"); if (!mGoogleApiClient.isConnected()) mGoogleApiClient.connect(); return START_STICKY; } @Override public void onConnected(Bundle bundle) { Log.i(LOGSERVICE, "onConnected" + bundle); Location l = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); if (l != null) { Log.i(LOGSERVICE, "lat " + l.getLatitude()); Log.i(LOGSERVICE, "lng " + l.getLongitude()); } startLocationUpdate(); } @Override public void onConnectionSuspended(int i) { Log.i(LOGSERVICE, "onConnectionSuspended " + i); } @Override public void onLocationChanged(Location location) { Log.i(LOGSERVICE, "lat " + location.getLatitude()); Log.i(LOGSERVICE, "lng " + location.getLongitude()); LatLng mLocation = (new LatLng(location.getLatitude(), location.getLongitude())); EventBus.getDefault().post(mLocation); } @Override public void onDestroy() { super.onDestroy(); Log.i(LOGSERVICE, "onDestroy - Estou sendo destruido "); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onConnectionFailed(ConnectionResult connectionResult) { Log.i(LOGSERVICE, "onConnectionFailed "); } private void initLocationRequest() { mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(5000); mLocationRequest.setFastestInterval(2000); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); } private void startLocationUpdate() { initLocationRequest(); 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; } LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); } private void stopLocationUpdate() { LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); } protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(this) .addOnConnectionFailedListener(this) .addConnectionCallbacks(this) .addApi(LocationServices.API) .build(); } } 
+21
May 24 '16 at 17:40
source share

All these answers do not work with M-to-Android "O" - 8, due to the Dozer mode, which restricts the service - any service or any background operation that requires certain things in the background will no longer work.

Thus, the approach is to listen to the FusedLocationApiClient system via BroadCastReciever, which always listens to the location and works even in Doze mode.

Posting a link will be pointless; look for FusedLocation with the Broadcast receiver.

thank

+5
Jan 29 '19 at 11:18
source share

Just complementing, I implemented this way and usually worked in a service class

In my service

 @Override public void onCreate() { mHandler = new Handler(Looper.getMainLooper()); mHandler.post(this); super.onCreate(); } @Override public void onDestroy() { mHandler.removeCallbacks(this); super.onDestroy(); } @Override public void run() { InciarGPSTracker(); } 
+1
Nov 20 '14 at 18:33
source share

Here is my solution

Step1 Register Serice in the manifest

 <receiver android:name=".MySMSBroadcastReceiver" android:exported="true"> <intent-filter> <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED" /> </intent-filter> </receiver> 

Step2 Service Code

 public class FusedLocationService extends Service { private String mLastUpdateTime = null; // bunch of location related apis private FusedLocationProviderClient mFusedLocationClient; private SettingsClient mSettingsClient; private LocationRequest mLocationRequest; private LocationSettingsRequest mLocationSettingsRequest; private LocationCallback mLocationCallback; private Location lastLocation; // location updates interval - 10sec private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 5000; // fastest updates interval - 5 sec // location updates will be received if another app is requesting the locations // than your app can handle private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 500; private DatabaseReference locationRef; private int notificationBuilder = 0; private boolean isInitRef; @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.log("LOCATION GET DURATION", "start in service"); init(); return START_STICKY; } /** * Initilize Location Apis * Create Builder if Share location true */ private void init() { mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); mSettingsClient = LocationServices.getSettingsClient(this); mLocationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { super.onLocationResult(locationResult); receiveLocation(locationResult); } }; mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS); mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder(); builder.addLocationRequest(mLocationRequest); mLocationSettingsRequest = builder.build(); startLocationUpdates(); } /** * Request Location Update */ @SuppressLint("MissingPermission") private void startLocationUpdates() { mSettingsClient .checkLocationSettings(mLocationSettingsRequest) .addOnSuccessListener(locationSettingsResponse -> { Log.log(TAG, "All location settings are satisfied. No MissingPermission"); //noinspection MissingPermission mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper()); }) .addOnFailureListener(e -> { int statusCode = ((ApiException) e).getStatusCode(); switch (statusCode) { case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: Log.loge("Location settings are not satisfied. Attempting to upgrade " + "location settings "); break; case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: Log.loge("Location settings are inadequate, and cannot be " + "fixed here. Fix in Settings."); } }); } /** * onLocationResult * on Receive Location share to other activity and save if save true * * @param locationResult */ private void receiveLocation(LocationResult locationResult) { lastLocation = locationResult.getLastLocation(); LocationInstance.getInstance().changeState(lastLocation); saveLocation(); } private void saveLocation() { String saveLocation = getsaveLocationStatus(this); if (saveLocation.equalsIgnoreCase("true") && notificationBuilder == 0) { notificationBuilder(); notificationBuilder = 1; } else if (saveLocation.equalsIgnoreCase("false") && notificationBuilder == 1) { ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).cancel(1); notificationBuilder = 0; } Log.logd("receiveLocation : Share :- " + saveLocation + ", [Lat " + lastLocation.getLatitude() + ", Lng" + lastLocation.getLongitude() + "], Time :- " + mLastUpdateTime); if (saveLocation.equalsIgnoreCase("true") || getPreviousMin() < getCurrentMin()) { setLatLng(this, lastLocation); mLastUpdateTime = DateFormat.getTimeInstance().format(new Date()); if (isOnline(this) && !getUserId(this).equalsIgnoreCase("")) { if (!isInitRef) { locationRef = getFirebaseInstance().child(getUserId(this)).child("location"); isInitRef = true; } if (isInitRef) { locationRef.setValue(new LocationModel(lastLocation.getLatitude(), lastLocation.getLongitude(), mLastUpdateTime)); } } } } private int getPreviousMin() { int previous_min = 0; if (mLastUpdateTime != null) { String[] pretime = mLastUpdateTime.split(":"); previous_min = Integer.parseInt(pretime[1].trim()) + 1; if (previous_min > 59) { previous_min = 0; } } return previous_min; } @Override public void onDestroy() { super.onDestroy(); stopLocationUpdates(); } /** * Remove Location Update */ public void stopLocationUpdates() { mFusedLocationClient .removeLocationUpdates(mLocationCallback) .addOnCompleteListener(task -> Log.logd("stopLocationUpdates : ")); } private void notificationBuilder() { if (Build.VERSION.SDK_INT >= 26) { String CHANNEL_ID = "my_channel_01"; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Channel human readable title", NotificationManager.IMPORTANCE_DEFAULT); ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel); Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("") .setContentText("").build(); startForeground(1, notification); } } @Override public IBinder onBind(Intent intent) { return null; } } 

Step 3

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

Step 4

 implementation 'com.google.android.gms:play-services-location:16.0.0' 
0
Jun 25 '19 at 10:13
source share



All Articles