Background service in android 10 to get location in every 10 minutes - android

I have facing issue in Android 10 to get location in every 10 minutes when app in background or app is killed. Till android 9 pie everything is working correct but in android 10 when app goes in background in few seconds onDestory() method is called in service and service is destroying. How can i reslove this issue and start service in background. Here is my service class :
public class LocaionTrackingService extends Service {
private static final String TAG = "LocaionTrackingService";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = Common.LOCATION_TIME_INTERVAL;
private static final float LOCATION_DISTANCE = 0;
private Context mContext;
boolean checkGPS = false;
boolean checkNetwork = false;
Location loc;
public static final int notify = Common.LOCATION_TIME_INTERVAL; //interval between two services(Here Service run every 5 Minute)
private Handler mHandler = new Handler(); //run on another Thread to avoid crash
private Timer mTimer = null;
private class LocationListener implements android.location.LocationListener {
Location mLastLocation;
public LocationListener(String provider) {
Common.printLog(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}
#Override
public void onLocationChanged(Location location) {
if (location != null) {
Common.printLog(TAG, "onLocationChanged: " + location + "\n" + "Lat:" + location.getLatitude() + "\nLang:" + location.getLongitude());
mLastLocation.set(location);
try {
Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
List<Address> addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
if (addresses.size() > 0) {
String address = Common.getFullAddressFromGeoCoder(addresses.get(0));
PreferenceData.setLocationData(String.valueOf(location.getLatitude()), String.valueOf(location.getLongitude()), address);
Common.printLog(TAG, "->address" + address);
}
sendLatLong(location.getLatitude() + "", location.getLongitude() + "", PreferenceData.getAddress(), Common.isGPSON(getApplicationContext()) ? "1" : "0");
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public void onProviderDisabled(String provider) {
Common.printLog(TAG, "onProviderDisabled: " + provider);
}
#Override
public void onProviderEnabled(String provider) {
Common.printLog(TAG, "onProviderEnabled: " + provider);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Common.printLog(TAG, "onStatusChanged: " + provider);
}
}
LocationListener[] mLocationListeners = new LocationListener[]{
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};
#Override
public IBinder onBind(Intent arg0) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Common.printLog(TAG, "onStartCommand");
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public void onCreate() {
Common.printLog(TAG, "onCreate");
initializeLocationManager();
setLastLocation();
if (mTimer != null) // Cancel if already existed
mTimer.cancel();
else
mTimer = new Timer(); //recreate new
mTimer.scheduleAtFixedRate(new TimeDisplay(), 0, notify); //Schedule task
}
void getAddressfromGeocoder(double Latitude, double Longitude) {
try {
Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
List<Address> addresses = null;
addresses = geocoder.getFromLocation(Latitude, Longitude, 1);
if (addresses.size() > 0) {
String address = Common.getFullAddressFromGeoCoder(addresses.get(0));
PreferenceData.setLocationData(String.valueOf(Latitude), String.valueOf(Longitude), address);
Common.printLog(TAG, "tag->getAddressfromGeocoder :" + address + "\nLatitude" + Latitude + "\nLongitude" + Longitude);
}
} catch (IOException e) {
e.printStackTrace();
}
}
void setLastLocation() {
try {
if (!checkGPS && !checkNetwork) {
//Toast.makeText(mContext, "No Service Provider is available", Toast.LENGTH_SHORT).show();
} else {
if (checkGPS && !PreferenceData.getLastLAN().equals("") && !PreferenceData.getLastLAT().equals("")) {
Common.printLog(TAG, "check For GPS");
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[0]);
if (mLocationListeners != null) {
loc = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc != null) {
getAddressfromGeocoder(loc.getLatitude(), loc.getLongitude());
}
}
} else if (checkNetwork) {
Common.printLog(TAG, "check For Network");
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
if (mLocationListeners != null) {
loc = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (loc != null) {
getAddressfromGeocoder(loc.getLatitude(), loc.getLongitude());
}
}
}
}
} catch (java.lang.SecurityException ex) {
Common.printLog(TAG, "fail to request location update, ignore" + ex);
} catch (IllegalArgumentException ex) {
Common.printLog(TAG, "gps provider does not exist " + ex.getMessage());
}
}
#Override
public void onDestroy() {
Common.printLog(TAG, "onDestroy");
super.onDestroy();
mTimer.cancel();
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
try {
mLocationManager.removeUpdates(mLocationListeners[i]);
} catch (Exception ex) {
Common.printLog(TAG, "fail to remove location listners, ignore" + ex);
}
}
}
}
private void initializeLocationManager() {
Common.printLog(TAG, "initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
// get GPS status
checkGPS = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
// get network provider status
checkNetwork = mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
}
void sendLatLong(final String Lat, final String Long, final String address, final String isLocationOn) {
if (NetworkUtil.getConnectivityStatus(getApplicationContext()) != 0) {
String url = Common.LIVE_EMP_TRACK;
Common.printLog(TAG, "url->" + url);
StringRequest strReq = new StringRequest(Request.Method.POST,
url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Common.printLog(TAG + "->response", response);
PreferenceData.setLocationData(Lat, Long, address);
PreferenceData.setLastUpdateLocation(System.currentTimeMillis());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//Common.printLog(TAG, String.valueOf(Common.getErrorMsg(mContext, error, null)));
PreferenceData.setLastUpdateLocation(System.currentTimeMillis());
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("Latitude", Lat);
params.put("Longitude", Long);
params.put("Location", address);
params.put("isLocationOn", isLocationOn);
params.put("EmpId", PreferenceData.getUserBy());
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("API-Key", BuildConfig.KEY);
params.put("Clientip", PreferenceData.getIpAddress());
params.put("Userid", PreferenceData.getUserId());
return params;
}
};
VolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(strReq);
} else {
Common.printLog("Service", "No network");
}
}
//class TimeDisplay for handling task
class TimeDisplay extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
setLastLocation();
Common.printLog(TAG, "Location Service running-" + Calendar.getInstance().getTimeInMillis());
//Toast.makeText(LocaionTrackingService.this, "Service is running", Toast.LENGTH_SHORT).show();
sendLatLong(PreferenceData.getLastLAT(), PreferenceData.getLastLAN(), PreferenceData.getAddress(), Common.isGPSON(getApplicationContext()) ? "1" : "0");
}
});
}
}
}

Due to the android's limitations for background tasks in post-O devices, background services are destroyed by the android system if the app is in the background for some time. You should use startForeground() in onStartCommand() to start the service as a foreground service and also show the notification for the same.

Related

Making a backend API call from a service

I have a service that runs in both foreground and background to get the user location at all times, I simply use a LocalBroadCastManager to send the location from the foreground to an activity in my application and then start my API call.
How to achieve the same when the service is running in the background or when the application is closed.
The service:
public class LocationService extends Service {
private static final String TAG = "LocationService";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 0;
private static final float LOCATION_DISTANCE = 1000f;
private HandlerThread mHandlerThread;
private Handler mHandler;
private final IBinder mBinder = new MyLocalBinder();
Location mLastLocation;
private class LocationListener implements android.location.LocationListener
{
public LocationListener(String provider)
{
Helper.showLog(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}
#Override
public void onLocationChanged(Location location)
{
Helper.showLog(TAG, "onLocationChanged: " + location);
mLastLocation.set(location);
sendBroadcast();
}
#Override
public void onProviderDisabled(String provider)
{
Helper.showLog(TAG, "onProviderDisabled: " + provider);
}
#Override
public void onProviderEnabled(String provider)
{
Helper.showLog(TAG, "onProviderEnabled: " + provider);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Helper.showLog(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");
mHandlerThread = new HandlerThread("LocalServiceThread");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
initializeLocationManager();
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, "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());
}
sendBroadcast();
}
public void postRunnable(Runnable runnable) {
mHandler.post(runnable);
}
public class MyLocalBinder extends Binder {
public LocationService getService() {
return LocationService.this;
}
}
#Override
public void onDestroy()
{
Helper.showLog(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 listeners, ignore", ex);
}
}
}
}
private void initializeLocationManager() {
Helper.showLog(TAG, "initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
private void sendBroadcast(){
Intent intent = new Intent ("message"); //put the same message as in the filter you used in the activity when registering the receiver
intent.putExtra("latitude",mLastLocation.getLatitude() );
intent.putExtra("longitude",mLastLocation.getLongitude() );
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}

Geofence service

I'm trying to make a service that inserts the location of a device in a database and when the device is outside of a list of geofences it sends another message to the server. Right now I only have the part where the service sends the location to the server.
Here's what I have:
public class UbicacionEmisor extends Service {
private static final String TAG = "BOOMBOOMTESTGPS";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 10000;
private static final float LOCATION_DISTANCE = 0;
private SOService mService;
SharedPreferences preferences;
SharedPreferences.Editor editor;
private static final String PREF_NAME = "decaught-preferences";
private List<GeofenceR> geofenceRList = new ArrayList<>();
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);
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
String date = f.format(new Date());
editor.putString("latitude", String.valueOf(location.getLatitude()));
editor.putString("longitude", String.valueOf(location.getLongitude()));
editor.apply();
//This part is used to send to the server the Location
mService.add_location("Token " + preferences.getString("token", ""), preferences.getString("imei",""), date, String.valueOf(location.getLatitude()), String.valueOf(location.getLongitude()), true).enqueue(new Callback<escoladeltreball.org.decaught.models.Location>() {
#Override
public void onResponse(Call<escoladeltreball.org.decaught.models.Location> call, Response<escoladeltreball.org.decaught.models.Location> response) {
if (response.isSuccessful()) {
Log.d("UbicationEmisor", "Ubication send");
} else {
int statusCode = response.code();
if (response.code() == 400) {
try {
Log.v("Error code 400", response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
}
}
Log.d("UbicationEmisor", "Ubication not send, error: " + statusCode);
Log.d("UbicationEmisor", "Ubication not send, error: " + response.errorBody());
// handle request errors depending on status code
}
}
#Override
public void onFailure(Call<escoladeltreball.org.decaught.models.Location> call, Throwable t) {
Log.d("RolSelectionActivity", "Error trying to connect to database");
}
});
}
#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);
preferences = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
editor = preferences.edit();
return START_STICKY;
}
#Override
public void onCreate() {
Log.e(TAG, "onCreate");
mService = ApiUtils.getSOService();
obtainGeofences();
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());
}
}
private void obtainGeofences() {
String imei = preferences.getString("imei","");
mService.listGeofence("Token " + preferences.getString("token", ""), imei).enqueue(new Callback<List<GeofenceR>>() {
#Override
public void onResponse(Call<List<GeofenceR>> call, Response<List<GeofenceR>> response) {
geofenceRList = response.body();
}
#Override
public void onFailure(Call<List<GeofenceR>> call, Throwable t) {
}
});
}
#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);
}
}
}
Any idea how to make the Geofence part? Or should I start over?
I've worked with Geofences, I really suggest you to read this Geofence Documentation and this example
Regarding your question, I'd suggest you start over again because geofences don't use LocationManager (or at least not explicitly).
You want to do something like (step list):
Define Geofence lng/lat and radius and assign exit event
mGeofenceList.add(new Geofence.Builder()
// Set the request ID of the geofence. This is a string to identify this
// geofence.
.setRequestId(entry.getKey())
.setCircularRegion(
entry.getValue().latitude,
entry.getValue().longitude,
Constants.GEOFENCE_RADIUS_IN_METERS
)
.setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_EXIT)
.build());
Define pending intent
public class MainActivity extends AppCompatActivity {
// ...
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
// calling addGeofences() and removeGeofences().
mGeofencePendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.
FLAG_UPDATE_CURRENT);
return mGeofencePendingIntent;
}
**Define the Service**
public class GeofenceTransitionsIntentService extends IntentService {
// ...
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = GeofenceErrorMessages.getErrorString(this,
geofencingEvent.getErrorCode());
Log.e(TAG, errorMessage);
return;
}
// Get the transition type.
int geofenceTransition = geofencingEvent.getGeofenceTransition();
// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
// Get the geofences that were triggered. A single event can trigger
// multiple geofences.
// HERE YOUR CODE TO SAVE THE LOCATION IN THE DB
// AND SEND THE NOTIFICATION
sendNotification(geofenceTransitionDetails);
Log.i(TAG, geofenceTransitionDetails);
} else {
// Log the error.
Log.e(TAG, getString(R.string.geofence_transition_invalid_type,
geofenceTransition));
}
}
NB
The most annoying thing of working with Geofences is Doze.
After a while you won't see anymore any notification because Doze stop it in order to save battery, so bear that in mind.
Make sure to read this before you start DOZE.
Enjoy =)

How to get location either from GPS or NETWORK providers in android

In my android app I'm retrieving user location for every 3 minutes and somehow I'm doing it in the following way.problems so far I have faced are
Whenever I'm getting location updates I'm getting multiple values at same time
Sometimes I'm getting both GPS and NETWORK provider values at a time.
I need only one value and also it should be either GPS or NETWORK Provider value,How to achieve this.
Here is my Service
public class MyService extends Service {
private static final String TAG = "TESTGPS";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 180000;
private static final float LOCATION_DISTANCE = 0.0f;
double lati,longi;
String loc_name;
private class LocationListener implements android.location.LocationListener {
Location mLastLocation;
public LocationListener(String provider) {
Log.i(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}
#Override
public void onLocationChanged(Location location) {
Log.i(TAG, "onLocationChanged: " + location);
Toast.makeText(getApplicationContext(), ""+location.getLatitude()+"==>"+location.getLongitude(), Toast.LENGTH_SHORT).show();
lati = location.getLatitude();
longi = location.getLongitude();
Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
try {
List<Address> addressList = geocoder.getFromLocation(
lati, longi, 1);
if (addressList != null && addressList.size() > 0) {
{
loc_name = addressList.get(0).getAddressLine(1);
}
AsyncHttpClient client = new AsyncHttpClient();
final RequestParams params = new RequestParams();
params.put("sendingJSON", composeLocation());
Toast.makeText(getApplicationContext(), "" + params, Toast.LENGTH_LONG).show();
client.post("http://192.168.0.120/gpstracker/send_location.php", params, new AsyncHttpResponseHandler() {
public void onSuccess(String response) {
Log.i("Status ==> ", "Sent to server");
}
public void onFailure(int statusCode, Throwable error, String content) {
if (statusCode == 404) {
Toast.makeText(getApplicationContext(), "Requested resource not found", Toast.LENGTH_LONG).show();
} else if (statusCode == 500) {
Toast.makeText(getApplicationContext(), "Something went wrong at server end", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Unexpected Error occcured! [Most common Error: Device might not be connected to Internet]", Toast.LENGTH_LONG).show();
}
}
});
}
} catch (IOException e) {
e.printStackTrace();
mLastLocation.set(location);
}
}
#Override
public void onProviderDisabled(String provider) {
Log.i(TAG, "onProviderDisabled: " + provider);
}
#Override
public void onProviderEnabled(String provider) {
Log.i(TAG, "onProviderEnabled: " + provider);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.i(TAG, "onStatusChanged: " + provider);
}
}
LocationListener[] mLocationListeners = new LocationListener[]{
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};
#Override
public IBinder onBind(Intent intent) {
return null;
}
public int onStartCommand(Intent intent, int flags, int startId) {
//Toast.makeText(MyService.this, "Service Started", Toast.LENGTH_SHORT).show();
Log.i("Service Started", "Started");
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 {
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;
}
mLocationManager.removeUpdates(mLocationListeners[i]);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listners, ignore", ex);
}
}
}
}
private void initializeLocationManager() {
Log.i(TAG, "initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
public String composeLocation()
{
ArrayList<HashMap<String, String>> locationList = new ArrayList();
HashMap<String, String> map = new HashMap();
String parsed_lati = String.valueOf(lati);
String parsed_longi = String.valueOf(longi);
map.put("e1", "123");
map.put("lati",parsed_lati);
map.put("longi",parsed_longi);
map.put("loc_name",loc_name);
locationList.add(map);
return new GsonBuilder().create().toJson(locationList);
}
}
You should first check before getting location from both. First check if location is available through gps and if not then use network to get location.
Here is a sample class which have methods for checking location.
public class GPSTracker extends Service implements LocationListener {
private final Context context;
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
public boolean canGetLocation = false;
Location location;
double latitude;
double longitude;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10;
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1;
protected LocationManager locationManager;
public GPSTracker(Context context) {
this.context = context;
getLocation();
}
public Location getLocation() {
try {
locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if(!isGPSEnabled && !isNetworkEnabled) {
} else {
this.canGetLocation = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
if(isGPSEnabled) {
if(location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if(locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
public void stopUsingGPS() {
if(locationManager != null) {
locationManager.removeUpdates(GPSTracker.this);
}
}
public double getLatitude() {
if(location != null) {
latitude = location.getLatitude();
}
return latitude;
}
public double getLongitude() {
if(location != null) {
longitude = location.getLongitude();
}
return longitude;
}
public boolean canGetLocation() {
return this.canGetLocation;
}
public void showSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
alertDialog.setTitle("GPS is settings");
alertDialog.setMessage("Turn on your GPS to find nearby helpers");
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
context.startActivity(intent);
}
});
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}
#Override
public void onLocationChanged(Location arg0) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
You should use Criteria to request location update instead of using Provider:
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
locationManager.requestSingleUpdate(criteria, listener, null);
That way you can use only one listener and the location value can be from either GPS or NETWORK provider.

using Service in android application

this code is work with me to take the coordination even if the application is not in use but when i switch of my phone then open my phone again it is not working in the background i need it continue working in the background. even if the user mobile pone is switched off and then it is opened again
public class Check2 extends Service
{
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
}
private static final String TAG = "GPS";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 1000*6;
private static final float LOCATION_DISTANCE = 0f;
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);
double lat = mLastLocation.getLatitude();;
double lon = mLastLocation.getLongitude();
Toast.makeText(getApplicationContext(), "Lat: "+lat+" Long: "+lon, Toast.LENGTH_LONG).show();
}
#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)
{
LocationManager loc;
loc=(LocationManager)getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
LocationListener listener =new LocationListener(TAG);
Location location ;
Log.e(TAG, "onStartCommand");
super.onStartCommand(intent, flags, startId);
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
// location = listener.mLastLocation;
location= loc.getLastKnownLocation(LocationManager.GPS_PROVIDER);
listener.onLocationChanged(location);
Log.d("is work","here");
} 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]);
location= loc.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
listener.onLocationChanged(location);
Log.d("is work", "here");
} 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());
}
return START_STICKY;
}
#Override
public void onCreate()
{
Log.e(TAG, "onCreate");
}
#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);
}
}
Create a Broadcast receiver to listen for Boot Complete event
Check this link for tutorials
Broadcast receiver for Boot Action
1 to Vivek, but also you should start your service in another process from your application. For example,
<< service
android:name=".TweetCollectorService"
android:process=":remote">
Then in your service you should add BroadcastReceiver to receive intent BOOT_COMPLETE. If you want this service to keep running no matter what, consider replacind startService method with startForeground

Android Is it a good practice to use LocationListener in a IntentService?

My app has a widget and shows information depending on the location of the device.
I would like to get the location by using a IntentService, because it destroys itself after the job is done, however the algorythm executes the
#Override
protected void onHandleIntent(Intent intent)
method and finishes. so there is no time to listen for some locations and give the info back.
is it possible to let the LocationListener wait until the
#Override
public void onLocationChanged(Location location) {
is called?
how to use properly the Looper in the
LocationManager.requestLocationUpdates(
method?
here the entire code for the IntentService:
public class GetLocation extends IntentService {
public GetLocation() {
super("GetLocation");
// TODO Auto-generated constructor stub
}
private static final String TAG = "GetLocation";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 1000;
private static final float LOCATION_DISTANCE = 10f;
private ResultReceiver resultReceiver;
public static final String RECEIVER = "receiver";
public static final String GPS = "gps";
private int result = Activity.RESULT_CANCELED;
public static String RESULT = "result";
Location mLastLocation;
private class LocationListener implements android.location.LocationListener {
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);
result = Activity.RESULT_OK;
publishResults(new double[] { mLastLocation.getLatitude(),
mLastLocation.getLongitude() }, result);
}
#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
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
Log.e(TAG, "onHandleIntent");
resultReceiver = intent.getParcelableExtra(RECEIVER);
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_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, "network 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]);
Log.i(TAG, "remove location listners");
} 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);
}
}
private void publishResults(double[] gps, int result) {
Bundle bundle = new Bundle();
bundle.putDoubleArray(GPS, gps);
bundle.putInt(RESULT, result);
resultReceiver.send(Activity.RESULT_OK, bundle);
}
}
EDIT:
I would like to add the final code for the Service that gives the coordinates to a receiver:
However, it is only the gps provider working, the network is ignored on the device (everything is activated in the settings)
public class LocationGetter extends Service {
private static final String TAG = "LocationGetter";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 1000;
private static final float LOCATION_DISTANCE = 10f;
private ResultReceiver resultReceiver;
public static final String RECEIVER = "receiver";
public static final String GPS = "gps";
private int result = Activity.RESULT_CANCELED;
public static String RESULT = "result";
Location mLastLocation;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.e(TAG, "onStartCommand");
resultReceiver = intent.getParcelableExtra(RECEIVER);
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_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, "network provider does not exist, " + ex.getMessage());
}
return super.onStartCommand(intent, flags, startId);
}
private class LocationListener implements android.location.LocationListener {
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);
result = Activity.RESULT_OK;
publishResults(new double[] { mLastLocation.getLatitude(),
mLastLocation.getLongitude() }, result);
}
#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) };
private void initializeLocationManager() {
Log.e(TAG, "initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext()
.getSystemService(Context.LOCATION_SERVICE);
}
}
private void publishResults(double[] gps, int result) {
Bundle bundle = new Bundle();
bundle.putDoubleArray(GPS, gps);
bundle.putInt(RESULT, result);
resultReceiver.send(Activity.RESULT_OK, bundle);
}
}
You had select the wrong way to go - you should use Service to listen for Location updates, because Service will not be closed after it's code have been executed.
Another way - is to subscribe some service component to Location updates via AndroidManifest.xml by defining proper IntentFilter. In this situation - it can be an IntentService, as only it's OnReceive() method will be executed.

Categories

Resources