In my project, i have used a service to retrieving location continuously in background. My LocationService is as follows:
public class LocationService extends Service
{
private static final int TWO_MINUTES = 1000 * 60 * 2;
public LocationManager locationManager;
public MyLocationListener listener;
public Location previousBestLocation = null;
Intent i;
#Override
public void onCreate()
{
super.onCreate();
i = new Intent("LOCATION_CHANGED");
}
#Override
public int onStartCommand(Intent intent,int flags, int startId)
{
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
listener = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 4000, 0, listener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 4000, 0, listener);
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return true;
}
return false;
}
/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
#Override
public void onDestroy() {
// handler.removeCallbacks(sendUpdatesToUI);
super.onDestroy();
Log.v("STOP_SERVICE", "DONE");
locationManager.removeUpdates(listener);
}
public static Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
#Override
public void run() {
try {
runnable.run();
} catch(Exception e) {
System.out.print(e);
}
}
};
t.start();
return t;
}
public class MyLocationListener implements LocationListener
{
public void onLocationChanged(final Location loc)
{
Log.i("**************************************", "Location changed");
if(isBetterLocation(loc, previousBestLocation)) {
String newLocation = "Lat: " + loc.getLatitude() + " and Long: " + loc.getLongitude();
i = new Intent("LOCATION_CHANGED");
i.putExtra("location", newLocation);
sendBroadcast(i);
}
}
public void onProviderDisabled(String provider)
{
Toast.makeText( getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT ).show();
}
public void onProviderEnabled(String provider)
{
Toast.makeText(getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show();
}
public void onStatusChanged(String provider, int status, Bundle extras)
{
}
}
}
And I have received broadcasted intent in MainActivity as follows:
public class MainActivity extends Activity {
TextView txt_location;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt_location = (TextView)findViewById(R.id.current_location);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
}
public class LocationBroadcast extends BroadcastReceiver {
#Override
public void onReceive(Context ctx, Intent intent) {
txt_location.setText(intent.getExtras().getString("location"));
}
}
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container,
false);
}
}
}
All i want to do is to set location's latitude and longitude on txt_location. this code isn't working and showing txt_location as it is:
As you can see, it is not showing any location updates...Logcat isn't showing any errors..Can anyone please guide me what is the mistake?
Use this class as Service. but before this define service class in manifest
<service android:name="com.example.androidservice.beckend.EndlessService" />
and use in activity class
startService(new Intent ( this , EndlessService.class)) ;
import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.util.Log;
import android.widget.Toast;
public class EndlessService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg)
{
new HitToTheInternet().execute("");
}
}
#Override
public void onCreate() {
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments",Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the
// job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
if ( intent == null )
{
Log.e("intentStatus", "intent is null");
}
// If we get killed, after returning from here, restart
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
#Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
class HitToTheInternet extends AsyncTask<String, String, String>
{
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
Log.e("doInBackground", "Running") ;
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
new Handler().postDelayed(new Runnable() {
public void run() {
Message msg = mServiceHandler.obtainMessage();
mServiceHandler.sendMessage(msg);
}
}, 10000);
}
}
}
for starting service says at 5 seconds:
AlarmManager alarm =(AlarmManager)context.getSystemService(context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(context, 0, new Intent(context,MonitorService.class), 0);
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 5*1000, pi);
For stopping alarm:
AlarmManager mgr =(AlarmManager)getSystemService(ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(context, 0, new Intent(this,MonitorService.class), 0);
mgr.cancel(pi);
pi.cancel();
Related
I am getting the following exception when I try to use LocationManager within a custom class running in an external service:
*** Uncaught remote exception! (Exceptions are not yet supported across processes.)
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at android.location.LocationManager$GpsStatusListenerTransport$1.<init>(LocationManager.java:1464)
at android.location.LocationManager$GpsStatusListenerTransport.<init>(LocationManager.java:1464)
at android.location.LocationManager.addGpsStatusListener(LocationManager.java:1503)
at org.poseidon_project.contexts.hardware.GPSIndoorOutdoorContext.start(GPSIndoorOutdoorContext.java:97)
at org.poseidon_project.context.management.ContextManager.addObserverRequirement(ContextManager.java:97)
at org.poseidon_project.context.reasoner.ContextMapper.registerIndoorOutdoorsContext(ContextMapper.java:260)
at org.poseidon_project.context.reasoner.ContextMapper.registerContext(ContextMapper.java:197)
at org.poseidon_project.context.ContextReasonerCore.addContextRequirement(ContextReasonerCore.java:70)
at org.poseidon_project.context.ContextReasonerService$1.addContextRequirement(ContextReasonerService.java:74)
at org.poseidon_project.context.IContextReasoner$Stub.onTransact(IContextReasoner.java:74)
at android.os.Binder.execTransact(Binder.java:446)
Now, I have read many answer relating back to the use of Looper, with stuff like:
Looper.prepare;
mLocationManager.requestLocationUpdates(mProvider, mMinTime, mMinDistance, this, Looper.getMainLooper);
But this ends up not causing the Callback (onLocationChanged(Location location)) to be called when there is an update?
The class implements the LocationListener, which also invokes the LocatioManager methods:
public abstract class LocationContext extends ContextObserver implements LocationListener {
protected LocationManager mLocationManager;
private int mMinTime = 3000;
private int mMinDistance = 10;
private String mProvider = LocationManager.GPS_PROVIDER;
private String mIdealProvider = LocationManager.GPS_PROVIDER;
public LocationContext (Context c) {
super(c);
mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
}
public LocationContext (Context c, ContextReceiver cr) {
super(c, cr);
mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
}
public LocationContext (Context c, ContextReceiver cr, int minTime, int minDistance, String name) {
super(c, cr, name);
mMinTime = minTime;
mMinDistance = minDistance;
mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
}
public LocationContext (Context c, ContextReceiver cr, int minTime, int minDistance, String provider, String name) {
super(c, cr, name);
mMinTime = minTime;
mMinDistance = minDistance;
mProvider = provider;
mIdealProvider = provider;
mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
}
#Override
public boolean start() {
//new Thread(new Runnable() {
// #Override
// public void run() {
//Looper.prepare();
mLocationManager.requestLocationUpdates(mProvider, mMinTime, mMinDistance, this);
//handler.sendEmptyMessage(0);
//Looper.loop();
// }
//}).start();
mIsRunning = true;
//Looper.loop();
return true;
}
#Override
public boolean pause() {
return stop();
}
#Override
public boolean resume() {
return start();
}
#Override
public boolean stop() {
mLocationManager.removeUpdates(this);
mIsRunning = false;
return true;
}
#Override
public void onLocationChanged(Location location) {
checkContext(location);
}
protected abstract void checkContext(Location location);
#Override
public void onProviderDisabled(String provider) {
if (provider.equals(mIdealProvider)) {
mProvider = LocationManager.GPS_PROVIDER;
if (! mLocationManager.isProviderEnabled(mProvider)) {
Intent gpsOptionIntent = new Intent (android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(gpsOptionIntent);
}
}
}
#Override
public void onProviderEnabled(String provider) {
if ((provider.equals(mIdealProvider)) && (! provider.equals(mProvider))) {
mLocationManager.removeUpdates(this);
mProvider = provider;
mLocationManager.requestLocationUpdates(mProvider, mMinTime, mMinDistance, this);
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
public int getMinTime() {
return mMinTime;
}
public void setMinTime(int mMinTime) {
this.mMinTime = mMinTime;
}
public int getMinDistance() {
return mMinDistance;
}
public void setMinDistance(int mMinDistance) {
this.mMinDistance = mMinDistance;
}
I don't really understand how to use the Looper in my situation. Can someone help? I understand the answer "run in UI thread" but this is a single service app, there is no UI, so I don't think I can do it in the UI thread?
****UPDATE*****Solution Found******
I believe I found a solution. The class in question was an abstract class, which I was extending by a few classes that did various Location based operations.
In the LocationContext abstract class I used:
mLocationManager.requestLocationUpdates(mProvider, mMinTime, mMinDistance,this, Looper.getMainLooper());
And in an implementation class (for example one for analysing GPS satellite status) I placed it in a new Thread:
new Thread(new Runnable() {
#Override
public void run() {
Looper.prepare();
GPSIndoorOutdoorContext.super.start();
mLocationManager.addGpsStatusListener(gpsListener);
Looper.loop();
}
}).start();
mLocationManager.requestLocationUpdates(mProvider, mMinTime, mMinDistance, this);
is getting called from a NON UI Thread. Make sure you call your init or call your method in the UI Thread. You're probably initiating LocationContext or calling start method from a NON UI Thread, which you can't do. To request location updates, it must be called from the UI Thread.
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);
}
}
In my project, there is a service that retrieves location of users. It continuously runs in background. I want to set location on my textview.
So, I have ManinActivity as follows:
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MainActivity extends Activity {
GPSTracker gps;
double mylatitude, mylongitude;
TextView txt_location;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt_location = (TextView)findViewById(R.id.current_location);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
public void btn_remember_Clicked(View v)
{
Intent i = new Intent(MainActivity.this,RememberActivity.class);
startActivity(i);
}
public void btn_show_places_Clicked(View v)
{
Intent i = new Intent(MainActivity.this,ShowPlacesActivity.class);
startActivity(i);
}
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
}
}
And my LocationService class is as follows:
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;
import android.widget.Toast;
public class LocationService extends Service
{
public static final String BROADCAST_ACTION = "Hello World";
private static final int TWO_MINUTES = 1000 * 60 * 2;
public LocationManager locationManager;
public MyLocationListener listener;
public Location previousBestLocation = null;
Intent intent;
#Override
public void onCreate()
{
super.onCreate();
intent = new Intent(BROADCAST_ACTION);
}
#Override
public int onStartCommand(Intent intent,int flags, int startId)
{
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
listener = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 4000, 0, listener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 4000, 0, listener);
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return true;
}
return false;
}
/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
#Override
public void onDestroy() {
// handler.removeCallbacks(sendUpdatesToUI);
super.onDestroy();
Log.v("STOP_SERVICE", "DONE");
locationManager.removeUpdates(listener);
}
public static Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
#Override
public void run() {
try {
runnable.run();
} catch(Exception e) {
System.out.print(e);
}
}
};
t.start();
return t;
}
public class MyLocationListener implements LocationListener {
public void onLocationChanged(final Location loc) {
Log.i("**************************************", "Location changed");
if(isBetterLocation(loc, previousBestLocation)) {
loc.getLatitude();
loc.getLongitude();
intent.putExtra("Latitude", loc.getLatitude());
intent.putExtra("Longitude", loc.getLongitude());
intent.putExtra("Provider", loc.getProvider());
sendBroadcast(intent);
}
}
public void onProviderDisabled(String provider) {
Toast.makeText( getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT ).show();
}
public void onProviderEnabled(String provider) {
Toast.makeText(getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show();
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
}
and I have LocationBroadcast class as follows:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class LocationBroadcast extends BroadcastReceiver{
#Override
public void onReceive(Context ctx, Intent intent) {
ctx.startService(new Intent(ctx, LocationService.class));
}
}
I want to set location on textview txt_location in MainActivity. I do not know much about services and how we can communicate within Activity. How can I get latitude and longitude in MainActivity? Please help.
Update:
I have just updated my code according to answers:
public class LocationService extends Service
{
private static final int TWO_MINUTES = 1000 * 60 * 2;
public LocationManager locationManager;
public MyLocationListener listener;
public Location previousBestLocation = null;
Intent i;
#Override
public void onCreate()
{
super.onCreate();
i = new Intent("LOCATION_CHANGED");
}
#Override
public int onStartCommand(Intent intent,int flags, int startId)
{
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
listener = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 4000, 0, listener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 4000, 0, listener);
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return true;
}
return false;
}
/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
#Override
public void onDestroy() {
// handler.removeCallbacks(sendUpdatesToUI);
super.onDestroy();
Log.v("STOP_SERVICE", "DONE");
locationManager.removeUpdates(listener);
}
public static Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
#Override
public void run() {
try {
runnable.run();
} catch(Exception e) {
System.out.print(e);
}
}
};
t.start();
return t;
}
public class MyLocationListener implements LocationListener
{
public void onLocationChanged(final Location loc)
{
Log.i("**************************************", "Location changed");
if(isBetterLocation(loc, previousBestLocation)) {
String newLocation = "Lat: " + loc.getLatitude() + " and Long: " + loc.getLongitude();
i = new Intent("LOCATION_CHANGED");
i.putExtra("location", newLocation);
sendBroadcast(i);
}
}
public void onProviderDisabled(String provider)
{
Toast.makeText( getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT ).show();
}
public void onProviderEnabled(String provider)
{
Toast.makeText(getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show();
}
public void onStatusChanged(String provider, int status, Bundle extras)
{
}
}
}
And I have received broadcasted intent in MainActivity as follows:
public class MainActivity extends Activity {
TextView txt_location;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt_location = (TextView)findViewById(R.id.current_location);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
}
public class LocationBroadcast extends BroadcastReceiver {
#Override
public void onReceive(Context ctx, Intent intent) {
txt_location.setText(intent.getExtras().getString("location"));
}
}
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
}
}
As you can see, it is not showing any location updates. Logcat isn't showing any errors. Can anyone please guide me what is the mistake?
Create a BroadcastReceiver in the MainActivity like
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context appContext, Intent intent) {
.......
//get location from Service and create Method for set location on textview txt_location
}
};
registerReceiver in onResume of MainActivity
registerReceiver(broadcastReceiver, new IntentFilter(GET_LOCATION));
and declare this in starting MainActivity
private static final String GET_LOCATION = "com.pkg.location";
and in your service pass your location as a broadcase
Intent intent = new Intent(GET_LOCATION);
intent.putExtra("location", "your_location_got_from_service");
sendBroadcast(intent);
and dont forget to unregisterReceiver in MainActivity
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
}
You can use BroadcastReceiver to receive the event of your LOCATION_CHANGED, and update the TextView from its onReceive method:
In your activity:
TextView textView = (TextView) findViewById(R.id.location_text); //global variable
registerReceiver(locationChangedReceiver, new IntentFilter("LOCATION_CHANGED"));
//your receiver class as inner class of activity.
private BroadcastReceiver locationChangedReceiver= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
textView.setText(intent.getExtras().getString("location"));
}
};
In your service, you can simply broadcast for "LOCATION_CHANGED", and pass String location as intent's extra argument.
String newLocation = "Lat: " + loc.getLatitude() + " and Long: " + loc.getLongitude();
Intent i = new Intent("LOCATION_CHANGED");
i.putExtra("location", newLocation);
sendBroadcast(i);
If you want to keep a separate receiver class (not in activity), you can use your context to update views like this:
public class LocationBroadcast extends BroadcastReceiver{
#Override
public void onReceive(Context ctx, Intent intent) {
TextView textView = (TextView) ctx.findViewById(R.id.location_text);
textView.setText(intent.getExtras().getString("location"));
}
}
Hope it helps.
i'm creating an app that show user's location into a map, now i want to update the user location when the app is in background,especially i want to start the Service when the Activity's method onPause() is called.
my activity:
public class MapsActivity extends Activity implements OnClickListener, GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener, LocationListener, OnInfoWindowClickListener {
private static final long UPDATE_INTERVAL = 5000;
private static final long FASTEST_INTERVAL = 1000;
private GoogleMap map = null;
private LocationClient locationClient;
private Location myLocation;
private LocationRequest locationRequest;
private LatLng newPosition;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
locationClient = new LocationClient(this, this, this);
locationRequest = LocationRequest.create().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY).setInterval(UPDATE_INTERVAL)
.setFastestInterval(FASTEST_INTERVAL).setSmallestDisplacement(10);
if (locationClient != null)
// connect the client to the Google Play services
locationClient.connect();
}
#Override
public void onLocationChanged(Location location) {
newPosition = new LatLng(location.getLatitude(), location.getLongitude());
myLocation = location;
if (myLocation != null)
button.setClickable(true);
else
button.setClickable(false);
map.animateCamera(CameraUpdateFactory.newLatLngZoom(newPosition, 20));
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
}
#Override
public void onConnected(Bundle arg0) {
Toast.makeText(this, "I'm bringing you to your area.", Toast.LENGTH_SHORT).show();
// start periodic updates
locationClient.requestLocationUpdates(locationRequest, this);
}
#Override
public void onDisconnected() {
Toast.makeText(this, "Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
}
public ProgressDialog getProgress() {
return progress;
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onRestart() {
super.onRestart();
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onStop() {
super.onStop();
}
#Override
protected void onDestroy() {
if (locationClient.isConnected() && locationClient != null) {
locationClient.removeLocationUpdates(this);
locationClient.disconnect();
}
super.onDestroy();
}
}
my Service Class:
public class locationBackgroundService extends Service implements LocationListener, GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
private LocationRequest mLocationRequest;
private LocationClient mLocationClient;
public locationBackgroundService() {
}
#Override
public void onCreate() {
mLocationRequest = LocationRequest.create();
// mLocationRequest.setInterval(CommonUtils.UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// mLocationRequest.setFastestInterval(CommonUtils.FAST_INTERVAL_CEILING_IN_MILLISECONDS);
mLocationClient = new LocationClient(getApplicationContext(), this, this);
mLocationClient.connect();
}
#Override
public void onStart(Intent intent, int startId) {
int start = Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
#Override
public void onConnected(Bundle arg0) {
Log.i("info", "Location Client is Connected");
mLocationClient.requestLocationUpdates(mLocationRequest, this);
Log.i("info", "Service Connect status :: " + isServicesConnected());
}
#Override
public void onDisconnected() {
Log.i("info", "Location Client is Disconnected");
}
#Override
public void onLocationChanged(Location location) {
double latitude = location.getLatitude();
double longitude = location.getLongitude();
}
private boolean isServicesConnected() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(locationBackgroundService.this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
return true;
} else {
return false;
}
}
#Override
public void onDestroy() {
mLocationClient.removeLocationUpdates(this);
super.onDestroy();
}
}
is it possible to do that?
thanks in advance.
example of LocationService.class
package com.example.myapp;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.example.myapp.activities.MainActivity;
public class LocationService extends Service implements
LocationListener,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
public static final String LOCATION_SERVICE = "LocationService";
private LocationClient mLocationClient;
private LocationRequest mLocationRequest;
float minDist = 100f;
int minTime = 10000;
PendingIntent contentIntent;
public static String USER_LATITUDE = "user_latitude";
public static String USER_LONGITUDE = "user_longitude";
#Override
public void onCreate() {
Log.d("onCreate", "");
super.onCreate();
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
mLocationClient = new LocationClient(this, this, this);
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(minTime);
//mLocationRequest.setSmallestDisplacement(minDist);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mLocationClient.connect();
return Service.START_NOT_STICKY;
}
#Override
public void onLocationChanged(Location location) {
float latitude = (float) location.getLatitude();
float longitude = (float) location.getLongitude();
Log.d("onLocationChanged. latLng", latitude + ", " + longitude);
Intent intent = new Intent(LOCATION_SERVICE);
intent.putExtra(USER_LATITUDE, latitude);
intent.putExtra(USER_LONGITUDE, longitude);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
#Override
public void onDestroy() {
super.onDestroy();
if (mLocationClient.isConnected() ) {
stopPeriodicUpdates();
}
}
#Override
public void onConnected(Bundle bundle) {
Log.d(LOCATION_SERVICE, "onConnected");
startPeriodicUpdates();
}
#Override
public void onDisconnected() {
Log.d(LOCATION_SERVICE, "onDisconnected");
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(LOCATION_SERVICE, "onConnectionFailed");
}
public void startPeriodicUpdates() {
mLocationClient.requestLocationUpdates(mLocationRequest, this);
Log.d(LOCATION_SERVICE, "startPeriodicUpdates");
}
private void stopPeriodicUpdates() {
mLocationClient.removeLocationUpdates(this);
Log.d(LOCATION_SERVICE, "stopPeriodicUpdates");
}
}
add in MainActivity.class
private boolean servicesConnected() {
int resultCode =
GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == resultCode) {
Log.d("servicesConnected", "Google play services isConnected");
return true;
} else {
return false;
}
}
private BroadcastReceiver mLocationReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
float latitude = intent.getFloatExtra(LocationService.USER_LATITUDE, 0);
float longitude = intent.getFloatExtra(LocationService.USER_LONGITUDE, 0);
//do something
}
};
#Override
public void onPause() {
super.onPause();
Intent service = new Intent(this, LocationService.class);
IntentFilter intentLocationServiceFilter = new IntentFilter(LocationService
.LOCATION_SERVICE);
LocalBroadcastManager.getInstance(this)
.registerReceiver(mLocationReceiver, intentLocationServiceFilter);
if (servicesConnected()) {
startService(service);
}
}
And do not forget add to AndroidManifest file your LocationService
I'm developing a tracking app. and i have problem with GPS module. The app must record a route. App work fine, but sometimes when the device is not moving, GPS still receive
continuous coordinate that don't indicate my position, error is within a radius of 20 meter, and when I'm moving again work fine.
Please give me some tips that can help me to fix this problem. Thanks a lot.
I have 3 calsses
1 - GPSReceiver here is method for get location
public void getMyLoction(){
_locationManager = (LocationManager) _context.getSystemService(LOCATION_SERVICE);
_isGPSEnabled =_locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (_isGPSEnabled) {
if (_location == null) {
_locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0, this);
if (_locationManager != null) {
_location = _locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
setLocation(_location);
}
}
}
}
2 RecordingActivity (take coordonates form services and processes then) work fine, a comment in method what they do.
public class RecordingActivity extends FragmentActivity {
public final static String BROADCAST_ACTION = "map.trackv";
public BroadcastReceiver receiver;
private GoogleMap map;
private TextView _messageToUser;
private Coordinate _pointFromService;
private long _timeWhenStartButtonWasPressed;
private List<Coordinate> _unprocessedCoords;
private List<Coordinate> _processedCoords;
private Button _stopButton;
private Button _startButton;
private String _startRecordingDate;
private String _stopRecordingDate;
private GPSReceiver _gps;
private DataBaseOperations _dataSource;
private boolean _recording;
private boolean _gpsStatus;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recording_route);
initActvity();
checkIfGPSisOn();
try {
Runtime.getRuntime().exec("logcat -f" + " /sdcard/Logcat.txt");
} catch (IOException e) {
// TODO Auto-generated catch block
Log.d("nu pot", "DDDDD");
e.printStackTrace();
}
receveirWork();
IntentFilter intentFilt = new IntentFilter(BROADCAST_ACTION);
registerReceiver(receiver, intentFilt);
}
public void checkIfGPSisOn() {
//check on start
}
public void receveirWork() {
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// request points and process then,
}
};
}
#Override
protected void onDestroy() {
super.onDestroy();
if (_stopButton.isEnabled())
{
stopService(new Intent(this, RecordingService.class));
_unprocessedCoords = null;
_processedCoords = null;
}
unregisterReceiver(receiver);
}
#Override
protected void onResume() {
if (!_stopButton.isEnabled()) {
_startButton.setEnabled(true);
_messageToUser.setText(Constants.PRESS_START_BUTTON);
map.clear();
}
super.onResume();
}
// actiune buton start;
public void startButtonEvent(View V) {
buttonsStateAndMessageToShow(false, true, Constants.MESSAGE_TO_WAIT);
_timeWhenStartButtonWasPressed = System.currentTimeMillis();
startService(new Intent(this, RecordingService.class));
// start service to get position
}
public void stopButtonEvent(View V) {
stopService(new Intent(this, RecordingService.class));
// stop service
// save route in BD
// resetData;
}
public void initActvity() {
// init date
}
#Override
protected void onSaveInstanceState(Bundle outState) {
// save state
}
}
3 RecordingServices class, ii think here is the problem.
public class RecordingService extends Service {
private Thread _backgroundWork;
private boolean _threadCanRun;
private GPSReceiver _gps;
private Coordinate _pointToSent;
public void onCreate() {
super.onCreate();
_threadCanRun = true;
_backgroundWork = new Thread(new Runnable() {
#Override
public void run() {
Looper.prepare();
getLocationFromGPS();
Looper.loop();
}
});
}
public int onStartCommand(Intent intent, int flags, int startId) {//
_backgroundWork.start();
return super.onStartCommand(intent, flags, startId);
}
public void onDestroy() {
_threadCanRun = false;
super.onDestroy();
}
public IBinder onBind(Intent intent) {
return null;
}
public void getLocationFromGPS() {
while (_threadCanRun) {
Intent _intent = new Intent(RecordingActivity.BROADCAST_ACTION);
_gps = new GPSReceiver(this);
_gps.getMyLoction();
if (_gps.getIsGPSEnabled()) {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {}
sentPoint(_intent);
} else {
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {}
_intent.putExtra("latitude", 0);
_intent.putExtra("longitude", 0);
_intent.putExtra("time", 0);
_intent.putExtra("GPSstatus", false);
sendBroadcast(_intent);
}
}
}
private void sentPoint(Intent _intent) {
_pointToSent = new Coordinate(_gps.getLatitude(), _gps.getLongitude(), _gps.getTime());
_intent.putExtra("latitude", _pointToSent.getLatitude());
_intent.putExtra("longitude", _pointToSent.getlongitude());
_intent.putExtra("time", _pointToSent.getTime());
_intent.putExtra("GPSstatus", _gps.getIsGPSEnabled());
sendBroadcast(_intent);
_pointToSent = null;
}
}
repeating the Location update request depends on how u implemented your tracking system
but in general(which is not recommended , just change your request update rate to save client Battery usage) you can find the distance between your locations by location1.distanceTo(location2) so if the distance is smaller than 30m then put the new location away