Greg
Here is my New code based on your suggestions. It did not work. I got a bunch of "Just sent a text message with coords" in a row. So it still is not sleeping for 15 seconds.
package com.droid.service;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
public class DroidService extends Service
{
private LocationManager lm;
private LocationListener locationListener;
private Location location = null;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
// #Override
// public void onCreate()
// {
// super.onCreate();
// initService();
// }
private static final int PERIOD = 15000;
Handler mHandler;
Runnable mRunnable;
#Override
public void onCreate()
{
super.onCreate();
mHandler = new Handler();
mRunnable = new Runnable()
{
public void run()
{
updateNotification();
mHandler.postDelayed(this, PERIOD);
System.out.println("PAUSE FOR 15 SECONDS..!!");
}
};
}
#Override
public void onStart(final Intent intent, final int startId)
{
super.onStart(intent, startId);
mRunnable.run();
}
// private void initService()
// {
// System.out.println("In initService..Droid Service...!!");
// int initialDelay = 15000; // start after 15 seconds
// // int period = 300000; // repeat every 5 minuets
// // int period = 1800000; // repeat every 30 minuets
// int period = 15000; // repeat every 15 seconds for testing
// Timer timer = new Timer();
// TimerTask task = new TimerTask()
// {
// public void run()
// {
// Looper.prepare();
// updateNotification();
// Looper.loop();
// }
// };
// timer.scheduleAtFixedRate(task, initialDelay, period);
// }
protected void updateNotification()
{
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationListener = new MyLocationlistener();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
public static class DateUtils
{
public static final String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss";
public static String now()
{
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
return sdf.format(cal.getTime());
}
}
private class MyLocationlistener implements LocationListener
{
public void onLocationChanged(Location loc)
{
double lat = loc.getLatitude();
double lon = loc.getLongitude();
String latitude = Double.toString(lat);
String longitude = Double.toString(lon);
String coords = latitude + longitude;
// comment out text message for debug mode
// SmsManager sm = SmsManager.getDefault();
// sm.sendTextMessage("phoneNumber", null, coords, null, null);
System.out.println("Just sent a text message with coords");
}
public void onProviderDisabled(String provider)
{
}
public void onProviderEnabled(String provider)
{
}
public void onStatusChanged(String provider, int status, Bundle extras)
{
}
}
}
Here is my code
I get "Just sent a text message with coords" sent like once a second even though my scheduleAtFixedRate is set for 10 seconds.
I got this to work in a normal program, but on the Android platform, they want you to use Looper....and it appears that my code is caught up in this Looper so therefore it is ignoring my scheduleAtFixedRate(10 seconds)
Any help is greatly appreciated.
package com.droid.service;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
public class DroidService extends Service
{
private LocationManager lm;
private LocationListener locationListener;
private Location location = null;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onCreate()
{
super.onCreate();
initService();
}
private void initService()
{
System.out.println("In initService..!!");
int initialDelay = 15000; // start after 15 seconds
// int period = 300000; // repeat every 5 minuets
// int period = 1800000; // repeat every 30 minuets
int period = 15000; // repeat every 15 seconds for testing
Timer timer = new Timer();
TimerTask task = new TimerTask()
{
public void run()
{
Looper.prepare();
updateNotification();
Looper.loop();
Looper.myLooper().quit();
}
};
timer.scheduleAtFixedRate(task, initialDelay, period);
}
protected void updateNotification()
{
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationListener = new MyLocationlistener();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
private class MyLocationlistener implements LocationListener
{
public void onLocationChanged(Location loc)
{
double lat = loc.getLatitude();
double lon = loc.getLongitude();
String latitude = Double.toString(lat);
String longitude = Double.toString(lon);
String coords = latitude + longitude;
// comment out text message for debug mode
// SmsManager sm = SmsManager.getDefault();
// sm.sendTextMessage("phoneNumber", null, coords, null, null);
System.out.println("Just sent a text message with coords");
}
public void onProviderDisabled(String provider)
{
}
public void onProviderEnabled(String provider)
{
}
public void onStatusChanged(String provider, int status, Bundle extras)
{
}
}
}
I think the misconception here is not so much that Android wants to use a Looper, but thaty you shouldn't use the Timer for the behavior that you desire. Instead of the Timer you have to manipulate a Looper. I haven't used the Looper directly in a while because there are other components which abstract away a lot of the nuances of it. However I think that Looper.loop() should not return until an outside entity either interrupts your thread or quit's the looper for you. So I don't think that will work, I could be wrong though.
You could use a Handler if you want to create a pulse. A Handler allow you to do work on the Looper thread.
So with the example you have,
private static final int PERIOD = 15000;
Handler mHandler;
Runnable mRunnable;
#Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
mRunnable = new Runnable() {
public void run() {
updateNotication();
mHandler.postDelayed(this, PERIOD);
}
};
}
I will admit from here on out I am only guessing I know the desired outcome of your application. I am assuming you don't need two way communication as your IBinder is null.
#Override
public void onStart() {
mRunnable.run();
}
// The rest of your code.
..
Try to call initService from onStart().
Basically the best bet for me was to call this onCreate. Now it is doing exactly what I want it to do. Thanks for all your inputs..!! This helped me solve the problem.
Related
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.Toast;
public class LocationService extends Service {
private LocationDatabaseHelper mLocationDatabaseHelper;
private LocationModel mLocationModel;
private Date mDate;
private Handler mHandler = new Handler();
private Timer mTimer = null;
private int mCount = 0;
public static final long NOTIFY_INTERVAL = 30 * 1000;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
// cancel if already existed
if (mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
mLocationModel = LocationModel.getInstance();
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
}
#Override
public void onDestroy() {
mTimer.cancel();
}
private class TimeDisplayTimerTask extends TimerTask implements LocationListener {
#Override
public void run() {
mHandler.post(new Runnable() {
#Override
public void run() {
//I send message to draw map here
sendMessage();
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
TimeDisplayTimerTask.this);
}
});
}
#Override
public void onLocationChanged(Location location) {
// I get location and do work here
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
}
private void sendMessage() {
Intent intent = new Intent("my-event");
intent.putExtra("message", "data");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
What I want is to get user location after every 30 seconds but this code does not work as I expected. It gets location very fast (I think every second).
I tried to get location this way because it can get my current location immediately after I start my app.I have tried getLastKnowLocation before, but it give me the last known location which is very far from where I am.
Please show me how fix this.Thank you!
in requestLocationUpdates method second parameter is minimum time interval between location updates, in milliseconds, So you just need to do this:
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30 * 1000, 0, TimeDisplayTimerTask.this);
According to Android Developer Reference Documentation
http://developer.android.com/reference/android/location/LocationManager.html#requestLocationUpdates(java.lang.String, long, float, android.location.LocationListener)
public void requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener)
When registering for location updates the LocationManager is invoking LocationListener onLocationChanged(Location) method with latest Location object.
And the second parameter of requestLocationUpdates method is
minTime The minimum time interval between location updates, in milliseconds
This does not mean that you will get location updates every 30 seconds constantly, because if the location cannot be obtained you will not get updates also, if the location is not being changed you will again not get any updates.
Anyway, if you would like to get location updates every 30 seconds constantly, you can keep latest location and send it using your scheduler, while updating it when the onLocationChanged method is called.
try using
TimerTask scanTask;
final Handler handler = new Handler();
mTimer = new Timer();
public void sendSMS(){
scanTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
//your method here which you want to call every 30 sec
}
});
}};
mTimer.schedule(scanTask, 30000, 30000);
}
I'm trying to make a trivial application in which the user clicks a button and a few text views display various information about the phone(model,battery %,location,signal strength etc). I'm having trouble getting the current latitude and longitude, since when I press the button the textview displays the previous latitude/longitude(first time it shows 0,0 and the second the position I was when I first pressed it).
What I'm trying to achieve is when I press the button, activate the location manager and location listener, and make the onClick() method wait until the latitude is not equal to the old latitude. I've tried Threads, handler, and asynctask but I haven't managed anything. Any tips? This is how my onClick() method looks right now: (Infogatherer is a class where I collect all the info)
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
switch(arg0.getId()){
case R.id.bMeasurements:
oldLat=InfoGatherer.getLatitude();
oldLong=InfoGatherer.getLongitude();
//SOMEWHERE HERE START A THREAD OR SOMETHING IN ORDER TO RETRIEVE CURRENT LOCATION
//Retrieval and Assignment of information to the corresponding text fields
DeviceName.setText(infogatherer.getDeviceName());
NetworkOp.setText(infogatherer.getNetworkOp());
Date.setText(infogatherer.getDate());
BatteryStatus.setText(String.valueOf(infogatherer.getBatteryStatus()));
Generation.setText(String.valueOf(infogatherer.getGeneration()));
infogatherer.getLocation();
Location.setText(String.valueOf(InfoGatherer.getLatitude()+","+InfoGatherer.getLatitude()));
infogatherer.getSignalStrength();
SignalStrength.setText(String.valueOf(infogatherer.getDbm()));
oldLat = InfoGatherer.getLatitude();
oldLong = InfoGatherer.getLongitude();
break;
}
This is my InfoGatherer class:
package com.example.netmap;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Bundle;
import android.telephony.CellInfoGsm;
import android.telephony.CellSignalStrengthGsm;
import android.telephony.PhoneStateListener;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
public class InfoGatherer extends Application{
String address,city,country;
int cid,lac,generation=0,ipAddress=0,signalStrngth=0;
private GsmCellLocation location;
private WifiInfo wifiInfo;
private LocationManager lm;
private LocationListener ll;
Geocoder geoc;
static public double Longitude,Latitude=0;
List<Address> addresses;
Context context;
Intent batteryIntent;
TelephonyManager tm;
WifiManager wifimanager;
public InfoGatherer(){
}
public InfoGatherer(Context context){
this.context = context;
}
public String getDate(){
Calendar c = Calendar.getInstance();
return Integer.toString(c.get(Calendar.DAY_OF_MONTH))+"-"+Integer.toString(c.get(Calendar.MONTH))+"-"+Integer.toString(c.get(Calendar.YEAR))+" "+Integer.toString(c.get(Calendar.HOUR_OF_DAY))+":"+Integer.toString(c.get(Calendar.MINUTE))+":"+Integer.toString(c.get(Calendar.SECOND));
}
public String getDeviceName(){
return Build.MANUFACTURER +" "+Build.MODEL;
}
public String getNetworkOp(){
tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getNetworkOperatorName();
}
public float getBatteryStatus() {
batteryIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
return ((float)batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) / (float)batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)) * 100.0f;
}
public int getGeneration(){
tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getNetworkType();
}
public int getCid(){
tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
location = (GsmCellLocation)tm.getCellLocation();
return location.getCid();
}
public int getLac(){
tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
location = (GsmCellLocation)tm.getCellLocation();
return location.getLac();
}
public String getIpAddress() {
// TODO Auto-generated method stub
wifimanager = (WifiManager) context.getSystemService(WIFI_SERVICE);
wifiInfo = wifimanager.getConnectionInfo();
ipAddress = wifiInfo.getIpAddress();
return String.format("%d.%d.%d.%d",(ipAddress & 0xff),(ipAddress >> 8 & 0xff),(ipAddress >> 16 & 0xff),(ipAddress >> 24 & 0xff));
}
public void getLocation(){
/*Criteria c = new Criteria();
c.setAccuracy(Criteria.ACCURACY_FINE);
c.setPowerRequirement(Criteria.POWER_LOW);
String provider = lm.getBestProvider(c, true);*/
lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
ll = new mylocationlistener();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
}
public class mylocationlistener implements LocationListener{
#Override
public void onLocationChanged(android.location.Location location) {
// TODO Auto-generated method stub
if(location!=null){
Longitude = location.getLongitude();
Latitude = location.getLatitude();
lm.removeUpdates(ll);
}
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
//Pass views as parameters? DIscuss
//DeviceName.setText(String.valueOf(Latitude) +" "+String.valueOf(Longitude));
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
}
public void getSignalStrength(){
tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener Listener = new phoneStateListener();
tm.listen(Listener ,PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}
public class phoneStateListener extends PhoneStateListener{
public void onSignalStrengthsChanged(SignalStrength signalStrength){
super.onSignalStrengthsChanged(signalStrength);
if (signalStrength.isGsm()) {
signalStrngth = -113 + 2 * signalStrength.getGsmSignalStrength();
}
else
signalStrngth = -113 + 2 * signalStrength.getCdmaDbm();
}
}
static public double getLatitude(){
return Latitude;
}
static public double getLongitude(){
return Longitude;
}
public String getAddress(){
return address;
}
public String getCity(){
return city;
}
public String getCountry(){
return country;
}
public int getDbm(){
return signalStrngth;
}
}
You donĀ“t provide enough time to Location service get the location.
You ask for latitude and longitude before the LocationManager have time to call onLocationChanged.
infogatherer.getLocation();
Location.setText(String.valueOf(InfoGatherer.getLatitude()+","+InfoGatherer.getLatitude()));
Call infogatherer.getLocation(); out of onClick event. Do that at Activity onResume() event.
Remove lm.removeUpdates(ll); from onLocationChanged. Call it at Activity onPause()event.
If you want see this example how to create a GPS Manager Class
EDIT
Try something like this: Note: Not tested!
private void updateLocationText(double oldLat, double oldLong) {
Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
boolean isPositionChanged = false;
double lat;
double long;
while (!isPositionChanged) {
lat = InfoGatherer.getLatitude();
long = InfoGatherer.getLongitude();
if(lat != oldLat || long != oldLong)isPositionChanged = true;
}
handler.post(new Runnable(){
public void run() {
Location.setText(String.valueOf(InfoGatherer.getLatitude()+","+InfoGatherer.getLatitude()));
});
}
}
};
new Thread(runnable).start();
}
Note that if you click on the button without having been no change of location, it will run forever.
EDIT AGAIN
Another approach more clean:
Replace
Location.setText(String.valueOf(InfoGatherer.getLatitude()+","+InfoGatherer.getLatitude()));
with this
Location.postDelayed(new Runnable() {
#Override
public void run() {
Location.setText(String.valueOf(InfoGatherer.getLatitude()+","+InfoGatherer.getLatitude()));
Location.postInvalidate();//Try without, may be not necessary
}
}, 3000);//Change if need
Create the LocationListener out of Aplication.
In the Ativity instantiate the class, override the onLocationChanged event and update Location TextView there.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
.........
.........
lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
listener = new MyLocationListener(){
#Override
public void onLocationChanged(android.location.Location location) {
if(location!=null){
Location.setText(String.valueOf(location.getLatitude()+","+location.getLatitude()));
lm.removeUpdates(listener);
}
}
}
}
In onClick() event replace:
infogatherer.getLocation();
Location.setText(String.valueOf(InfoGatherer.getLatitude()+","+InfoGatherer.getLatitude()));
with
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
In the end I used AsyncTask, which helped me in order to sleep the app while I looked for the location.
private class LocationThread extends AsyncTask<Context, Void, Void> {
protected void onPreExecute() {
infogatherer.startLocationListener();
}
#Override
protected Void doInBackground(Context... params) {
while (!infogatherer.getGo()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
protected void onPostExecute(final Void unused) {
//Do whatever you wanna do after you get location
}
}
getGo is a boolean which whenever becomes true gives the location back
public class mylocationlistener implements LocationListener {
#Override
public void onLocationChanged(android.location.Location location) {
if(location != null){
Longitude = location.getLongitude();
Latitude = location.getLatitude();
lm.removeUpdates(ll);
go = true;
}
}
hope you understand the procedure. Cheers.
What should i do to turn off the gps if location is not found at 1st instance..without location update being called
package mobile.sales;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
public class test extends Activity
{
DataSource dataSource;
Double lat=0.0,lng=0.0;
String GPS_FILTER = "";
Thread triggerService;
LocationListener locationListener;
LocationManager lm;
private static final long MINIMUM_DISTANCE_CHANGE_FOR_UPDATES = 1000; // in Meters
private static final long MINIMUM_TIME_BETWEEN_UPDATES = 29*1000*60; // in Milliseconds
protected LocationManager locationManager;
boolean isRunning = true;
NotificationManager notificationManager;
PendingIntent contentIntent;
Notification notification;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
turnGPSOn();
LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
locationListener = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,MINIMUM_TIME_BETWEEN_UPDATES, MINIMUM_DISTANCE_CHANGE_FOR_UPDATES, locationListener);
}
#Override
public void onDestroy()
{
// TODO Auto-generated method stub
locationManager.removeUpdates(locationListener);
locationManager= null;
turnGPSOnOff();
super.onDestroy();
// removeGpsListener();
}
private class MyLocationListener implements LocationListener
{
public void onLocationChanged(Location location)
{
lat=location.getLatitude();
lng=location.getLongitude();
turnGPSOnOff();
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
String currentDateandTime = sdf.format(new Date());
SimpleDateFormat sdft = new SimpleDateFormat("hh:mm:ss");
String time=sdft.format(new Date());
dataSource.insertIntoLocationDetails(""+lat,""+lng,currentDateandTime,""+time);
Log.d("service","location Inserted");
}
public void onStatusChanged(String s, int i, Bundle b) {
}
public void onProviderDisabled(String s) {
}
public void onProviderEnabled(String s) {
}
}
private void turnGPSOnOff(){
Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", false);
sendBroadcast(intent);
}
private void turnGPSOn(){
String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
if(!provider.contains("gps")){
final Intent poke = new Intent();
poke.setClassName("com.android.settings","com.android.settings.widget.SettingsAppWidgetProvider");
poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
poke.setData(Uri.parse("3"));
sendBroadcast(poke);
}
}
}
You are calling the function when you are trying to DESTROY The activity itself. First find the Fix of GPS using GPSStatusListener
Use this code
Check Gps Status
Call your GpsTurnOff status in GPSStatusListener
new Handler().postDelayed(new Runnable() {
#Override
public void run()
{
turnGPSOnOff();
}
}, 2000*60);
this will turnoff my gps after certain time
I have use service for collect fixes from network plocation provider. I have not use wacklock, but my app whatever locks device.
I have seen it in Battery Histor for GB, for example:
Screen ON: 2 minutes;
Running: 5 minutes;
Partial wake lock by my app: 10 minutes.
It should be? I need collect location data only when device awake.
This is my sercive:
package com.myapp.service;
import com.myapp.App;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.IBinder;
public class LocationMonitor extends Service
{
/**********************
* PUBLIC CONSTANTS
**********************/
public static final String ACTION_START = "StartService"; // start action
public static final String ACTION_STOP = "StopService"; // stop action
/**********************
* PRIVATE CONSTANTS
**********************/
private static final long MINIMUM_DISTANCE_CHANGE = 10; // in Meters
private static final long MINIMUM_TIME_BETWEEN_UPDATES = 300 * 1000; // in Milliseconds
/**********************
* PRIVATE VARIBLES
**********************/
private LocationManager sLocationManager; // location manager
/**********************
* SERVICE LIFECYCLE
**********************/
#Override
public void onCreate()
{
super.onCreate();
startService();
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
if (intent != null)
{
if (intent.getAction().equals(ACTION_STOP))
{
stopService();
return START_NOT_STICKY;
}
}
return START_STICKY;
}
private void startService()
{
sLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
sLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
MINIMUM_TIME_BETWEEN_UPDATES, MINIMUM_DISTANCE_CHANGE, sNetworkLocationListener);
}
private void stopService()
{
sLocationManager.removeUpdates(sNetworkLocationListener);
stopSelf();
}
/**********************
* LOCATION LISTENERS
**********************/
private LocationListener sNetworkLocationListener = new LocationListener()
{
#Override
public void onLocationChanged(Location location)
{
// store location in db
}
#Override
public void onProviderDisabled(String provider) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
/**********************
* STATIC METHODS
**********************/
public static void startService(Context context)
{
Intent newIntent = getServiceIntent(context);
newIntent.setAction(ACTION_START);
context.startService(newIntent);
}
public static void stopService(Context context)
{
Intent newIntent = getServiceIntent(context);
newIntent.setAction(ACTION_STOP);
context.startService(newIntent);
}
}
I wrote a GPSDataCollectService to collect location data every 10 seconds, but it did not report location in my HTC mobile phone, any wrong? could anyone help me?
package com.android.example;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
public class GPSDataCollectorService extends Service {
private static final String TAG = GPSDataCollectorService.class
.getSimpleName();
LocationManager locationManager;
LocationListener gpsLocationListener;
#Override
public IBinder onBind(Intent intent) {
return null;
}
private Timer timer;
private TimerTask collectTask = new TimerTask() {
#Override
public void run() {
Log.i(TAG, "Timer task doing work: "
+ Calendar.getInstance().getTimeInMillis());
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
gpsLocationListener = new GPSLocationListener();
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 10 * 1000L, 0,
gpsLocationListener);
}
};
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Service creating");
timer = new Timer("GPSDataCollectorTimer");
timer.schedule(collectTask, 1000L, 10 * 1000L);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "Service destroying");
locationManager.removeUpdates(gpsLocationListener);
timer.cancel();
timer = null;
}
private class GPSLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged: " + location.toString());
locationManager.removeUpdates(gpsLocationListener);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TAG, "onStatusChanged: " + status);
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
}
}
If your location is changed every 10 sec then only your LocationManager will track the new location. Otherwise it will use the same last known location.
Instead of using a LocationListener, you may want to use a Timer, within the TimerTask, maybe you can do something like this:
LocationManager lm = yourActivityReference.getSystemService(Context.LOCATION_SERVICE);
String provider = lm.getBestProvider(new Criteria(),true);
Location loc = lm.getLastKnownLocation (provider);
I haven't checked it, but if I do I will let know...
Regards.
EDIt: Let me try again with the "classic" approach.
public class GPSDataCollectorService extends Service {
private static final String TAG = GPSDataCollectorService.class
.getSimpleName();
LocationManager locationManager;
LocationListener gpsLocationListener;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
gpsLocationListener = new GPSLocationListener();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10 * 1000L, 0, gpsLocationListener);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "Service destroying");
locationManager.removeUpdates(gpsLocationListener);
}
private class GPSLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged: " + location.toString());
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TAG, "onStatusChanged: " + status);
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
}
}
I don't think you need any Timer, since the Location updates will call your listener asynchronally and you can set the timeout. I haven't played much with GPS in Android, but there must be plenty of examples out there.
The location update interval can be controlled using the minTime parameter. The elapsed time between location updates will never be less than minTime, although it can be more depending on the Location Provider implementation
Use
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 20 * 1000, 0, this);
more details refer Location Manager