onLocationChanged event is not fired with requestSingleUpdate.
It seems that it depends on the looper attached ex:
locManager.requestSingleUpdate("network",locListener,Looper.getMainLooper());
locManager.requestSingleUpdate("network",locListener,null);
locManager.requestSingleUpdate("network",locListener,Looper.myLooper());
are not giving the same results with the emulator and the device !
Questions
If requestSingleUpdate is called many times (with different providers), only the last query will be taken ?
requestSingleUpdate must be called on ui thread ? If not, there's a trick to call it outside ?
Complete Class :
public class LocationNew {
private Context context;
public LocationNew(Context context) {
this.context = context;
}
public void requestNew(Looper paramLooper){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int permissionLocation = ContextCompat.checkSelfPermission(DooodApp.getContext(), Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionLocation != PackageManager.PERMISSION_GRANTED) {
return;
}
}
LocationManager locManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
List<String> listProv = locManager.getProviders(true);
for (String provTmp: listProv) {
locManager.requestSingleUpdate(provTmp,locListener,Looper.getMainLooper());
}
}
private LocationListener locListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Toast.makeText(context, "New location from : " + location.getProvider(), Toast.LENGTH_SHORT).show();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Toast.makeText(context, "onStatusChanged" , Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderEnabled(String provider) {
Toast.makeText(context, "onProviderEnabled" , Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderDisabled(String provider) {
Toast.makeText(context, "onProviderDisabled" , Toast.LENGTH_SHORT).show();
}
};
}
Thank's to all.
Related
I'm doing a flutter project,my problem is:
how to make the GPS function work normally when the app is running in the background,i use Service,but only when the app is in the foreground can GPS get it.
this is my code:
#Override
public void onCreate()
{
//
startService();
Log.v(tag, "GPSService Started.");
}
#TargetApi(Build.VERSION_CODES.M)
public void startService()
{
boolean isOpen = isOPen();
if (isOpen) {
initLocation();
return;
}
}
#TargetApi(Build.VERSION_CODES.M)
private void initLocation() {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.mainThis, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_CODE);
return;
}
if (network&&gps){
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 500,0, listener); // network locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500, 8, listener); // gps
}else if(network&&!gps){
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 500,8, listener); // n
}else {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500, 8, listener); // g
}
}
LocationListener listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
updateShow(location);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#SuppressLint("MissingPermission")
#Override
public void onProviderEnabled(String provider) {
updateShow(locationManager.getLastKnownLocation(provider));
}
#Override
public void onProviderDisabled(String provider) {
updateShow(null);
}
};
The article below has the caption "How to fetch user location in background with Flutter".
With subtopics like this,
How to fetch a user location
How to fetch it even if the app is running in the background
The limitations of the system
https://medium.com/#pierre.sabot/how-to-fetch-user-location-in-background-with-flutter-e3494021bdf5
I have one Android Service. This Service launch one class for geolocation. This is the code.
public class Localizar implements LocationListener {
private LocationManager manejador;
private Context context;
private DBAdapter db;
public Localizar(Context context) {
this.context = context;
db = new DBAdapter(context);
}
public void start() {
manejador = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (manejador.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
manejador.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 500, 0, this);
}else {
}
}
public void stop() {
manejador.removeUpdates(this);
}
private void saveData(double longitude, double latitude) {
Toast.makeText(context, "G R A B A N D O D A T O S", Toast.LENGTH_LONG).show();
}
public void onLocationChanged(Location location) {
saveData(location.getLatitude(), location.getLongitude());
}
public void onProviderDisabled(String proveedor) {
}
public void onProviderEnabled(String proveedor) {
}
public void onStatusChanged(String arg0, int arg1, Bundle bundle) {
}
}
My problem is that the method onLocationChanged never executed. What have I done wrong ?
Thank you!
I tried it on another phone and it works correctly, maybe my phone is broken. I have a samsung galaxy DUOS.....
There is a lot reasons why you don't get onLocationChanged
If you run it in Service try add Looper.getMainLooper(), like:
manejador.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
500,
0,
this,
Looper.getMainLooper()
);
I have a class for get the user location.
If the GPS is off I turned it on and show the location, but it doesnt work.
this is the class:
public class UseGPS implements Runnable{
Activity activity;
Context context;
private ProgressDialog pd;
LocationManager mLocationManager;
Location mLocation;
MyLocationListener mLocationListener;
Location currentLocation = null;
public UseGPS(Activity Activity, Context Context){
this.activity = Activity;
this.context = Context;
}
public void getMyPos(){
DialogInterface.OnCancelListener dialogCancel = new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
Toast.makeText(activity,"no gps signal",Toast.LENGTH_LONG).show();
handler.sendEmptyMessage(0);
}
};
pd = ProgressDialog.show(activity,context.getString(R.string.looking_for), context.getString(R.string.gps_signal), true, true, dialogCancel);
writeSignalGPS();
}
private void setCurrentLocation(Location loc) {
currentLocation = loc;
}
private void writeSignalGPS() {
Thread thread = new Thread(this);
thread.start();
}
public void run() {
mLocationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
Looper.prepare();
mLocationListener = new MyLocationListener();
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener);
Looper.loop();
Looper.myLooper().quit();
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
pd.dismiss();
mLocationManager.removeUpdates(mLocationListener);
if (currentLocation!=null) {
Toast.makeText(activity,currentLocation.getLatitude(),Toast.LENGTH_LONG).show();
Toast.makeText(activity,currentLocation.getLongitude(),Toast.LENGTH_LONG).show();
}
}
};
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
if (loc != null) {
setCurrentLocation(loc);
handler.sendEmptyMessage(0);
}
}
#Override
public void onProviderDisabled(String provider) {
/*turn on GPS*/
Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", true);
context.sendBroadcast(intent);
}
#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
}
}
}
The code works when the GPS is turned on, but it doesnt turn the gps on.
What can I do?
While launching time of your app, give one pop-up message with option to turn on the GPS by the user.
This pop-up button navigates to GPS setting in Setting for their user can turn on the GPS.
Here is the code snippet:
AlertDialog gpsonBuilder = new AlertDialog.Builder(Home_Activity.this);
gpsonBuilder.setTitle("Your Gps Provider is disabled please Enable it");
gpsonBuilder.setPositiveButton("ON",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
});
gpsonBuilder.show();
There is the following code for getting current location:
final LocationManager manager=(LocationManager)getSystemService(Context.LOCATION_SERVICE);
LocationListener listener=new LocationListener() {
#Override
public void onLocationChanged(Location location) {
manager.removeUpdates(this);
Toast.makeText(MainActivity.this, "2", Toast.LENGTH_LONG).show();
if (location!=null) {
doSomeAction();
}
else {
Toast.makeText(MainActivity.this, LOCATION_IS_NULL_MESSAGE, Toast.LENGTH_LONG).show();
}
}
#Override
public void onProviderDisabled(String provider) {
manager.removeUpdates(this);
String newProvider=provider.equals(LocationManager.GPS_PROVIDER) ? LocationManager.NETWORK_PROVIDER : null;
if (newProvider==null) {
Toast.makeText(MainActivity.this, LOCATION_PROVIDERS_ARE_DISABLED_MESSAGE, Toast.LENGTH_LONG).show();
}
else {
manager.requestLocationUpdates(newProvider, 0, 0, this);
}
}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {}
};
String provider=manager.isProviderEnabled(LocationManager.GPS_PROVIDER) ? LocationManager.GPS_PROVIDER :
LocationManager.NETWORK_PROVIDER;
Location location=manager.getLastKnownLocation(provider);
if (location!=null) {
doSomeAction();
}
else {
Toast.makeText(this, "1", Toast.LENGTH_LONG).show();
manager.requestLocationUpdates(provider, 0, 0, listener);
}
I see toast "1" each time, but I've never seen "2" toast, therefore my location isn't be updated. Please, tell me, I need to get my current location - how can I fix my problem? I use network location provider.
Did you actually attach the listener? With out attaching the listener its code is useless, but furthermore afaik: If the LocationManager has no Listener attached it will not update any location.
Try like this :
public class Locato extends Activity implements LocationListener {
LocationManager locman;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.idlayout);
locman = (LocatonManager) getSystemService(Context.LOCATION_SERVICE);
}
public void onStatusChanged(String pr, int s, Bundle a) {}
#Override
public void onProviderDisabled(String provider) {
Log.d("MyApp", "Provider disabled : " + provider);
}
#Override
public void onProviderEnabled(String provider) {
Log.d("MyApp", "Provider enabled : " + provider);
}
#Override
public void onLocationChanged(Location location) {
// do something
}
You must also add permissions to manifest : access coarse location and access fine location
I'm beta testing my first Android app and have had a few users mention that when they attempt to lookup by GPS it hangs. In order to improve error handling around this I wanted to get the opinion of people who have apps in the wild.
My current activity does the following to kick off the lookup
findViewById(R.id.gpsButton).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LocationManager mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
MyLocationListener mlocListener = new MyLocationListener();
Criteria locationCriteria = new Criteria();
locationCriteria.setAccuracy(Criteria.ACCURACY_FINE);
mlocManager.requestLocationUpdates(mlocManager.getBestProvider(locationCriteria, true), 0, 0, mlocListener);
}
});
The implementation of my custom location lookup class is below
public class MyLocationListener implements LocationListener {
private boolean alreadyLocatedDevice;
private ProgressDialog dialog;
public MyLocationListener() {
this.dialog = ProgressDialog.show(LocationLookup.this, "", "Loading...");
}
#Override
public void onProviderDisabled(String provider) {
this.dialog.dismiss();
DialogHelper.showDialogWithMessageAndTitle("", "You don't currently have location services turned on", LocationLookup.this);
}
#Override
public void onLocationChanged(android.location.Location location) {
if (!alreadyLocatedDevice) {
alreadyLocatedDevice = true;
Location loc = new Location();
loc.setLng(Double.toString(location.getLongitude()));
loc.setLat(Double.toString(location.getLatitude()));
((AppDelegate) getApplicationContext()).setSelectedLocation(loc);
Intent findKioskLocation = new Intent(LocationLookup.this, FindKioskLocation.class);
this.dialog.dismiss();
startActivity(findKioskLocation);
}
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
//To change body of implemented methods use File | Settings | File Templates.
}
#Override
public void onProviderEnabled(String s) {
//To change body of implemented methods use File | Settings | File Templates.
}
}
And finally I've added both the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions in my manifest file.
Any help would be much appreciated!
Here is a nice implementation that I recnetly looked at. Basically by default it uses GPS to get a location. If no location can be found within a certain time period or no satellites are available it switches to Network.
Hope this helps
A Stacktrace from the logcat would have helped you and other developers here understand where the problem is coming from. Try to ask the users to recreate the problem if possible and find out when it is occurring.
As for guidance with the locaton manager, Google Developers just posted a blog recently and also updated the docs on how to use location manager. Check the documentation here and also the blog post which explains it with an example. That might help you better. The blog post also explains how to use different location providers and how to be user friendly and guidance necessary in most ases when using location in Android applications.
For anyone who might follow this thread -I found a mixture of my own approach (admittedly hackish in this code example) and the one mentioned by #bear to work without any issues (plus the location lookup was fast/accurate and error free)
I found the example listed by #bear to be a little more complex than I needed. For starters I wanted to kick off the GPS lookup when a button was clicked and have a simple async task wrapping this so it would throw up a dialog/etc
Next I wanted the exact latitude and longitude (no need to pass this off to another class because my example was simply to use the lat + lng to locate a resource and plot it)
So if you can follow my untested rather copy/paste approach here goes...
Inside your activity you would spin up the service during an onclick lets say ...
LocationManager networkManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationManager gpsManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationService locationProcessor = new LocationService(YourActivityName.this, networkManager, gpsManager, dialog);
locationProcessor.onStartCommand();
Now the location service itself
package com.epicsoftware.android.global;
import android.app.ProgressDialog;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import com.epicsoftware.android.activity.LocationLookup;
public class LocationService {
private LocationManager networkLm;
private LocationManager gpsLm;
private LocationListener networkListener;
private LocationListener gpsListener;
private boolean isRunning;
private boolean networkLocDisabled;
private boolean gpsLocDisabled;
private Context activity;
private LocationManager tmpNetworkManager;
private LocationManager tmpGpsManager;
private Handler locationHandler;
private ProgressDialog dialog;
private boolean gpsUpdated;
private boolean done;
public LocationService(final Context activity, LocationManager networkManager, LocationManager gpsManager, ProgressDialog dialog) {
this.tmpNetworkManager = networkManager;
this.tmpGpsManager = gpsManager;
this.activity = activity;
this.dialog = dialog;
}
public void onStartCommand() {
if (!isRunning) {
isRunning = true;
startLocationListeners();
locationHandler = new Handler();
getLocationByZip.start();
}
}
private void startLocationListeners() {
networkListener = new NetworkLocationListener();
gpsListener = new GpsLocationListener();
networkLm = tmpNetworkManager;
gpsLm = tmpGpsManager;
networkLm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, networkListener);
gpsLm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpsListener);
}
private Thread getLocationByZip = new Thread() {
public void run() {
try {
for (int i = 0; i < 15;) {
if (!locationDisabled() || !gpsUpdated) {
try {
Thread.sleep(1000);
} catch (Exception e) {
break;
}
i++;
} else {
break;
}
}
locationHandler.post(monitorTheNetworkAndGpsProviders);
} catch (Exception e) {
killService();
done = true;
}
}
};
private Runnable monitorTheNetworkAndGpsProviders = new Runnable() {
#Override
public void run() {
killService();
dialog.dismiss();
if (!done) {
done = true;
((LocationLookup) activity).warnUserThatLocationServicesAreDisabledOrFailed();
}
}
};
private boolean locationDisabled() {
if (gpsLocDisabled && networkLocDisabled) {
done = true;
((LocationLookup) activity).warnUserThatLocationServicesAreDisabledOrFailed();
return true;
} else {
return false;
}
}
private void updateDb(Double lat, Double lon) {
done = true;
((LocationLookup) activity).setLocationDataAndSpinUpNextActivity(lat, lon);
}
public void killService() {
networkLm.removeUpdates(networkListener);
gpsLm.removeUpdates(gpsListener);
}
public class NetworkLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
if (location != null) {
updateDb(location.getLatitude(), location.getLongitude());
}
}
#Override
public void onProviderDisabled(String provider) {
networkLocDisabled = true;
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
public class GpsLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
if (location != null) {
gpsUpdated = true;
updateDb(location.getLatitude(), location.getLongitude());
}
}
#Override
public void onProviderDisabled(String provider) {
gpsLocDisabled = true;
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
}