I want to keep my application running in background
I have an application that sends the user's location to our server
I have the following code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LocationManager locationManager;
String context = Context.LOCATION_SERVICE;
locationManager = (LocationManager)getSystemService(context);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);
String provider = locationManager.getBestProvider(criteria, true);
updateWithNewLocation(null);
locationManager.requestLocationUpdates(provider, (10*60*1000), 10,
locationListener);
}
private final LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
updateWithNewLocation(location);
}
public void onProviderDisabled(String provider){
updateWithNewLocation(null);
}
public void onProviderEnabled(String provider){ }
public void onStatusChanged(String provider, int status,
Bundle extras){ }
};
public void updateWithNewLocation(Location location) {
if (location != null) {
Dbhelper helper = new Dbhelper(this);
final SQLiteDatabase db = helper.getWritableDatabase();
long time = System.currentTimeMillis();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss");
final String curTime = df.format(time);
final double lat = location.getLatitude();
final double lng = location.getLongitude();
final double alt = location.getAltitude();
System.out.println(lat);
System.out.println(lng);
System.out.println(alt);
db.execSQL("INSERT INTO location (longitude,latitude,altitude,tgl_buat) VALUES " +
"('"+lng+"','"+lat+"','"+alt+"','"+curTime+"')");
db.close();
/*Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask(){
#Override
public void run(){
db.execSQL("INSERT INTO location (longitude,latitude,altitude,tgl_buat) VALUES " +
"('121.2149012','-6.217837','0.0','2012-05-07 10:20:01')");
db.close();
}
}, 10*60*1000, 10*60*1000);*/
}
}
I want my applicatioin to be running in the background. I want it to launch automatically when the phone is turned on
A very simple answer for your problem is to use Service. It will allow you to perform variety of tasks while being in background and is your best bet for sending your location to server silently.
Read this answer for help.
You can keep your application running in the background using Service
I hope this link will help you
Please read the documentation for further details
Run your background logic in a Service, and if you want to give a good UX experience (and to also have an higher priority) post a Notification to status-bar (using NotificationManager).
GrabLocationDetails.java
Use this code as your GrabLocationDetails.java
public class GrabLocationDetails extends Service implements LocationListener {
double lat,lng;
private LocationManager locationManager;
private String provider;
boolean isGps;
private ArrayList<String> mList;
Context GLDContext;
public GrabLocationDetails(Context cont){
this.GLDContext=cont;
}
public GrabLocationDetails(){}
#Override
public void onCreate() {
super.onCreate();
mList = new ArrayList<String>();
isGps = false;
lat=0.0;
lng=0.0;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//super.onStart(intent, startId);
try {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean enabled = service.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!enabled) {
isGps = false;
ListAddItem(isGps);
SendBroadcast();
} else {
isGps = true;
Location location = locationManager.getLastKnownLocation(provider);
lat=(location.getLatitude());
lng=(location.getLongitude());
ListAddItem(true);
SendBroadcast();
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
} catch (Exception e) {
ListAddItem(isGps);
SendBroadcast();
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
//locationManager.removeUpdates(this);
}
public void SendBroadcast(){
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(CommandExecutionModule.LocationDetails);
broadcastIntent.putExtra("Data", mList);
sendBroadcast(broadcastIntent);
}
public void ListAddItem(boolean GPS) {
//if(!GPS)
//mList.add("0");
//else
//mList.add("1");
mList.add(Double.toString(lat));
mList.add(Double.toString(lng));
}
/**************************************************************************************************************/
#Override
public void onLocationChanged(Location location){
locationManager.requestLocationUpdates(provider, 400, 1, this);
mList.clear();
lat = (location.getLatitude());
lng = (location.getLongitude());
ListAddItem(isGps);
SendBroadcast();
locationManager.removeUpdates(this);
stopSelf();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
#Override
public void onProviderEnabled(String provider){
isGps=true;
}
#Override
public void onProviderDisabled(String provider){
isGps=false;
lat=0.0;
lng=0.0;
mList.clear();
ListAddItem(isGps);
//SendBroadcast();
}
You should use a Service and a BroadcastReceiver
Related
I'm looking a way to get distance travelled by the user. On purpose I try services like this
public class GPSService extends Service {
private LocationListener listener;
private LocationManager locationManager;
private List<Location> locationList = new ArrayList<>();
private float distancetracking = 0;
private int j = 0;
private float finaldist = 0;
String provider;
public IBinder onBind(Intent intent){
return null;
}
#SuppressLint("MissingPermission")
#Override
public void onCreate() {
super.onCreate();
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
locationList.add(location);
Intent i = new Intent("location_update");
while (j < locationList.size() - 1) {
Location loc1 = locationList.get(j);
Location loc2 = locationList.get(j + 1);
distancetracking += loc1.distanceTo(loc2);
j++;
}
Log.d("service", String.valueOf(distancetracking));
finaldist = distancetracking/1000;
i.putExtra("coordinates", finaldist);
sendBroadcast(i);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
locationManager.requestLocationUpdates(provider,0,0,listener);
}
#Override
public void onDestroy() {
super.onDestroy();
if (locationManager != null){
locationManager.removeUpdates(listener);
}
locationList.clear();
}
}
But when my app goes in background the location didn't receive any location...I was aware of some limitation but actually I didn't understand what to do. I'have to do that on purpose to calculta CO2 from the distance travelled
I'm writing an app that requests for location updates like this:
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, interval, 0, locationListener);
onLocationChanged gets invoked when device is on but when put into sleep it stops receiving further updates. I followed this thread but as I said - it doesn't work.
The listener is registered inside foreground service that needs to work all the time. I want to conserve battery by waking it from sleep only when I receive new location.
EDIT: of course everything works when I acquire wakelock in onCreate() method and release it in onDestroy() method for service but I don't want to do this.
If you want to use background task then use this service
public class LocationFinder extends Service {
public static double lat, lng;
LocationManager locationManager;
public void onDestroy() {
super.onDestroy();
if (locationManager != null && locationListener != null) {
locationManager.removeUpdates(locationListener);
}
}
#Override
public void onCreate() {
Log.v("location", "===>location ed onCreate " + lat);
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.v("location", "===>location ed onStartCommand " + lat + "==>" + lng);
new Handler().post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
getLocation();
}
});
return START_STICKY;
}
final LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
updateWithNewLocation(location);
}
public void onProviderDisabled(String provider) {
updateWithNewLocation(null);
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
private void getLocation() {
String context = Context.LOCATION_SERVICE;
locationManager = (LocationManager) getSystemService(context);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);
if (locationManager != null) {
String provider = locationManager.getBestProvider(criteria, true);
if (provider != null) {
Location location = locationManager.getLastKnownLocation(provider);
updateWithNewLocation(location);
locationManager.requestLocationUpdates(provider, 500, 50, locationListener);
} else {
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 500, 50, locationListener);
} else if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500, 50, locationListener);
} else if (locationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER)) {
locationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 500, 50, locationListener);
}
}
}
}
private void updateWithNewLocation(Location location) {
if (location != null) {
Log.v("location", "===>location ed " + lat);
lat = location.getLatitude();
lng = location.getLongitude();
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
I'm trying to program an application which is using the current location from the user and calculating the distance and writes it into my listview.
The location doesn't have to be very accurate and i only want to fetch a new location when the list is refreshed or on app start, not continously.
My problem is that the locationlistener with gps takes too long to find a location and i have to update my list a lot before it is showing the right distance.
I was thinking about implementing a background task which gets the location and updates the list automatically when it found the position. Would that be a solution?
Is there any option to get a location faster, even if it is not as accurate as gps?
what i have so far on my location listener:
public class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
lat = location.getLatitude();
lng = location.getLongitude();
myLoc.setLatitude(lat);
myLoc.setLongitude(lng);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
in this method i'm calling the locationmanager and listener and creating the listview with the distance
public void getList(){
locationManager = (LocationManager) getActivity().getSystemService(getActivity().LOCATION_SERVICE);
locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mLocationListener);
//... creating the list with distance and so on
}
i hope you can give me some hints how i can implement this that i will work as described above or tell me what i should use instead.
thanks :)
1). You can use LocationManager.NETWORK_PROVIDER
This provider determines location based on availability of cell tower and WiFi access points. Results are retrieved by means of a network lookup. Requires either of the permissions android.permission.ACCESS_COARSE_LOCATION or android.permission.ACCESS_FINE_LOCATION.
eg:- locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 500, 50, locationListener);
2). If you want to use background task then use this service
public class LocationFinder extends Service {
public static double lat, lng;
LocationManager locationManager;
public void onDestroy() {
super.onDestroy();
if (locationManager != null && locationListener != null) {
locationManager.removeUpdates(locationListener);
}
}
#Override
public void onCreate() {
Log.v("location", "===>location ed onCreate " + lat);
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.v("location", "===>location ed onStartCommand " + lat + "==>" + lng);
new Handler().post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
getLocation();
}
});
return START_STICKY;
}
final LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
updateWithNewLocation(location);
}
public void onProviderDisabled(String provider) {
updateWithNewLocation(null);
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
private void getLocation() {
String context = Context.LOCATION_SERVICE;
locationManager = (LocationManager) getSystemService(context);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);
if (locationManager != null) {
String provider = locationManager.getBestProvider(criteria, true);
if (provider != null) {
Location location = locationManager.getLastKnownLocation(provider);
updateWithNewLocation(location);
locationManager.requestLocationUpdates(provider, 500, 50, locationListener);
} else {
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 500, 50, locationListener);
} else if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500, 50, locationListener);
} else if (locationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER)) {
locationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 500, 50, locationListener);
}
}
}
}
private void updateWithNewLocation(Location location) {
if (location != null) {
Log.v("location", "===>location ed " + lat);
lat = location.getLatitude();
lng = location.getLongitude();
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
I'm trying to get GPS values every few seconds and I'm missing some trick. Here's what I've tried:
public class Locn extends ActionBarActivity
{
private LocationManager locationManager;
private String provider;
private Location loc = null;
private Criteria criteria;
... local variables ...
#Override
protected void onCreate(Bundle savedInstanceState)
{
...
// Get the location manager
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean enabled = service.isProviderEnabled(LocationManager.GPS_PROVIDER);
// Check if enabled. If not send user to the GPS settings
if (!enabled)
{
Toast.makeText(this, "Please enable GPS location service",
Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
else
{
Toast.makeText(this, "GPS location service is enabled",
Toast.LENGTH_SHORT).show();
}
// Define the criteria to select the location provider -> use default
criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
// Let Android select the best location provider based on criteria
provider = locationManager.getBestProvider(criteria, true);
...
}
//--------------------------------------
// Set up timer handlers
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable()
{
#Override
public void run()
{
provider = locationManager.getBestProvider(criteria, true);
loc = locationManager.getLastKnownLocation(provider);
milli = System.currentTimeMillis();
longitude = loc.getLongitude();
latitude = loc.getLatitude();
count++;
timerHandler.postDelayed(this, 2000);
}
};
count and milli changes every two seconds but the latitude and longitude do not change at all. (Yes, I'm changing position -- up to 2 miles)
What am I missing here? Does loc have to be cleared before calling getLastKnownLocation again?
Thanks,
Walt
Timer tm =new Timer();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
boolean enabled = service.isProviderEnabled(LocationManager.GPS_PROVIDER);
tm.schedule(new task(),10,10000);//this execute task every 10 seconds
//use the timer task in your main activity
class task extends TimerTask {
public void run() {
Home.this.runOnUiThread(new Runnable() {
public void run() {
longitude = loc.getLongitude();
latitude = loc.getLatitude();
});
}
};
You don't need a Timer. Just use LocationManager.requestLocationUpdates()
From Android documentation:
requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)
See at: Android LocationManager
Just use like below:
public class MainActivity extends Activity implements LocationListener {
private String provider;
private LocationManager lm;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
provider = lm.getBestProvider(criteria, false);
Location location = lm.getLastKnownLocation(provider);
if (location != null) {
onLocationChanged(location);
}
}
#Override
protected void onResume() {
super.onResume();
lm.requestLocationUpdates(provider, 1000, 10, this);
}
#Override
protected void onPause() {
super.onPause();
lm.removeUpdates(this);
}
#Override
protected boolean isRouteDisplayed() {
return false;
}
public void onLocationChanged(Location location) {
double lat = location.getLatitude();
double lng = location.getLongitude();
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
I want to get the speed out of the LocationManager in my app. I have a Criteria with setSpeedRequired(true) attribute. I am doing location.getSPeed(), but it gives me 0 all the time. Below is the code for the GPS which I am running as a Service.
public class Tracking extends Service implements LocationListener {
protected LocationManager locationManager;
Location location;
double latitude;
double longitude;
float velocity;
String provider;
private static final long minDist = 0;
private static final long minTime = 0;
LocationDatabaseHandler ldb;
#Override
public void onCreate() {
ldb = new LocationDatabaseHandler(this);
getLocation();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent,flags,startId);
//because we do not want to stop the service unless we explicitly say so.
return START_STICKY;
}
public Location getLocation() {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setSpeedRequired(true);
provider = locationManager.getBestProvider(criteria, false);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minTime, minDist,
this);
location = locationManager.getLastKnownLocation(provider);
if(location != null) {
onLocationChanged(location);
}
return location;
}
#Override
public void onLocationChanged(Location location) {
latitude = location.getLatitude();
longitude = location.getLongitude();
batteryP = getBatteryPerc();
velocity = location.getSpeed();
insertIntoDb(latitude, longitude, velocity, "onchanged");
}
public void insertIntoDb(double latitude, double longitude, float velocity, String where) {
Date date = new Date();
String dateStr = date.toString();
ldb.addLocation(new Locations(latitude, longitude, dateStr, velocity));
}
}
When I see my database, the velocity is always 0.0. Is there something I am missing?
locationManager.requestLocationUpdates(provider, minTime, minDist, this);