GeofenceIntentService not getting triggered on geofence enter - android

I'm trying to create geofences without google maps (just service that triggers PendingIntent when user is in geofence area). The problem is that I'm not able to get response when user enters geofence location. Here is my code from service class:
public class GeofenceBackgroundService extends Service implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener,
ResultCallback<Status> {
private GoogleApiClient googleApiClient;
private GeofencingClient mGeofencingClient;
private LocationRequest locationRequest;
private PendingIntent geoFencePendingIntent;
private final int GEOFENCE_REQ_CODE = 0;
private static final String GEOFENCE_REQ_ID = "My Geofence";
private static final float GEOFENCE_RADIUS = 500.0f;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
/*mGeofencingClient = LocationServices.getGeofencingClient(this);*/
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
googleApiClient.connect();
locationRequest = LocationRequest.create()
.setInterval(10000)
.setFastestInterval(5000)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
return START_STICKY;
}
#Override
public void onConnected(Bundle dataBundle) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
Geofence geofence = createGeofence();
GeofencingRequest geofenceRequest = createGeofenceRequest(geofence);
addGeofence(geofenceRequest);
}
#Override
public void onConnectionSuspended(int i) {
googleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
if (location != null) {
Log.e("TAG", "Location changed " + location.getLatitude() +" " + location.getLongitude());
}
}
private Geofence createGeofence() {
return new Geofence.Builder()
.setRequestId(GEOFENCE_REQ_ID)
.setCircularRegion(35.3140045, 103.4839695, GEOFENCE_RADIUS)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setNotificationResponsiveness(1000)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
.build();
}
private GeofencingRequest createGeofenceRequest(Geofence geofence) {
return new GeofencingRequest.Builder()
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
.addGeofence(geofence)
.build();
}
private PendingIntent createGeofencePendingIntent() {
if (geoFencePendingIntent != null)
return geoFencePendingIntent;
/*Intent intent = new Intent("com.receive.ACTION_RECEIVE_GEOFENCE");
PendingIntent geoFencePendingIntent = PendingIntent.getBroadcast( getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return geoFencePendingIntent;*/
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
return PendingIntent.getService(this, GEOFENCE_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
private void addGeofence(GeofencingRequest request) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.GeofencingApi.addGeofences(googleApiClient, request, createGeofencePendingIntent()).setResultCallback(this);
}
#Override
public void onResult(#NonNull Status status) {
if ( status.isSuccess() ) {
} else {
}
}
#Override
public void onDestroy() {
super.onDestroy();
googleApiClient.disconnect();
}}
Also I tried to use both IntentService and Broadcast receiver and declared them properly in android manifest file

Related

Can not get accurate location while travelling in bus without internet

I am developing offline car tracker android application. It will update location after 5 min and stores it in SQLite.I used FusedLocationAPI but can not get accurate location while travelling in bus without Internet. I am getting accuracy 999m and getting same location after every 5 minutes.
I set alarm manager to 5 minutes.
public static void startAlarmManager(Context context)
{
preferences =context.getSharedPreferences(Constant.SHARED_PREF_NAME, Context.MODE_PRIVATE);
int duration= Integer.parseInt(preferences.getString(Constant.DURATION_SHARED_PREF,Constant.CONSTANT_DURATION_SHARED_PREF));
Log.d("duration",duration+"");
alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
gpsTrackerIntent = new Intent(context, GpsTrackerAlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(context, 0, gpsTrackerIntent, 0);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
5*60000,
pendingIntent);
}
It will fire broadcast receiver.
public class GpsTrackerAlarmReceiver extends WakefulBroadcastReceiver {
private static final String TAG = "GpsTrackerAlarmReceiver";
#Override
public void onReceive(Context context, Intent intent) {
LocationManager manager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE );
boolean statusOfGPS = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if(statusOfGPS) {
context.startService(new Intent(context, LocationService.class));
}
}
}
This is location service. I am getting location with this way.
public class LocationService extends Service implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private static final String TAG = "LocationService";
public static GoogleApiClient googleApiClient;
private LocationRequest locationRequest;
public Context context;
private DatabaseHelper db;
private boolean currentlyProcessingLocation = false;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
if (!currentlyProcessingLocation) {
currentlyProcessingLocation = true;
startTracking();
}
return START_NOT_STICKY;
}
private void startTracking() {
if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
if (!googleApiClient.isConnected() || !googleApiClient.isConnecting()) {
googleApiClient.connect();
}
} else {
Log.e(TAG, "unable to connect to google play services.");
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.d(TAG, "onConnected");
locationRequest = LocationRequest.create();
locationRequest.setInterval(1000); // milliseconds
locationRequest.setFastestInterval(1000); // the fastest rate in milliseconds at which your app can handle location updates
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(
googleApiClient, locationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
Log.e(TAG, "GoogleApiClient connection has been suspend");
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged");
startupdate(location);
}
private void startupdate(Location location) {
if (location != null) {
db=new DatabaseHelper(this);
db.insertLocation(location.getLatitude(), location.getLongitude(), "FusedApi Provider", location.getAccuracy());
stopLocationUpdates();
stopSelf();
}
}
public void stopLocationUpdates() {
if (googleApiClient != null && googleApiClient.isConnected()) {
googleApiClient.disconnect();
}
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.e(TAG, "onConnectionFailed");
stopLocationUpdates();
stopSelf();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Please help...if i am wrong. Thanks in advance.
When GPS is not practical you can use LocationManager.NETWORK_PROVIDER, this is location from the phone carrier that is less accurate than GPS but is available everywhere the carrier has a tower. The way I do it is a set a flag isGpsAvailable() to see if that is true I use GPS otherwise I use network provided location. This Google's doc provides detailed solutions including code snippets that you can use and change the way you it fits your needs.

Re- JobScheduler combined with FusedLocationProvider Api oftens gives null location value

I have a jobScheduler with fusedLocationApi provider. It works alright but once a while it gives null value for a no. of time (6-7 times in a sequence). I tried onLocationChanged() and LocationServices.FusedLocationApi.requestLocationUpdates(), both gives null values at same time. How can I improve it? I have set high accuracy or Gps,wifi and mobile networks as locating method in device setting. thanks in advance.
One more thing, 80% of the null value are received when there is no wifi. I think Fused Api should have worked well without wifi as well Since there is gps available, isn't it?
Main class
public class LiveTrack extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live_track);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
jobScheduler = (JobScheduler)getSystemService(JOB_SCHEDULER_SERVICE);
ComponentName jobService =
new ComponentName(getPackageName(), MyJobService.class.getName());
JobInfo jobInfo =
new JobInfo.Builder(MYJOBID, jobService).setPeriodic(15 * 60 * 1000L)
.setExtras(bundle)
.build();
int jobId = jobScheduler.schedule(jobInfo);
if(jobScheduler.schedule(jobInfo)>0){
Log.e("status","running");
}else{
Log.e("status","failed");
}
}
}
JobService class with fused Api Provider
public class MyJobService extends JobService
implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener
, LocationListener {
private GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
private Location mLastLocation;
public static String latitude;
public static String latitudeIfNull;
public static String longitude;
public static String longitudeIfNull;
#Override
public boolean onStartJob(JobParameters jobParameters) {
setUpLocationClientIfNeeded();
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(30000);
mLocationRequest.setFastestInterval(30000);
return false;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
Toast.makeText(this,
"App has stopped working. Please open the app again. Thankyou",
Toast.LENGTH_LONG).show();
return false;
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(this.mGoogleApiClient,mLocationRequest, this);
createLocationRequest();
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
private void setUpLocationClientIfNeeded()
{
if(mGoogleApiClient == null)
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
this.mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
this.mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
latitudeIfNull = location.getLatitude() + "";
longitudeIfNull = location.getLongitude() + "";
Log.e("gps longitude",longitudeIfNull);
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(60000);
mLocationRequest.setFastestInterval(50000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationCallback() {
#Override
public void onLocationResult(final LocationResult locationResult) {
latitude = locationResult.getLastLocation().getLatitude() + "";
longitude = locationResult.getLastLocation().getLongitude() + "";
Log.i("latitude ", latitude + "");
Log.i("longitude ", longitude + "");
}
#Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
Log.i("onLocationAvailability", "onLocationAvailability: isLocationAvailable = " + locationAvailability.isLocationAvailable());
}
}, null);
}
}
.
Try this
Create a background service class like this
public class LocationBackGroundService extends Service implements LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "LocationBackGroundService";
private static final long INTERVAL = 100;
private static final long FASTEST_INTERVAL = 100;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mCurrentLocation;
Context mCOntext;
public void LocationBackGroundService(Context mContext) {
this.mCOntext = mContext;
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
mGoogleApiClient.connect();
}
#Override
public void onCreate() {
super.onCreate();
if (!isGooglePlayServicesAvailable()) {
// finish();
}
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
}
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
return false;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
protected void startLocationUpdates() {
PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Log.d(TAG, "Location update started ..............: ");
}
#Override
public void onConnectionSuspended(int i) {
Toast.makeText(this, "OnConnection Suspended", Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(this, "OnConnection Failed", Toast.LENGTH_SHORT).show();
}
#Override
public void onLocationChanged(Location location) {
if (null != mCurrentLocation) {
mCurrentLocation = location;
String lat = String.valueOf(mCurrentLocation.getLatitude());
String lng = String.valueOf(mCurrentLocation.getLongitude());
}
}
}
And call when activity starts like this
startService(new Intent(this, yourBackgroundServiceName.class));
and in menifest
<service android:name=".yourBackgroundServiceName"></service>
and don;t forget to add run time permissions before stating a service

Geofences do not trigger my Service

I have read various tutorials, forums and the official Google documentation and still cannot understand why my code does not work as expected. There are the relevant parts:
Activity
public class MainMap extends FragmentActivity implements OnMarkerClickListener, OnMapReadyCallback,
ConnectionCallbacks, OnConnectionFailedListener, LocationListener, ActivityCompat.OnRequestPermissionsResultCallback, ResultCallback<Status> {
private static final int REQUEST_ACCESS_FINE_LOCATION = 0;
protected GoogleApiClient mGoogleApiClient;
protected Location mCurrentLocation;
protected LocationRequest mLocationRequest;
private GoogleMap m_map;
private SupportMapFragment m_map_fragment;
protected ArrayList<Geofence> mGeofenceList;
private PendingIntent mGeofencePendingIntent;
private boolean m_geofences_added;
private SharedPreferences m_preferences;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_map);
m_preferences = this.getSharedPreferences("com.example",Context.MODE_PRIVATE);
// map fragment
m_map_fragment= (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
m_map_fragment.getMapAsync(this);
}
#Override
protected void onStart() {
super.onStart();
// location and geofences
add_location_and_geofences();
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
// remove geofences
LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient, getGeofencePendingIntent());
super.onStop();
mGoogleApiClient.disconnect();
}
#Override
public void onConnected(Bundle connectionHint) {
// permissions
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
request_fine_location_permission();
}
// location
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
// geofencing
try {
LocationServices.GeofencingApi.addGeofences(
mGoogleApiClient,
getGeofencingRequest(),
getGeofencePendingIntent()
).setResultCallback(this);
} catch (SecurityException securityException) {
Log.e(TAG, "Invalid location permission. " +
"You need to use ACCESS_FINE_LOCATION with geofences", securityException);
}
}
public void onResult(Status status) {
if (status.isSuccess()) {
} else {
String errorMessage = GeofenceErrorMessages.getErrorString(this,
status.getStatusCode());
Log.e(TAG, errorMessage);
}
}
private void add_location_and_geofences() {
for (int i =0; i < 3; i++) {
mGeofencePendingIntent = null;
mGeofenceList = new ArrayList<>();
mGeofenceList.add(new Geofence.Builder()
.setRequestId(Integer.toString(i)) // request id is the index so that I can later retrieve it
.setCircularRegion( /* I set coordinates here and a radius of 10meters*/)
.setExpirationDuration(NEVER_EXPIRE)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_DWELL)
.setLoiteringDelay(4000)
.build());
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(500);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
}
private PendingIntent getGeofencePendingIntent() {
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_DWELL);
builder.addGeofences(mGeofenceList);
return builder.build();
}
}
my Service:
public class GeofenceTransitionsIntentService extends IntentService {
private Intent m_intent;
#Override
public void onCreate() {
super.onCreate();
m_intent = new Intent(this, Guide.class);
}
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = GeofenceErrorMessages.getErrorString(this,
geofencingEvent.getErrorCode());
Log.e(TAG, errorMessage);
} else {
if (debug_mode) {
Log.i(TAG, "something has been received");
}
int geofenceTransition = geofencingEvent.getGeofenceTransition();
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL) {
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
for (Geofence geofence : triggeringGeofences) {
Log.i(TAG, "INSIDE GEOFENCE");
}
} else {
Log.e(TAG, getString(R.string.geofence_transition_invalid_type, geofenceTransition));
}
}
}
}
and my manifest
<service android:name="com.example.GeofenceTransitionsIntentService" />
With this code geofencing silently fails - my service is never triggered, both using wifi indoors and using 3G/4G networks outdoors.
Are you looking only for dwell events, or enter and exit events? If the latter, set your initial trigger to INITIAL_TRIGGER_ENTER, and the transition types to GEOFENCE_TRANSITION_ENTER| GEOFENCE_TRANSITION_EXIT.
If you are looking for dwell events, you need to stay within the geofence for about 5 minutes to get the initial trigger. When you leave, you won't get any event about it, but once you re-enter it, you'll need to stay within your geofence again for another 5 minutes to get your event.

Geofencing not triggered when user exit that fence?(P.S.when it is already on same area it triggered)

So Far :-
When user in same(under fence area) it gives notification "user enters in area" is ok.But same user leave fence area its not notified.
This is my code:-
public class MainActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener,
LocationListener, OnMapReadyCallback, GoogleMap.OnMapClickListener, GoogleMap.OnMarkerClickListener,
ResultCallback<Status>
{
private static final String TAG = MainActivity.class.getSimpleName();
private GoogleMap map;
private GoogleApiClient googleApiClient;
private Location lastLocation;
private TextView textLat, textLong;
private MapFragment mapFragment;
private static final String NOTIFICATION_MSG = "NOTIFICATION MSG";
// Create a Intent send by the notification
public static Intent makeNotificationIntent(Context context, String msg) {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(NOTIFICATION_MSG, msg);
return intent;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textLat = (TextView) findViewById(R.id.lat);
textLong = (TextView) findViewById(R.id.lon);
// initialize GoogleMaps
initGMaps();
// create GoogleApiClient
createGoogleApi();
}
// Create GoogleApiClient instance
private void createGoogleApi() {
Log.d(TAG, "createGoogleApi()");
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}
#Override
protected void onStart() {
super.onStart();
// Call GoogleApiClient connection when starting the Activity
googleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
// Disconnect GoogleApiClient when stopping Activity
googleApiClient.disconnect();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.geofence: {
startGeofence();
return true;
}
case R.id.clear: {
clearGeofence();
return true;
}
}
return super.onOptionsItemSelected(item);
}
private final int REQ_PERMISSION = 999;
// Check for permission to access Location
private boolean checkPermission() {
Log.d(TAG, "checkPermission()");
// Ask for permission if it wasn't granted yet
return (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED);
}
// Asks for permission
private void askPermission() {
Log.d(TAG, "askPermission()");
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQ_PERMISSION
);
}
// Verify user's response of the permission requested
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
Log.d(TAG, "onRequestPermissionsResult()");
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQ_PERMISSION: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted
getLastKnownLocation();
} else {
// Permission denied
permissionsDenied();
}
break;
}
}
}
// App cannot work without the permissions
private void permissionsDenied() {
Log.w(TAG, "permissionsDenied()");
// TODO close app and warn user
}
// Initialize GoogleMaps
private void initGMaps() {
mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
// Callback called when Map is ready
#Override
public void onMapReady(GoogleMap googleMap) {
Log.d(TAG, "onMapReady()");
map = googleMap;
map.setOnMapClickListener(this);
map.setOnMarkerClickListener(this);
}
#Override
public void onMapClick(LatLng latLng) {
Log.d(TAG, "onMapClick(" + latLng + ")");
//markerForGeofence(latLng);
}
#Override
public boolean onMarkerClick(Marker marker) {
Log.d(TAG, "onMarkerClickListener: " + marker.getPosition());
return false;
}
private LocationRequest locationRequest;
// Defined in mili seconds.
// This number in extremely low, and should be used only for debug
private final int UPDATE_INTERVAL = 1000;
private final int FASTEST_INTERVAL = 900;
// Start location Updates
private void startLocationUpdates() {
Log.i(TAG, "startLocationUpdates()");
locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL)
.setFastestInterval(FASTEST_INTERVAL);
if (checkPermission())
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged [" + location + "]");
lastLocation = location;
writeActualLocation(location);
}
// GoogleApiClient.ConnectionCallbacks connected
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.i(TAG, "onConnected()");
getLastKnownLocation();
recoverGeofenceMarker();
startGeofence();
}
// GoogleApiClient.ConnectionCallbacks suspended
#Override
public void onConnectionSuspended(int i) {
Log.w(TAG, "onConnectionSuspended()");
}
// GoogleApiClient.OnConnectionFailedListener fail
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.w(TAG, "onConnectionFailed()");
}
// Get last known location
private void getLastKnownLocation() {
Log.d(TAG, "getLastKnownLocation()");
if (checkPermission()) {
lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (lastLocation != null) {
Log.i(TAG, "LasKnown location. " +
"Long: " + lastLocation.getLongitude() +
" | Lat: " + lastLocation.getLatitude());
writeLastLocation();
startLocationUpdates();
} else {
Log.w(TAG, "No location retrieved yet");
startLocationUpdates();
}
} else askPermission();
}
private void writeActualLocation(Location location) {
textLat.setText("Lat: " + location.getLatitude());
textLong.setText("Long: " + location.getLongitude());
markerLocation(new LatLng(location.getLatitude(), location.getLongitude()));
}
private void writeLastLocation() {
writeActualLocation(lastLocation);
}
private Marker locationMarker;
private void markerLocation(LatLng latLng) {
Log.i(TAG, "markerLocation(" + latLng + ")");
String title = latLng.latitude + ", " + latLng.longitude;
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.title(title);
if (map != null) {
if (locationMarker != null)
locationMarker.remove();
locationMarker = map.addMarker(markerOptions);
float zoom = 14f;
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, zoom);
map.animateCamera(cameraUpdate);
}
}
// Start Geofence creation process
private void startGeofence() {
Log.i(TAG, "startGeofence()");
Geofence geofence = createGeofence();
GeofencingRequest geofenceRequest = createGeofenceRequest(geofence);
addGeofence(geofenceRequest);
}
private static final long GEO_DURATION = 60 * 60 * 1000;
private static final String GEOFENCE_REQ_ID = "My Geofence";
private static final float GEOFENCE_RADIUS = 200.0f; // in meters
// Create a Geofence
private Geofence createGeofence() {
Log.d(TAG, "createGeofence");
return new Geofence.Builder()
.setRequestId(GEOFENCE_REQ_ID)
.setCircularRegion(18.478122, 73.890158, GEOFENCE_RADIUS)
.setExpirationDuration(GEO_DURATION)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_EXIT)
.build();
}
// Create a Geofence Request
private GeofencingRequest createGeofenceRequest(Geofence geofence) {
Log.d(TAG, "createGeofenceRequest");
return new GeofencingRequest.Builder()
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
.addGeofence(geofence)
.build();
}
private PendingIntent geoFencePendingIntent;
private static final int GEOFENCE_REQ_CODE = 0;
private PendingIntent createGeofencePendingIntent() {
Log.d(TAG, "createGeofencePendingIntent");
if (geoFencePendingIntent != null)
return geoFencePendingIntent;
Intent intent = new Intent(this, GeofenceTrasitionService.class);
return PendingIntent.getService(
this, GEOFENCE_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
// Add the created GeofenceRequest to the device's monitoring list
private void addGeofence(GeofencingRequest request) {
Log.d(TAG, "addGeofence");
if (checkPermission())
LocationServices.GeofencingApi.addGeofences(
googleApiClient,
request,
createGeofencePendingIntent()
).setResultCallback(this);
}
#Override
public void onResult(#NonNull Status status) {
Log.i(TAG, "onResult: " + status);
if (status.isSuccess()) {
drawGeofence();
} else {
// inform about fail
}
}
// Draw Geofence circle on GoogleMap
private Circle geoFenceLimits;
private void drawGeofence() {
Log.d(TAG, "drawGeofence()");
if (geoFenceLimits != null)
geoFenceLimits.remove();
CircleOptions circleOptions = new CircleOptions()
.center(new LatLng(18.478122, 73.890158))
.strokeColor(Color.argb(50, 70, 70, 70))
.fillColor(Color.argb(100, 150, 150, 150))
.radius(GEOFENCE_RADIUS);
geoFenceLimits = map.addCircle(circleOptions);
}
private final String KEY_GEOFENCE_LAT = "GEOFENCE LATITUDE";
private final String KEY_GEOFENCE_LON = "GEOFENCE LONGITUDE";
// Saving GeoFence marker with prefs mng
private void saveGeofence() {
Log.d(TAG, "saveGeofence()");
SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
// editor.putLong(KEY_GEOFENCE_LAT, Double.doubleToRawLongBits(geoFenceMarker.getPosition().latitude));
// editor.putLong(KEY_GEOFENCE_LON, Double.doubleToRawLongBits(geoFenceMarker.getPosition().longitude));
editor.apply();
}
// Recovering last Geofence marker
private void recoverGeofenceMarker() {
drawGeofence();
}
// Clear Geofence
private void clearGeofence() {
Log.d(TAG, "clearGeofence()");
LocationServices.GeofencingApi.removeGeofences(
googleApiClient,
createGeofencePendingIntent()
).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(#NonNull Status status) {
if (status.isSuccess()) {
// remove drawing
removeGeofenceDraw();
}
}
});
}
private void removeGeofenceDraw() {
Log.d(TAG, "removeGeofenceDraw()");
}
}
To get notification:-
public class GeofenceTrasitionService extends IntentService {
private static final String TAG = GeofenceTrasitionService.class.getSimpleName();
public static final int GEOFENCE_NOTIFICATION_ID = 0;
public GeofenceTrasitionService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
// Handling errors
if ( geofencingEvent.hasError() ) {
String errorMsg = getErrorString(geofencingEvent.getErrorCode() );
Log.e( TAG, errorMsg );
return;
}
int geoFenceTransition = geofencingEvent.getGeofenceTransition();
// Check if the transition type is of interest
if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT ) {
// Get the geofence that were triggered
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
String geofenceTransitionDetails = getGeofenceTrasitionDetails(geoFenceTransition, triggeringGeofences );
// Send notification details as a String
sendNotification( geofenceTransitionDetails );
}
}
private String getGeofenceTrasitionDetails(int geoFenceTransition, List<Geofence> triggeringGeofences) {
// get the ID of each geofence triggered
ArrayList<String> triggeringGeofencesList = new ArrayList<>();
for ( Geofence geofence : triggeringGeofences ) {
triggeringGeofencesList.add( geofence.getRequestId() );
}
String status = null;
if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT )
status = "Exiting ";
return status + TextUtils.join( ", ", triggeringGeofencesList);
}
private void sendNotification( String msg ) {
Log.i(TAG, "sendNotification: " + msg );
// Intent to start the main Activity
Intent notificationIntent = MainActivity.makeNotificationIntent(
getApplicationContext(), msg
);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(notificationIntent);
PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Creating and sending Notification
NotificationManager notificatioMng =
(NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE );
notificatioMng.notify(
GEOFENCE_NOTIFICATION_ID,
createNotification(msg, notificationPendingIntent));
}
// Create notification
private Notification createNotification(String msg, PendingIntent notificationPendingIntent) {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder
.setSmallIcon(R.drawable.ic_action_location)
.setColor(Color.RED)
.setContentTitle(msg)
.setContentText("Geofence Notification!")
.setContentIntent(notificationPendingIntent)
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND)
.setAutoCancel(true);
return notificationBuilder.build();
}
private static String getErrorString(int errorCode) {
switch (errorCode) {
case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
return "GeoFence not available";
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
return "Too many GeoFences";
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
return "Too many pending intents";
default:
return "Unknown error.";
}
}
}
As per tutorial i see:- there are 3 notification trigger
1.Enter 2.Dwell 3.Exit
I dont know how did i get notified when it leave the fence so far as in code i tried Exit.But no luck.
Ok i understand so just need to change the function :-
private GeofencingRequest createGeofenceRequest(Geofence geofence) {
Log.d(TAG, "createGeofenceRequest");
return new GeofencingRequest.Builder()
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_EXIT)
.addGeofence(geofence)
.build();
}
Here i did changed My initial trigger with Exit
"GeofencingRequest.INITIAL_TRIGGER_EXIT"
and got perfect output.
This work for both enter and exit
private GeofencingRequest createGeofenceRequest(Geofence geofence) {
return new GeofencingRequest.Builder()
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_EXIT|GeofencingRequest.INITIAL_TRIGGER_ENTER)
.addGeofence(geofence)
.build();

FusedLocaionAPI Searching GPS signal stops

I have a service that when it creates and starts, initiates prerequisites of using FusedLocationAPI . buildGoogleApiClient() and createLocationRequest() with parameters that initiated by my getConfig() method from database.
This solution works great and accurate with parameters like:
UPDATE_INTERVAL= 10000 (10 sec) , FASTEST_INTERVAL= 5000 (5 sec) , DISPLACEMENT= 10 ( m )
But I need to set interval up to 5 minutes. So when i set prameters like :
UPDATE_INTERVAL= 300000 (5 min) , FASTEST_INTERVAL= 180000 (3 min) , DISPLACEMENT= 10 ( m )
GPS behaves differently and after 30 seconds stops searching GPS and location notification that blinks, disappears.
And starts searching again after device locked and unlocked or this Service stops and starts again.
Here is my service. Please tell me why searching GPS stops right after 30 seconds.
Thanks in advanece.
public class MainService extends Service implements ConnectionCallbacks,
OnConnectionFailedListener, LocationListener {
private final static String TAG = MainActivity.class.getSimpleName();
private static int UPDATE_INTERVAL;
private static int FASTEST_INTERVAL;
private static int DISPLACEMENT;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private Location mLastLocation;
public String deviceIMEI;
public boolean isGpsEnabled = false;
DatabaseHelper mDBHelper;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
getDeviceIMEI();
getConfig();
startForeGroundService();
if (checkPlayServices() && checkLocationServices()) {
buildGoogleApiClient();
createLocationRequest();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (mGoogleApiClient != null)
mGoogleApiClient.connect();
else {
stopForeground(true);
stopSelf();
}
return (START_NOT_STICKY);
}
#Override
public void onDestroy() {
stopForeground(true);
if (mGoogleApiClient != null)
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
#SuppressWarnings("deprecation")
public void startForeGroundService() {
Notification note = new Notification(
R.drawable.track_notification_alert,
"GPS tracking started ...", System.currentTimeMillis());
Intent i = new Intent();
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);
note.setLatestEventInfo(this, "GPS is active.",
"Now this tablet is under tracking. ", pi);
note.flags |= Notification.FLAG_NO_CLEAR;
startForeground(1337, note);
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private boolean checkLocationServices() {
LocationManager lm = (LocationManager) getApplicationContext()
.getSystemService(LOCATION_SERVICE);
isGpsEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
return isGpsEnabled;
}
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
return false;
}
return true;
}
#Override
public void onConnected(Bundle arg0) {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
if (Globals.isSatelliteFix && Globals.isGPSEnable)
setPoint();
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
if (Globals.isSatelliteFix && Globals.isGPSEnable)
setPoint();
}
private void setPoint() {
mDBHelper = new DatabaseHelper(getApplicationContext());
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
try {
Point p = new Point();
p.setId(UUID.randomUUID().toString());
p.setIMEI(deviceIMEI);
p.setLatitude(String.valueOf(latitude));
p.setLongitude(String.valueOf(longitude));
p.setTimeStamp(createTimeStamp());
long result = mDBHelper.addPoint(p);
if (result != -1) {
Log.i(TAG, "Insertion Successfull With RowId: " + result);
} else
Log.e(TAG, "Insertion Error");
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Insertion Error: " + e.getMessage());
}
}
}
public String createTimeStamp() {
String strTimeStamp = new SimpleDateFormat("yyyy-MM-dd_kk:mm:ss")
.format(new Date());
return strTimeStamp;
}
public void getDeviceIMEI() {
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
deviceIMEI = telephonyManager.getDeviceId();
}
public long getTimeInMiliSeconds() {
Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();
return date.getTime();
}
public void getConfig() {
Config config = new Config();
mDBHelper = new DatabaseHelper(getApplicationContext());
config = mDBHelper.getConfig();
UPDATE_INTERVAL = config.getUpdateInterval();
FASTEST_INTERVAL = config.getFastestInterval();
DISPLACEMENT = config.getSmallestDisplacement();
}
}

Categories

Resources