Keep a specific activity alive while switching between Activities - android

My application contains 6 separated activities, one of them returns GPS coordination, this activity work perfectly when it's open but first I return to the main activity it stops updating location.
details :
I have created a GPS services and called it in the Manifest.xml
<service android:name=".Services.GPS_Service" />
This is the Service :
public class GPS_Service extends Service {
private LocationListener listener;
private LocationManager locationManager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#SuppressLint("MissingPermission")
#Override
public void onCreate() {
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Intent i = new Intent("location_update");
i.putExtra("Longitude", location.getLongitude());
i.putExtra("Latitude", location.getLatitude());
final Date date = new Date(location.getTime());
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
i.putExtra("time", sdf.format(date));
sendBroadcast(i);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
//noinspection MissingPermission
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, listener);
}
#SuppressLint("MissingPermission")
#Override
public void onDestroy() {
super.onDestroy();
if (locationManager != null) {
//noinspection MissingPermission
locationManager.removeUpdates(listener);
}
}
}

According to your answers and the phrasing you use: "when it's open but first I return to the main activity" - I am assuming by 'I return to the main activity' you mean that either onBackPressed is involved, or just a simple finish() was called. For that reason, onDestroy was called so your listener gets cancelled, and that why it stops working.

You cannot have two activities active at the same time. You must use Android Service to update location.

Related

Tracking location in the background

I want to implement location tracking in android but in a small time interval (seconds), after searching and reading the documentation i found that there is restrictions on location access when app is in the background, and the solution is to use foreground service, But i need another legal and efficient solution without the need to show notification to the user.
You could use something like that
public class GPSService extends Service {
private LocationListener listener;
private LocationManager locationManager;
public IBinder onBind(Intent intent){
return null;
}
#SuppressLint("MissingPermission")
#Override
public void onCreate() {
super.onCreate();
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Intent i = new Intent("location_update");
i.putExtra("coordinates",location);
sendBroadcast(i);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,5000,0,listener);
}
#Override
public void onDestroy() {
super.onDestroy();
if (locationManager != null){
locationManager.removeUpdates(listener);
}
}
}
And retreive by broadcaster

getting gps data from service in background

I tried to get gps data (speed) when I don't use the app i'm programming.
but always when I close the app it stops asking for gps updates. now I got told, that I have to use a service. so i did, but it still stops asking for updates everytime I close to ui of the app.
here is my code of the service:
package com.example.slartibartfast.kslordered;
public class BackroundService extends Service {
private static float speed;
//initializing the Location Manager and Listener
LocationManager locationManager;
LocationListener locationListener;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#SuppressLint("MissingPermission")
#Override
public void onCreate() {
//Instantiating the device manager an listener
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
//when the location changed
Log.d("Location", ""+location);
Log.d("Float Location", ""+ location.getLongitude() + " " + location.getLatitude());
Log.d("Speed", " "+location.getSpeed());
//initializing the variable speed with the speed number given by the LocationListener
speed = location.getSpeed();
//creating a broadcast reciever
Intent intent = new Intent("speed_update");
intent.putExtra("speed", speed);
//sending speed to main activity
sendBroadcast(intent);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
//if gps is disabled, this opens the gps settings
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
};
locationManager.requestLocationUpdates("gps", 5000, 0, locationListener);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
}
and here of my main activity:
package com.example.slartibartfast.kslordered;
public class MainActivity extends AppCompatActivity {
//initializing ui elements
TextView textviewSpeed;
Button button;
//initializing ui BroadcastReciever
private BroadcastReceiver broadcastReceiver;
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//instantiating the ui elements
textviewSpeed = (TextView)findViewById(R.id.textview_speed);
//checking if permission to use gps location is given
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 10);
return;
}else{
}
startService(new Intent(this, BackroundService.class));
}
#Override
protected void onResume() {
super.onResume();
//broadcast reciever gets speed from the backround service
if (broadcastReceiver == null){
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//speed get's set on the textview
textviewSpeed.setText(""+ intent.getExtras().get("speed"));
}
};
}
registerReceiver(broadcastReceiver, new IntentFilter("speed_update"));
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
//asks for the gps user permission
switch (requestCode){
case 10:
if (grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//(5000);
}
}
}
I think you need to add your code on OnStart instead of OnCreate
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
//when the location changed
Log.d("Location", ""+location);
Log.d("Float Location", ""+ location.getLongitude() + " " + location.getLatitude());
Log.d("Speed", " "+location.getSpeed());
//initializing the variable speed with the speed number given by the LocationListener
speed = location.getSpeed();
//creating a broadcast reciever
Intent intent = new Intent("speed_update");
intent.putExtra("speed", speed);
//sending speed to main activity
sendBroadcast(intent);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
//if gps is disabled, this opens the gps settings
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
};
locationManager.requestLocationUpdates("gps", 5000, 0, locationListener);
return START_STICKY;
}

GPS Service stops after push power button

I'm starting a GPS location service on several devices, the service works correctly in devices with Android Version <= 7 even when the power button is pressed and in the lockscreen status, but I tried in a Nokia 3 with Android 8.0.0 and the service stops after push the power button but it doesn't stop when the device locks by itself after some time. When I push the power button and unlock the device the service starts to send the GPS data again. This is my code:
public class GPS_Service extends Service {
private static final String TAG = GPS_Service.class.getName();
private static final int minTimeSecondsSamplingRate = AppConfig.GPS_MIN_TIME;
private static final int minDistMetersSamplingRate = AppConfig.GPS_MIN_DISTANCE;
private LocationManager locationManager;
private LocationListener locationListener;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#SuppressLint("MissingPermission")
#Override
public void onCreate() {
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Location changed");
Intent intentSendToMainActivity = new Intent(AppConfig.C_STR_INTENT_FILTER_LOCATION_CHANGED);
intentSendToMainActivity.putExtra(AppConfig.C_STR_LATITUDE, location.getLatitude());
intentSendToMainActivity.putExtra(AppConfig.C_STR_LONGITUDE, location.getLongitude());
sendBroadcast(intentSendToMainActivity);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
if (locationManager != null) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minTimeSecondsSamplingRate, minDistMetersSamplingRate, locationListener);
Log.i(TAG, "Starting Location Service");
} else {
Log.e(TAG, "Can't Start Location Service");
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (locationManager != null) {
locationManager.removeUpdates(locationListener);
}
}
}
I've tried dissabling the battery optimization for my application but the problem persists
stop/start location update if no location is received in 2 minutes
also create a service an make it foreground and put location updates methods inside it
all the best

How to separate location listener and Google map

I am trying to make a location tracking application on an android phone, it will be just same as the built-in google map in the phone. It will continue to track the phone even the app is close, so it will be running in the background of other applications.
I am thinking of splitting up both the classes, User Interface (Google Map) and location tracking, where the location tracking will always run but the google map will only display when the user open the application. Thus this is what I reached so far.
MapDisplay class for Google Map
public class MapDisplay extends Activity {
private GoogleMap map;
private LocationService locationService;
private Intent locationServiceIntent;
private Location myLocation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_display);
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.googleMap)).getMap();
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
map.setMyLocationEnabled(true);
locationServiceIntent = new Intent(this, LocationService.class);
x=0;
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
startService(locationServiceIntent);
bindService(locationServiceIntent, locationServiceConnection, Context.BIND_AUTO_CREATE);
}
#Override
public void updateLocation()
{
// for testing purpose, to make sure it will update periodically
Toast.makeText(MapDisplay.this, String.valueOf(myLocation.getLatitude()), Toast.LENGTH_SHORT).show();
}
private ServiceConnection locationServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
locationService = ((LocationService.LocationBinder)service).getService();
myLocation = locationService.getMyLocation();
updateLocation();
}
#Override
public void onServiceDisconnected(ComponentName name) {
locationService = null;
}
};
}
LocationService class
public class LocationService extends Service implements LocationListener
{
private LocationManager locationManager;
private Location myLocation;
private IBinder locationBinder = new LocationBinder();
public class LocationBinder extends Binder
{
public LocationService getService()
{
return LocationService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return locationBinder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
myLocation = null;
boolean networkProviderAvailable = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
boolean gpsProviderAvailable = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if(networkProviderAvailable)
{
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
}
else if(gpsProviderAvailable)
{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
else
{
stopSelf();
}
return super.onStartCommand(intent, flags, startId);
}
public Location getMyLocation()
{
return myLocation;
}
#Override
public void onLocationChanged(Location location) {
myLocation = location;
}
#Override
public void onProviderDisabled(String arg0) {
}
#Override
public void onProviderEnabled(String arg0) {
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
}
Using code above I experienced application crash because of this line
myLocation = locationService.getMyLocation();
String.valueOf(myLocation.getLatitude())
It can't get the location from LocationService class.
So, my questions are:
1) is this a good way to make the application?
2) how to periodically call the updateLocation() in MapDisplay when there are new updates in onLocationChanged method?
I will be much appreciate if someone can help me on this.
You have to account for the case that you have not yet received a location. To do that, your client code needs to check the return of getLocation for null, and handle accordingly.
Additionally you may want some more intelligence in onLocationChanged. Right now if a gps location comes in and then a network location comes in, the network location will overwrite the gps location, despite being less accurate. I'd take a look at some code I wrote at http://gabesechansoftware.com/location-tracking/ You'll see a class FallbackLocationTracker which will track both gps and network location, returning the most accurate location received so far. I think it does what you're trying to do.

Toggle Service via ToggleButton for GPS Tracker

i'm currently writing an app that should to the following:
The UI only contains one toggle button. If it is turned on the GPS Position shall be sent to an external server. If it is turned off, nothing shall happen.
If the Button was turned on and the app (activity) is closed the location should still be send until the Button is turned off again.
How can i achieve this ? I read a lot of threads and tutorials and on dev.google.com, but i was not able to find the best solution for my problem.
My current approach:
MainActivity.java
public void onClick(View v) {
if (onOffButton.isChecked()) {
Intent startIntent = new Intent(this, LocationService.class);
startService(startIntent);
} else {
stopService(new Intent(this, LocationService.class));
}
}
LocationService.java
public class LocationService extends Service implements LocationListener {
final public static String START_ACTION = "START_LOCATION";
final public static int NOTE_ID = 1;
private int updateRate;
private LocationManager locationManager;
private NotificationManager notifyManager;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
// show popup message
Toast.makeText(this, getText(R.string.start_message), Toast.LENGTH_SHORT).show();
// display icon in status bar
requestLocationUpdates();
}
private void requestLocationUpdates() {
if(locationManager != null)
locationManager.removeUpdates(this);
// get location service
Criteria crit = new Criteria();
crit.setPowerRequirement(Criteria.ACCURACY_FINE);
String bestProvider = getLocationManager().getBestProvider(crit, true);
getLocationManager().requestLocationUpdates(bestProvider, updateRate * 1000,
0 /* minDist */, this);
LocationService.running = true;
}
#Override
public void onDestroy() {
super.onDestroy();
getLocationManager().removeUpdates(this);
notifyManager.cancel(NOTE_ID);
Toast.makeText(this, getText(R.string.stop_message), Toast.LENGTH_SHORT).show();
LocationService.running = false;
}
#Override
public void onLocationChanged(Location location) {
//Send Location to Server
}
#Override
public void onProviderDisabled(String provider) {
// TODO stop service, notify user
}
#Override
public void onProviderEnabled(String provider) {
requestLocationUpdates();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO notify user
}
private LocationManager getLocationManager() {
if (this.locationManager == null)
this.locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
return this.locationManager;
}
}
I got this from a very old gps tracker i found on the Internet (i know that onStart() is deprecated and should replaced with onCommandStart()) I just want to know if the general approach is good..
Regards.
The approach looks fine. You just need to implement the call-back methods to report your location.

Categories

Resources