I want to get the current location and add a proximity alert to that location. When ever I exit or enter a radius around the current location. As I am getting the current location's latitude and longitude and adding the proximity alert, I get an alert as soon as I register. But I am not getting when I exit even if i am on the foreground. I have registered my reciever in the manifest.
This is my Activity.
public class GeoFencer extends FragmentActivity implements LocationListener {
private LocationManager locMan, locManForProximitySensor;
private Intent i;
private PendingIntent pService;
Context context;
#Override
protected void onCreate(Bundle arg0) {
setContentView(R.layout.geo_fencer_layout);
super.onCreate(arg0);
context = this;
locMan = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locManForProximitySensor = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
i = new Intent("com.packagename.proximity");
pService = PendingIntent.getBroadcast(this, 0 , i, 0);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
MenuInflater inflater= getMenuInflater();
inflater.inflate(R.menu.geofencemenu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.action_geo){
if(locMan.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
locMan.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
}
else if(locMan.isProviderEnabled(LocationManager.GPS_PROVIDER)){
locMan.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
else
Toast.makeText(this, "GPS is disabled. Please Enable.", Toast.LENGTH_LONG).show();
}
return super.onOptionsItemSelected(item);
}
#Override
public void onLocationChanged(Location location) {
locManForProximitySensor.addProximityAlert(location.getLatitude(), location.getLongitude(), 10, -1 , pService) ;
Log.d(getClass().getSimpleName(),"Proximity alert added (" + location.getLatitude() + ", "+ location.getLongitude() + ")");
locMan.removeUpdates(this);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
}
My Reciever
public class ProximityAlertReceiver extends BroadcastReceiver{
private static final int NOTIFICATION_ID = 1000;
#Override
public void onReceive(Context context, Intent intent) {
String key = LocationManager.KEY_PROXIMITY_ENTERING;
String message = " ";
Boolean entering = intent.getBooleanExtra(key, false);
if (entering) {
Log.d(getClass().getSimpleName(), "entering");
message = "You are entering your point";
}
else {
Log.d(getClass().getSimpleName(), "exiting");
message = "You are exiting your point";
}
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.app_icon)
.setContentTitle("CompanyName")
.setContentText(message);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
Please tell me what I am doing wrong here. Thanks in Adavance.
you should add one of this flags: PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_UPDATE_CURRENT .
Related
I have a location service which sends location to my server after every 3 minutes.This location service is started from Activity by click of a button.I want this service stops automatically after 6 hours from started time.Here is my service file.Service is starting normally and i am able to stop it by click of a button in activity.But i want to stop it automatically after 6 hours even app is minimized.Any help would be highly appreciated.
public class LocationService extends Service {
private LocationListener listener;
private LocationManager locationManager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.i("location:","location is "+location.getLongitude()+" "+location.getLatitude());
LocationApi.sendGpsLocation(getApplicationContext(),location.getLongitude(),location.getLatitude());
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String provider) {
Log.e("disabled provider is :","location is "+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);
if (ContextCompat.checkSelfPermission(DashboardActivity.activity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ) {
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,3000,0,listener);
}
}
/* #Override
public final void stopSelf(){
}*/
#Override
public boolean onUnbind(Intent intent) {
LocationApi.stopLocation(getApplicationContext());
//super.onDestroy();
if (locationManager != null) {
//noinspection MissingPermission
locationManager.removeUpdates(listener);
}
return super.onUnbind(intent);
}
#Override
public void onDestroy() {
LocationApi.stopLocation(getApplicationContext());
super.onDestroy();
if(locationManager != null){
//noinspection MissingPermission
locationManager.removeUpdates(listener);
}
}
}
and i start this service in Activity by below code.
Intent i = new Intent(getApplicationContext(), LocationService.class);
if (Build.VERSION.SDK_INT >= 26) {
startForegroundService(i);
}else{
startService(i);
}
You can add a counter to your 3 min timer and count up til you reach 120 and than stop Locationupdates and shutdown the service.
You could schedule an alarm via AlarmManager when the service gets started - this will be an Intent you receive. When receiving you can stop your running service.
Try this code:
public class LocationService extends Service {
public static final String ACTION_STOP = "com.mycompany.myapp.SERVICE_STOP";
/*private static final long UPDATE_INTERVAL = 3 * 60 * 1000;
private static final long STOP_INTERVAL = 6 * 3600 * 1000;*/
private static final long UPDATE_INTERVAL = 3 * 1000;
private static final long STOP_INTERVAL = 20 * 1000;
private LocationListener listener;
private LocationManager locationManager;
private BroadcastReceiver receiver;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent i, int flags, int startId){
if (Build.VERSION.SDK_INT >= 26){
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel("Location",
"Location", NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
Notification notif = new NotificationCompat.Builder(this, "Location")
.setContentTitle("Location service")
.build();
startForeground(3001, notif);
}
return START_STICKY;
}
#Override
public void onCreate() {
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.i("location:","location is "+location.getLongitude()+" "+location.getLatitude());
LocationApi.sendGpsLocation(getApplicationContext(),location.getLongitude(),location.getLatitude());
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String provider) {
Log.e("disabled provider is :","location is "+provider);
Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
};
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ) {
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,UPDATE_INTERVAL,0,listener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,UPDATE_INTERVAL,0f,listener);
}
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent i = new Intent(ACTION_STOP);
PendingIntent pi = PendingIntent.getBroadcast(this, 100, i, PendingIntent.FLAG_UPDATE_CURRENT);
am.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + STOP_INTERVAL, pi);
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
stopSelf();
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_STOP);
registerReceiver(receiver, filter);
}
#Override
public void onDestroy() {
Log.i("location:","stopping updates");
unregisterReceiver(receiver);
LocationApi.stopLocation(getApplicationContext());
super.onDestroy();
if(locationManager != null){
locationManager.removeUpdates(listener);
}
}
}
Explanation: use AlarmManager.set() to schedule a broadcast after certain time (STOP_INTERVAL). To receive the broadcast, register a receiver in onCreate(), and unregister it in onDestroy().
I am starting my background service from the MainActivity with startService(intent) which sends the location of the user to the server. I want to enable the user to stops this service (also stoping requestLocationUpdates of firing the data from the onLocationChanged method) if he does not wish it by clicking button in the Menu.
I have tried the code in the onOptionsItemSelected method but the service it still works when I click button.
How can I stop this service?
MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.route_available);
Intent i = new Intent(this, TrackingService.class);
startService(i);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.disconnect_id:
System.out.println("test onCreateOptionsMenu was invoked.");
// Stop the service when the Menu button clicks.
Intent i = new Intent(this, TrackingService.class);
stopService(i);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Tracking Service class:
public class TrackingService extends Service {
....
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Toast.makeText(this, "Location Updation has started", Toast.LENGTH_LONG)
.show();
Log.v("X", "Response:in onStartCommand()");
detectLocation();
stopSelf();
return START_STICKY;
}
private void detectLocation() {
// TODO Auto-generated method stub
Toast.makeText(this, "Inside detectlocation()", Toast.LENGTH_SHORT)
.show();
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener ll = new MyLocationListener(this);
// location updates: at least 0 meter and 60 seconds change.
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30 * 1000, 0,
ll);
Log.v("X", "Response:After lm1.requestLocationUpdates ");
enableGPS(lm);
}
}
It looks like the way you have it coded now, your Service isn't really doing anything.
Because you have registered your MyLocationListener instance as the LocationListener, stopping the Service doesn't do anything.
Also, since you call stopSelf() in onStartCommand(), you're stopping the Service immediately every time it starts.
I would recommend making the Service the LocationListener, and don't call stopSelf() in onStartCommand()
.
Also, override onDestroy() in the Service, and explicitly call removeUpdates() in order to ensure your app releases it's request to keep the GPS radio active.
Something like this:
public class TrackingService extends Service implements LocationListener{
LocationManager lm; //make instance variable
//....
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Toast.makeText(this, "Location Updation has started", Toast.LENGTH_LONG)
.show();
Log.v("X", "Response:in onStartCommand()");
detectLocation();
//stopSelf(); //don't stop the service here
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
lm.removeUpdates(this);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void detectLocation() {
// TODO Auto-generated method stub
Toast.makeText(this, "Inside detectlocation()", Toast.LENGTH_SHORT)
.show();
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
//LocationListener ll = new MyLocationListener(this);
// location updates: at least 0 meter and 60 seconds change.
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30 * 1000, 0,
this);
Log.v("X", "Response:After lm1.requestLocationUpdates ");
enableGPS(lm);
}
#Override
public void onLocationChanged(Location location) {
//put your location changed code here
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
i want a background service class that which will get the user current location sends as a notification to the user if the user changes its location then the updated location will sends back to the user as a notification..even if the user close the application then also will receive the notification (the service will trace the location in background even application closed)
currently i am using this service for tracing the location which works if the application in foreground
can u pls. help me to get out of this i am struggling for 4 hours
in your activity unlike the one that you are using make your buttons start and stop the service and it will run in the background unless the user reopens the app and stops it
Intent i = new Intent(MainActivity.this,gpsservice.class);
startService(new Intent(i));
or to stop
Intent j = new Intent(MainActivity.this,gpsservice.class);
stopService(new Intent(j));
use this service
public class gpsservice extends Service{
private LocationManager locationManager;
MyLocationListener locationListenerp;
public gpsservice() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
locationManager = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
locationListenerp = new MyLocationListener();
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 5000, 10, locationListenerp);
}
#Override
public void onDestroy() {
locationManager.removeUpdates(locationListenerp);
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "location Service Started", Toast.LENGTH_LONG).show();
}
public class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
Toast.makeText(getApplicationContext(), "I was here", Toast.LENGTH_LONG).show();
}
#Override
public void onProviderDisabled(String s) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
}
}
I found hundreds of topics related to the same problem, but I cannot understand where I get wrong! Because I have written the same code basically...
This is a service which controls the position and adds a promityAlert
public class GeoReminderService extends Service implements LocationListener{
private LocationManager locationManager;
private final String proximityIntentAction = "com.example.geo.ProximityIntentReceiver";
private float latitude;
private float longitude;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 400, 10, this);
addProximityAlert(45.477872,9.23457);
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onLocationChanged(Location location) {
Log.v("Service","Location changed");
if (location != null) {
Log.v("Location changed : Lat: ", ""+location.getLatitude());
Log.v("Location changed : Lon: ", ""+location.getLongitude());
}
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#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
}
private void addProximityAlert(double latitude, double longitude) {
Log.v("Service","proximity alert added" + latitude +" "+ longitude);
Intent intent = new Intent(proximityIntentAction);
PendingIntent proximityIntent = PendingIntent.getBroadcast(getApplicationContext(), -1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
locationManager.addProximityAlert(latitude, longitude, 3000, -1, proximityIntent);
IntentFilter filter = new IntentFilter(proximityIntentAction);
registerReceiver(new ProximityIntentReceiver(), filter);
}
Instead this one is the receiver which should captures the event
public class ProximityIntentReceiver extends BroadcastReceiver {
private static final int NOTIFICATION_ID = 1000;
#Override
public void onReceive(Context context, Intent intent) {
Log.v("proximity receiver", "alert received");
String key = LocationManager.KEY_PROXIMITY_ENTERING;
Boolean entering = intent.getBooleanExtra(key, false);
if (entering) {
Log.v("ProximityIntentReceiver", "entering");
}
else {
Log.v("ProximityIntentReceiver", "exiting");
}
}
Even if I change the position (I am using the Android emulator) the event onReceive doesn't fire. At the same time I am sure that I am changing the position correctly , since the event locationChanged works. Can anyone help me, please?
Have you declared ProximityIntentReceiver in the manifest?
In the same area of the manifest where you declare activites, etc., you'd also declare your BroadcastReceiver.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.geo"
android:versionCode="001"
android:versionName="0.1"
>
<application>
...
<receiver android:name=".ProximityIntentReceiver">
</receiver>
</application>
</manifest>
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.