I'm trying to write a service to locate the user by it's GPs location in Android. I wrotre a service for that. But alwasy when I try to start the service the error
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want? appears. I already searched for this problem on google and added the follwoing line to my sourcecode:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
But the Error still appears. What can I do in order to make the service start without any errors? Here is my code:
MainActivity.java:
public class MainActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start);
//GPs Standort bestimmung starten
Intent intent;
intent = new Intent(this, Gps_Service.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startService(intent);
initButtons();
}
}
"Gps_service.java":
public class Gps_Service extends Service implements LocationListener{
private double längengrad = 0.0, breitengrad = 0.0;
LocationManager locationManager;
Address adresse;
String straße, Ort, Land;
#Override
public void onCreate(){
super.onCreate();
locationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(locationManager.GPS_PROVIDER, 10000, 100, this);
}
#Override
public void onDestroy(){
super.onDestroy();
locationManager.removeUpdates(this);
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onLocationChanged(Location location) {
längengrad = location.getLongitude();
breitengrad = location.getLatitude();
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
Instead of running a service to retreive the user's location via GPS, use Google's Fused Location API.
The link provided has a detailed guide about how to implement it and is much more reliable and accurate in receiving location data.
Don't forget this gradle dependency as well:
compile 'com.google.android.gms:play-services-location:8.4.0'
Related
I'm using the following code to change two text views based on when the user turns on/off their network and their GPS. I was able to get the network text view to work but not the location text view. I think I am using the wrong filter, but I don't know which to use instead. Any suggestions/answers?
public class MainActivity extends AppCompatActivity {
TextView networkTextView;
TextView locationTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
networkTextView = findViewById(R.id.networkTextView);
locationTextView = findViewById(R.id.locationTextView);
IntentFilter filter1 = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(broadcastReceiver1, filter1);
IntentFilter filter2 = new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION);
registerReceiver(broadcastReceiver2, filter2);
}
BroadcastReceiver broadcastReceiver1 = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
boolean noNetworkConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (noNetworkConnectivity) {
networkTextView.setText("Disconnected");
} else {
networkTextView.setText("Connected");
}
}
}
};
BroadcastReceiver broadcastReceiver2 = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (LocationManager.PROVIDERS_CHANGED_ACTION.equals(intent.getAction())) {
boolean noLocationConnectivity = intent.getBooleanExtra(LocationManager.PROVIDERS_CHANGED_ACTION, false);
if (noLocationConnectivity) {
locationTextView.setText("Disconnected");
} else {
locationTextView.setText("Connected");
}
}
}
};
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(broadcastReceiver1);
unregisterReceiver(broadcastReceiver2);
}
}
Update:
In the broadcast receiver for the location I replaced
boolean noLocationConnectivity = intent.getBooleanExtra(LocationManager.PROVIDERS_CHANGED_ACTION, false);
with
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
boolean locationConnectivity = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
but that didn't work. Maybe need to request location data permission from user?
Update 2:
Realized that it is registering boolean changes of the LocationManager.GPS_provider, but not initially. Only after the Location setting is manually changed after the app is started does the text change, unlike with the network check that changes the text as soon as the app starts.
I think that this question has already been answered here
But I'm thinking if use LocationManager and LocationListener is a good idea or not, I mean, LocationListener has those overrided methods:
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
I leave it to your consideration
The thing is that I'm trying on the emulator, and it works but only once I press the "send location to device" on the emulator but before that I don't have the chance to get the location....How do I get the location for the first time using this service?. I don't have a real device right know and the emulator is my only way of testing this for now.....I tried to send a 0,0 at first to see if that would trigger a location update but it's not working as well......any ideas?
#SuppressWarnings("MissingPermission")
public class GPSService extends Service {
private LocationListener listener;
private LocationManager locationManager;
private String lastKnownLatitude;
private String lastKnownLongitude;
private Boolean isFirstTime=true;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
broadcastLocation("0","0");
listener= new LocationListener() {
#Override
public void onLocationChanged(Location location) {
//To transfer the data to the main activity I use broadcast receiver in the main activity, using an intent filter location_update
Intent intentSendLocationMainActivity = new Intent("location_update");
lastKnownLatitude=""+location.getLatitude();
lastKnownLongitude=""+location.getLongitude();
Log.d("LOCATION-UPDATE",lastKnownLatitude+" long:"+lastKnownLongitude);
broadcastLocation(lastKnownLatitude,lastKnownLongitude);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
Log.d("GPS-Stat-Changed",s);
}
#Override
public void onProviderEnabled(String s) {
Log.d("GPS-Provider-Enabled",s);
}
#Override
public void onProviderDisabled(String s) {
Intent activateGPSIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
activateGPSIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activateGPSIntent);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
//noinspection MissingPermission, listen for updates every 3 seconds
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,5000,0,listener);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("ClearFromRecentService", "Service Started");
Log.d("LAST_LAT_AND_LONG",lastKnownLatitude+" "+lastKnownLongitude);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("ClearFromRecentService", "Service Destroyed, Removing update location listener");
//unregistering the listener
/*if(locationManager != null){
locationManager.removeUpdates(listener);
}*/
}
public void onTaskRemoved(Intent rootIntent) {
Log.e("ClearFromRecentService", "END");
//here you can call a background network request to post you location to server when app is killed
Toast.makeText(getApplicationContext(), "I'm still getting user coordinates", Toast.LENGTH_LONG).show();
//stopSelf(); //call this method to stop the service
}
public void broadcastLocation(String latitude,String longitude){
Intent intentSendLocationMainActivity = new Intent("location_update");
intentSendLocationMainActivity.putExtra("latitude",latitude);
intentSendLocationMainActivity.putExtra("longitude",longitude);
//I need to differentiate here if the app is killed or not to send the location to main activity or to a server
sendBroadcast(intentSendLocationMainActivity);
}
}
EDIT: This is the complete service working. For the first time it gets the coordinates with the getLastKnownLocation() and the on sucesive times with the listener onLocationChanged()
#SuppressWarnings("MissingPermission")
public class GPSService extends Service {
private LocationListener listener;
private LocationManager locationManager;
private String lastKnownLatitude;
private String lastKnownLongitude;
private Boolean isFirstTime=true;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
listener= new LocationListener() {
#Override
public void onLocationChanged(Location location) {
//To transfer the data to the main activity I use broadcast receiver in the main activity, using an intent filter location_update
Intent intentSendLocationMainActivity = new Intent("location_update");
lastKnownLatitude=""+location.getLatitude();
lastKnownLongitude=""+location.getLongitude();
Log.d("LOCATION-UPDATE",lastKnownLatitude+" long:"+lastKnownLongitude);
broadcastLocation(lastKnownLatitude,lastKnownLongitude);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
Log.d("GPS-Stat-Changed",s);
}
#Override
public void onProviderEnabled(String s) {
Log.d("GPS-Provider-Enabled",s);
}
#Override
public void onProviderDisabled(String s) {
Intent activateGPSIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
activateGPSIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activateGPSIntent);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
//noinspection MissingPermission, listen for updates every 3 seconds
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,5000,0,listener);
Map<String, String> coordinates=getLastKnownLocation(locationManager);
broadcastLocation(coordinates.get("latitude"),coordinates.get("longitude"));
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("ClearFromRecentService", "Service Started");
Log.d("LAST_LAT_AND_LONG",lastKnownLatitude+" "+lastKnownLongitude);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("ClearFromRecentService", "Service Destroyed, Removing update location listener");
//unregistering the listener
/*if(locationManager != null){
locationManager.removeUpdates(listener);
}*/
}
public void onTaskRemoved(Intent rootIntent) {
Log.e("ClearFromRecentService", "END");
//here you can call a background network request to post you location to server when app is killed
Toast.makeText(getApplicationContext(), "I'm still getting user coordinates", Toast.LENGTH_LONG).show();
//stopSelf(); //call this method to stop the service
}
private void broadcastLocation(String latitude,String longitude){
Intent intentSendLocationMainActivity = new Intent("location_update");
intentSendLocationMainActivity.putExtra("latitude",latitude);
intentSendLocationMainActivity.putExtra("longitude",longitude);
//I need to differentiate here if the app is killed or not to send the location to main activity or to a server
sendBroadcast(intentSendLocationMainActivity);
}
private Map<String, String> getLastKnownLocation(LocationManager lm){
Location lastKnownLocation=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
String ll=""+lastKnownLocation.getLatitude();
Map<String, String> coordinates = new HashMap<String, String>();
// Check everytime this value, it may be null
if(lastKnownLocation != null){
coordinates.put("latitude",""+lastKnownLocation.getLatitude());
coordinates.put("longitude",""+lastKnownLocation.getLongitude());
}else{
coordinates.put("latitude","0");
coordinates.put("longitude","0");
}
return coordinates;
}
}
#Override
public void onCreate() {
super.onCreate();
locationManager = (LocationManager) getApplicationContext()
.getSystemService(Context.LOCATION_SERVICE);
Location lastKnownLocation = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
// Check everytime this value, it may be null
if(lastKnownLocation != null){
double latitude = lastKnownLocation.getLatitude();
double longitude = lastKnownLocation.getLongitude();
// Use values as you wish
}
broadcastLocation("0","0");
....
}
I thought this would be super easy - but this is taking waaaay longer than it should.
I'm simply trying to get the GPS coordinates to go to the logcat, that's literally it.
The intent fires fine. The "Intent Fired" message appears every time. The application just refuses to go to the location changed event.
If someone could take a look and let me know where I'm failing, it would be super appreciated.
public class MyReceiver extends IntentService implements LocationListener {
private LocationManager locationManager;
public MyReceiver() {
super("MyReceiver");
}
protected void onHandleIntent(Intent intent) {
Log.i("DebugMe", "Intent Fired");
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
}
public void onLocationChanged(Location location) {
String lat = String.valueOf(location.getLatitude());
String lon = String.valueOf(location.getLongitude());
Log.i("DebugMe", lat + " " + lon);
locationManager.removeUpdates(this);
}
public void onProviderDisabled(String provider) {
Log.d("DebugMe ", "Disabled");
}
public void onProviderEnabled(String provider) {
Log.d("DebugMe","Enabled");
}
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d("DebugMe","Status");
}
}
Thank you
Well, the location manager works asynchronously, and IntentService is implemented in such a way, that when onHandleIntent(Intent intent) returns, the service stops itself. That means it's destroyed before any location can be provided to your onLocationChanged(location location) method. If you want to use IntentService you need to block the onHandleIntent(Intent intent) method from returning before you have your location, or use a standard Service and execute stopSelf when you obtain a Location object.
public class MyReceiver extends Service implements LocationListener {
private LocationManager locationManager;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
onHandleIntent(intent);
return START_NOT_STICKY;
}
protected void onHandleIntent(Intent intent) {
Log.i("DebugMe", "Intent Fired");
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
}
public void onLocationChanged(Location location) {
String lat = String.valueOf(location.getLatitude());
String lon = String.valueOf(location.getLongitude());
Log.i("DebugMe", lat + " " + lon);
locationManager.removeUpdates(this);
// this is where you stop the service
stopSelf();
}
public void onProviderDisabled(String provider) {
Log.d("DebugMe ", "Disabled");
}
public void onProviderEnabled(String provider) {
Log.d("DebugMe", "Enabled");
}
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d("DebugMe", "Status");
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Keep in mind that this implementation won't run in a separate thread as default, as an IntentService would.
Hie,
I tried this sample code that one of the person who gave me this in my other question in stack overflow. I tried using this code but when i run the applicationn, it doesnt locate my current device and it doesnt even display a dot of my location .. The code does not give me any red underline errors but i am unable to locate the current location i am at.
What did i miss out? is there anyone who has a sample working source code file that i can download from to get my current device location??
the codes i used is as followed,
This is my MainActivity.class
public class MainActivity extends Activity {
MapView mMapView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mMapView = (MapView) findViewById(R.id.mapview);
mMapView.addLayer(new ArcGISTiledMapServiceLayer(
"http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer"));
mMapView = new MapView(this);
LocationResult locationResult = new LocationResult(){
#Override
public void gotLocation(Location loc){
}
};
MyLocation mylocation = new MyLocation();
mylocation.getLocation(this, locationResult);
}
This is MyLocation.java
public class MyLocation {
Timer timer1;
LocationManager lm;
LocationResult locationResult;
boolean gps_enabled=false;
boolean network_enabled=false;
public boolean getLocation(Context context, LocationResult result)
{
//I use LocationResult callback class to pass location value from MyLocation to user code.
locationResult=result;
if(lm==null)
lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
//exceptions will be thrown if provider is not permitted.
try{gps_enabled=lm.isProviderEnabled(LocationManager.GPS_PROVIDER);}catch(Exception ex){}
try{network_enabled=lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);}catch(Exception ex){}
//don't start listeners if no provider is enabled
if(!gps_enabled && !network_enabled)
return false;
if(gps_enabled)
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
if(network_enabled)
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
timer1=new Timer();
timer1.schedule(new GetLastLocation(), 20000);
return true;
}
LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerNetwork);
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
LocationListener locationListenerNetwork = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerGps);
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
class GetLastLocation extends TimerTask {
#Override
public void run() {
lm.removeUpdates(locationListenerGps);
lm.removeUpdates(locationListenerNetwork);
Location net_loc=null, gps_loc=null;
if(gps_enabled)
gps_loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(network_enabled)
net_loc=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
//if there are both values use the latest one
if(gps_loc!=null && net_loc!=null){
if(gps_loc.getTime()>net_loc.getTime())
locationResult.gotLocation(gps_loc);
else
locationResult.gotLocation(net_loc);
return;
}
if(gps_loc!=null){
locationResult.gotLocation(gps_loc);
return;
}
if(net_loc!=null){
locationResult.gotLocation(net_loc);
return;
}
locationResult.gotLocation(null);
}
}
public static abstract class LocationResult{
public abstract void gotLocation(Location location);
}
}
You have to write the code for displaying a red dot in the gotLocation method which is currently empty. That is why you are not getting anything displayed on top of the map.
I am writting code for getting current location (latitude and longitude) of my phone. I display a toast whether Network Location service is provided by the phone or not. This toast doesn't show up ever. The other question is, for getting current location using Network_location, will the app use phone's gprs/internet or not?
I have created the instance of this class in the main activity and then get data using Latitude and Longitude variables of this class, in another class which extends broadcast reciever .
public class GpsClass extends Activity{
public static String Latitude="";
public static String Longitude="";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener listener = new LocationListener() { // anonymous class
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onLocationChanged(Location currentLocation) {
double lat= currentLocation.getLatitude();
Latitude = Double.toString(lat);
double longt= currentLocation.getLongitude();
Longitude = Double.toString(longt);
}
};
manager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
if(manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
{
Toast.makeText(getApplicationContext(), "Network enabled", 0).show();
}
else
Toast.makeText(getApplicationContext(), "Network not enabled", 0).show();
}
}
Is there anything I am doing wrong?
Regards
I think the problem is that you are passing 0 for duration i.e. last parameter of makeText() method.
Try passing Toast.LENGTH_SHORT or Toast.LENGTH_LONG.
if(manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
{
Toast.makeText(getApplicationContext(), "Network enabled", Toast.LENGTH_LONG).show();
}
else
Toast.makeText(getApplicationContext(), "Network not enabled", Toast.LENGTH_LONG).show();
This can help you to get answer to your first question.
The answer to your second question is - No, the app will not use phone's gprs/internet for getting location through network provider.
The problem is setting 0 for duration.
This is a sample example:
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
currentLocation = new GeoPoint(location.getLatitude(), location.getLongitude());
// Set Toast Here To Diplay location
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
//10000 means request update every 10 sec
//10 tell listener that if location change more than 10m then run locationChanged method
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 10, locationListener);
} else {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 10, locationListener);
}