Android LocationListener on Service with Thread - android

I´d like to implement a LocationListener in this way.
1 - Activity_first - Call LocationListener, but I have some spinner and this don´t respond when the LocationListener are onStart(). I´d like to implement with a Thread.
2 - When the onLocationChanged() in LocationListener gets called, I call Geocoder, and when the address is different than null, I save it on the shared preferences, and stop it.
Point 2, must be done in the background because the user might be in an Activity when I get the Geocoder's address (about 10 seconds, it depend on connection)
I was testing with IntentService, but of course, I doesn't work.
My Code
public class Carga_1 extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.carga_1);
// Todo Create Spinner, etc
startService(new Intent(Carga_1.this, LocationService2.class));
}
}
public class LocationService2 extends Service {
public static final String BROADCAST_ACTION = "Hello World";
//public LocationManager locationManager; testted
//public MyLocationListener listener; tested
public Location previousBestLocation = null;
Thread my_thread;
#Override
public IBinder onBind(Intent intent) {
Log.d("[GPS_coord]", "????");
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onStart(Intent intent, int startId) {
Runnable r = new Runnable() {
public void run() {
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
MyLocationListener listener = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
}
};
my_thread = new Thread(r);
my_thread.start();
}
#Override
public void onDestroy() {
super.onDestroy();
my_thread.stop();
}
private void get_address(double lat, double longi) {
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> addresses;
try {
addresses = geocoder.getFromLocation(lat, longi, 1);
//SAVE ON SharedPrefereces
this.stopSelf();
}
catch (IOException e) {
Log.d("[GPS_geocoder]", "Decodificacion Erronea");
}
}
public class MyLocationListener implements LocationListener {
public void onLocationChanged(final Location loc) {
Log.i("GPS_Service", "Location changed");
Log.d("GPS_Service", String.valueOf(loc.getLatitude() + " : " + String.valueOf(loc.getLongitude())));
get_address(loc.getLatitude(), loc.getLongitude());
}
public void onProviderDisabled(String provider) {
Log.i("GPS_Service", "DES_habilitado");
}
public void onProviderEnabled(String provider) {
Log.i("GPS_Service", "Habilitado");
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}

Related

Disable location updates from GPS

UPDATED QUESTION - STILL NOT WORKING
I've changed the code.
Now, deactivateAlerts and activateAlerts are in the MainActivity.
Now, inside activateAlerts(), I'm instantiating a GPSListener for the GPS Provider:
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
gpsListener = new GPSListener(getApplicationContext());
} else if
Where the GPSListener is this:
public class GPSListener implements LocationListener {
private Context mCtx;
private Location cLoc;
private LocationManager mLocMan;
public GPSListener (Context ctx){
mCtx = ctx;
mLocMan = (LocationManager) mCtx.getSystemService(Context.LOCATION_SERVICE);
mLocMan.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
public Location getLocation()
{
cLoc = mLocMan.getLastKnownLocation(LocationManager.GPS_PROVIDER);
return cLoc;
}
public void stop()
{
mLocMan.removeUpdates(GPSListener.this);
}
#Override
public void onLocationChanged(Location location) {
Log.i("UPDATING", "updating location");
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
With the deactiveAlerts() function, I execute the instruction to remove the GPS updates:
if(gpsListener!=null){
gpsListener.stop();
}
But the GPS is not stopping yet =(
What is the problem now?
ORIGINAL QUESTION
The user can activate or deactivate location updates.
If the location updates are activated, it works ok, but when the location updates are deactivated, the GPS is still waiting for updates (and the icon appears on the action bar).
The code is that:
public class Alerts extends Fragment {
MyLocationListener myLocationListener = null;
...
public void activateAlerts() {
locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
myLocationListener = new MyLocationListener();
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
Utils.MINIMUM_TIME_BETWEEN_UPDATE,
Utils.MINIMUM_DISTANCECHANGE_FOR_UPDATE,
myLocationListener
);
} else if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
Utils.MINIMUM_TIME_BETWEEN_UPDATE,
Utils.MINIMUM_DISTANCECHANGE_FOR_UPDATE,
myLocationListener
);
} else {
locationManager.requestLocationUpdates(
LocationManager.PASSIVE_PROVIDER,
Utils.MINIMUM_TIME_BETWEEN_UPDATE,
Utils.MINIMUM_DISTANCECHANGE_FOR_UPDATE,
myLocationListener
);
}
}
});
...
}
public void deactivateAlerts() {
...
locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
if(myLocationListener != null) {
locationManager.removeUpdates(myLocationListener);
myLocationListener = null;
}
...
}
public class MyLocationListener implements android.location.LocationListener {
public void onLocationChanged(Location location) {
Log.i("UPDATING", "updating location");
}
public void onStatusChanged(String s, int i, Bundle b) {
Log.v("LocationListener", "onStatusChanged");
}
public void onProviderDisabled(String s) {
Log.v("LocationListener", "onProviderDisabled");
}
public void onProviderEnabled(String s) {
Log.v("LocationListener", "onProviderEnabled");
}
}
What is the problem?
I've read this posts:
Post1
Post2
Post3
Post4

running an script only for an specific time

I have a code for detecting location that I want to works only for 2 minutes.
when I fire start() method script must works almost for 2 minutes.
problem is in there that how run my script only for an specific time.
I used this code but don't running correct.
don't fire stop() method from in Timer().schedule()
public class a implements LocationListener{
private LocationManager locationManager;
private String provider;
private Location lastloc;
private Context _context;
public a(Context context){
_context = context;
}
public void start(){
locationManager = (LocationManager) _context.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 1, (LocationListener) this);
new Timer().schedule(
new TimerTask(){
public void run() {
stop();
}
}
,System.currentTimeMillis(), 2*60*1000);
}
public void stop(){
Log.d("states","stop");
locationManager.removeUpdates((LocationListener) this);
}
#Override
public void onLocationChanged(Location location) {
Log.d("states", "onLocationChanged()");
lastloc = location;
}
#Override
public void onProviderDisabled(String arg0) {
}
#Override
public void onProviderEnabled(String arg0) {
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
}
Check your code of Timer again. Usually, the Timer code should be like:
Timer.schedule(TimerTask,
delayTime); // delay a task before executed for the first time, in milliseconds
Because of your delayTime has been executed by using System.currentTimeMillis(), the System picks the current time in milliseconds since midnight, so that the TimerTask will be executed after millions millisecond.
Hence, use this code:
Timer timer = new Timer();
timer.schedule(new TimerTask(){
#Override
public void run() {
// do your thing here
}
}, 2*60*1000);
See this documentation about the type of Timer you created.
I finally solved my problem by using handlers.
read this page: Using Bundle Android to Exchange Data Between Threads
a.java
public class a implements LocationListener{
private LocationManager locationManager;
private String provider;
private Location lastloc;
private Context _context;
private Thread workingthread = null;
final Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
Log.d("states","return msg from timer2min");
if(msg.what==1){
stop();
}
super.handleMessage(msg);
}
};
public a(Context context){
_context = context;
}
public void start(){
locationManager = (LocationManager) _context.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 1, (LocationListener) this);
workingthread=new timer2min(mHandler);
workingthread.start();
}
public void stop(){
Log.d("states","stop");
locationManager.removeUpdates((LocationListener) this);
}
#Override
public void onLocationChanged(Location location) {
Log.d("states", "onLocationChanged()");
}
#Override
public void onProviderDisabled(String arg0) {
}
#Override
public void onProviderEnabled(String arg0) {
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
}
timer2min.java
public class timer2min extends Thread {
private Handler hd;
public timer2min(Handler msgHandler){
hd = msgHandler;
}
public void run() {
try {
Thread.sleep(2*60*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = hd.obtainMessage();
msg.what = 1;
hd.sendMessage(msg);
}
}

Using GPS on Services

On this code i want to get the gps location every 3 seconds. but when i run this program on my device it tells me that latitude and longitude are both 0 every time. how should i handle this problem?
and what is the looper task ?? it gives me error when i donot use it
public class LocationService extends Service {
final static String TAG = "MyService";
double latitude ;
double Longitude ;
LocationManager lm;
LocationListener ll;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Log.d(TAG, "onCreate");
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread() {
public void run() {
Looper.prepare();
while(true){
lm = (LocationManager) getSystemService(LOCATION_SERVICE);
ll = new MyLocationListener();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,
0, 0, ll);
//when i log here , it gives me wronganswer
Log.d(TAG,Double.toString(latitude));
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
Log.d(TAG, "OnDestroy");
super.onDestroy();
}
class MyLocationListener implements LocationListener{
#Override
public void onLocationChanged(Location location) {
//when i log here , it gives me correct answer
double lat = location.getLatitude();
double lon = location.getLongitude();
latitude = lat;
Longitude = lon;
}
#Override
public void onProviderDisabled(String arg0) {
}
#Override
public void onProviderEnabled(String arg0) {
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
};
}
When you get location from GPS, it can take some time, because GPS module needs to find satellites. So you need to wait couple or few minutes while GPS module find satellites. If WI-FI location provider available you can get location more quick.
Additional info about location providers you can find here: http://developer.android.com/guide/topics/location/strategies.html
Since Android has
GPS_PROVIDER and NETWORK_PROVIDER
you can register to both and start fetch events from onLocationChanged(Location location) from two at the same time. So far so good. Now the question do we need two results or we should take the best. As I know GPS_PROVIDER results have better accuracy than NETWORK_PROVIDER.
for example you have location listener:
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
//here you get locations from both providers
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
YOu need to do something like that:
LocationManager lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,locationListener);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,locationListener);
but before registering you need to check is these providers available on this device, like that:
boolean network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
boolean gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);

Get Current Location From Android Background Service Issue

I want to develop location based reminder app. Therefore I want to use android service for get current location even app is not running. But I didn't do. I set timer in android service class but I don't know how to get current location in service class. What is the problem ? I got some error like this:
can't create handler inside thread that has not called looper.prepare()
public class TrackerService extends Service {
double latShared;
double lngShared;
double latService;
double lngService;
private LocationManager lm;
Timer timer;
Handler handler;
final static long TIME = 15000;
SharedPreferences mSharedPrefs;
SharedPreferences.Editor mPrefsEditor;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
mSharedPrefs = getSharedPreferences("locationXML", MODE_PRIVATE);
latShared = (double)mSharedPrefs.getFloat("lat", 0);
lngShared = (double)mSharedPrefs.getFloat("lng", 0);
timer = new Timer();
timer.schedule(new TimerTask(){
#Override
public void run(){
LocationUpdates();
}
},0,TIME);
}
public void LocationUpdates(){
locListener locList = new locListener();
lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locList);
}
#Override
public void onDestroy() {
//lm.removeUpdates(this);
timer.cancel();
}
public class locListener implements LocationListener{
#Override
public void onLocationChanged(Location location) {
latService = location.getLatitude();
lngService = location.getLongitude();
}
#Override
public void onProviderDisabled(String provider) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
}
LocationManager.requestLocationUpdates is supposed to run on UI thread as its sibling method defines. On the other hand TimerTask introduces a new thread to offload its execution.
However, if you are not using a new process for your service then simply call LocationUpdates() as below:
#Override
protected void onCreate() {
mSharedPrefs = getSharedPreferences("locationXML", MODE_PRIVATE);
latShared = (double)mSharedPrefs.getFloat("lat", 0);
lngShared = (double)mSharedPrefs.getFloat("lng", 0);
final Handler h = new Handler();
h.post(new Runnable() {
#Override
public void run() {
LocationUpdates();
h.postDelayed(this, TIME);
}
});
}
OR, if you don't want to use handler then simply upgrade your requestLocationUpdates as below:
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locList, getMainLooper());
In above case, getMainLooper() will dispatch your location updates from UI thread.

Listening to bound location service from an activity

I've got a location service to have an updated location in my app. I bind it to every activity requiring location data, and now I'd like to know in these activities when the location listener in the service receives events such as onLocationChanged, onProviderEnabled... How can I do that?
In my activities
private ServiceConnection mConnection;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Bind location service
bindService(new Intent(this, LocationService.class), mConnection, Context.BIND_AUTO_CREATE);
// Activity stuff...
}
#Override
protected void onDestroy() {
super.onDestroy();
// Unbind LocationService
context.unbindService(mConnection);
}
LocationService.java
public class LocationService extends Service implements LocationListener {
LocationManager locationManager;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
// Update after minimum 5 minutes and if user has moved at least 100 meters.
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5 * 60 * 1000, 100, this);
Location loc = getBestLocation(locationManager);
if(loc!=null){
GlobalVars.lat = (Double) (loc.getLatitude());
GlobalVars.lng = (Double) (loc.getLongitude());
}
}
}
public void onLocationChanged(Location loc) {
GlobalVars.lat = (Double) (loc.getLatitude());
GlobalVars.lng = (Double) (loc.getLongitude());
}
public static Location getBestLocation(LocationManager locationManager) {
Location location_gps = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Location location_network = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
// If both are available, get the most recent
if(location_gps!=null && location_network !=null) {
return (location_gps.getTime() > location_network.getTime())?location_gps:location_network;
}
else if(location_gps==null && location_network ==null){
return null;
}
else
return (location_gps==null)?location_network:location_gps;
}
public void onProviderEnabled(String s){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5 * 60 * 1000, 0, this);
}
public void onProviderDisabled(String s){
locationManager.removeUpdates(this);
GlobalVars.lat = null;
GlobalVars.lng = null;
}
public void onStatusChanged(String s, int i, Bundle b){}
#Override
public void onDestroy() {
locationManager.removeUpdates(this);
}
}
I would do it on this way:
Create LocationListener class..
Each time i get a new location, send broadcast message with specific predefined ACTION and in extras put lat and lon.
Each activity creates broadcast listener for this message with intentFilter(Action);
Get extras from the intent.

Categories

Resources