Android Geofence works after phone restart - android

I am adding multiple geofence to one app.(Max 100 allowed according to documentation.) I was getting callbacks of geofence then it stopped.
Geofence works smoothly only when I restart phone. After few minutes it stops working again.
public class GeoFenceHelper implements IGeoFenceListener, GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private Context context;
private GeofencingClient mGeoFencingClient;
private PendingIntent geoFencePendingIntent;
private String TAG = GeoFenceHelper.class.getSimpleName();
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;
Location tempLocation = new Location("");
/**
* The list of geoFences used in this sample.
*/
private ArrayList<Geofence> mGeoFenceList;
private List<GeoFenceModel> geoFenceEntries;
private ArrayList<String> removeGeoFenceList = new ArrayList<>();
public GeoFenceHelper(Context context) {
this.context = context;
mGeoFenceList = new ArrayList<>();
mGeoFencingClient = LocationServices.getGeofencingClient(context);
}
public void registerGeoFence(List<GeoFenceModel> geoFenceEntries) {
mGeoFenceList.clear();
this.geoFenceEntries = geoFenceEntries;
if (DatabaseManager.getInstance(context).getGeoFenceLocationCount() <= Constants.MAX_GEOFENCE_ENTRY_COUNT) {
addGeoFences(geoFenceEntries);
} else {
buildGoogleApiClient();
}
}
private void addGeoFences(List<GeoFenceModel> geoFenceEntries) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
for (GeoFenceModel geoFenceEntry : geoFenceEntries) {
if(geoFenceEntry.getId()==Constants.DESTINATION_REACHED_ID) {
removeGeoFenceList.clear();
removeGeoFenceList.add(""+geoFenceEntry.getId());
unregisterGeoFence(removeGeoFenceList);
}
Geofence geoFence = new Geofence.Builder()
.setRequestId(String.valueOf(geoFenceEntry.getId()))
.setExpirationDuration(geoFenceEntry.getExpireDuration())
.setCircularRegion(
geoFenceEntry.getLatitude(),
geoFenceEntry.getLongitude(),
geoFenceEntry.getRadius()
)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
.build();
CustomLogger.logE("GEOGENCE", "Geo Fence lat = " + geoFenceEntry.getLatitude() + " log = " + geoFenceEntry.getLongitude() + "Radius = " + geoFenceEntry.getRadius()+" Expiry "+geoFenceEntry.getExpireDate());
mGeoFenceList.add(geoFence);
}
mGeoFencingClient.addGeofences(getGeoFencingRequest(mGeoFenceList), getGeoFencePendingIntent());
Utils.stopLocationUpdate(context);
}
#Override
public void unregisterGeoFence(List<String> genFenceList) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
CustomLogger.logE("GeoFence","Remove GeoFence "+genFenceList.get(0));
mGeoFencingClient.removeGeofences(genFenceList);
}
/**
* Builds and returns a GeoFencingRequest. Specifies the list of geoFences to be monitored.
* Also specifies how the geoFence notifications are initially triggered.
*
* #param mGeoFenceList
*/
private GeofencingRequest getGeoFencingRequest(ArrayList<Geofence> mGeoFenceList) {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
builder.addGeofences(mGeoFenceList);
return builder.build();
}
private PendingIntent getGeoFencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (geoFencePendingIntent != null) {
return geoFencePendingIntent;
}
Intent intent = new Intent(context, GeofenceTransitionsIntentService.class);
geoFencePendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return geoFencePendingIntent;
}
//Location related code
private synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this.context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
if (mGoogleApiClient != null && !mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
CustomLogger.logE("tempLocation", "lat " + latitude + "long " + longitude);
List<GeoFenceModel> geoFenceLocations = DatabaseManager.getInstance(context).getGeoFenceLocation();
calculateLocationDistance(mLastLocation, geoFenceLocations);
try {
deleteLocations(geoFenceLocations);
addGeoFences(geoFenceEntries);
} catch (SQLException e) {
e.printStackTrace();
}
} else {
CustomLogger.logE("tempLocation", "(Couldn't get the tempLocation. Make sure tempLocation is enabled on the device)");
}
}
private void deleteLocations(List<GeoFenceModel> geoFenceLocations) throws SQLException {
int reduceCount = Math.abs(Constants.MAX_GEOFENCE_ENTRY_COUNT - geoFenceLocations.size());
CustomLogger.logE("GEOGENCE", "Geo Fence App lat = "+geoFenceLocations.get(0).getLatitude() + " log = "+ geoFenceLocations.get(0).getLongitude() + "App sepcific = "+ geoFenceLocations.get(0).isAppSpecific());
GeoFenceModel geoFenceModel = null;
for (int i = 0; i < reduceCount; i++) {
if(geoFenceLocations.get(0).isAppSpecific())
{
geoFenceModel = geoFenceLocations.remove(1); //because app specific item will be available at top of the list
}
else
{
geoFenceModel = geoFenceLocations.remove(0);
}
DatabaseManager.getInstance(context).getHelper().getNotificationGeoFenceModelDao().delete(geoFenceModel);
try {
List notificationIds = new ArrayList<String>();
notificationIds.add(String.valueOf(geoFenceModel.getId()));
unregisterGeoFence(notificationIds);
}
catch (Exception e)
{
CustomLogger.logE("GEOFENCE ","EXCEPTION"+e);
}
for (GeoFenceModel geoFence: geoFenceEntries) {
if (geoFence.getId()==geoFenceModel.getId())
{
geoFenceEntries.remove(geoFenceModel);
CustomLogger.logE("GEOGENCE", "Geo Fence Removed lat = "+geoFence.getLatitude() + " log = "+ geoFence.getLongitude() + "Radius = "+ geoFence.getRadius());
}
}
}
}
private void calculateLocationDistance(Location mLastLocation, List<GeoFenceModel> geoFenceLocations) {
for (GeoFenceModel geoFenceLocation : geoFenceLocations) {
tempLocation.setLatitude(geoFenceLocation.getLatitude());
tempLocation.setLongitude(geoFenceLocation.getLongitude());
geoFenceLocation.setDistanceInMeters(mLastLocation.distanceTo(tempLocation));
}
Collections.sort(geoFenceLocations);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
In logs, geofence is getting register properly.
I have implemented IntentService in pending intent. I tried broadcast receiver also but result was same.
Tried same code with multiple devices and OS version.

Location updates on interval is missing in your code.
You have to request for location at HIGH_ACCURACY which enables GPS to give you accurate location at given interval time.
There are lot of changes required as per this tutorial.
go through above tutorial and let me know if it doesn't work.
You must have to create location request.
one more tutorial

Related

Places API android not showing on specific device

I'm trying to create a location based notification for an app I'm working on. I get a location using Google Places API and create a location based notification like so:
//used to get places
private void showPlaces() {
try {
PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
startActivityForResult(builder.build(getActivity()), PLACE_PICKER_REQUEST);
} catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PLACE_PICKER_REQUEST && resultCode == Activity.RESULT_OK) {
displayPlace(PlacePicker.getPlace(getContext(), data));
}
}
private void displayPlace(Place place)
{
if (place == null)
return;
double latitude = place.getLatLng().latitude;
double longitude = place.getLatLng().longitude;
if (ingredient_list.size() > 0)
{
System.out.println("Display Place:");
if (ActivityCompat.checkSelfPermission(getContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(getActivity(), new String[]{ android.Manifest.permission.ACCESS_FINE_LOCATION}, 1);
ActivityCompat.requestPermissions(getActivity(), new String[]{ android.Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
return;
}
System.out.println("Display Place:");
initGoogleAPIClient();
createGeofences(latitude, longitude);
Toast.makeText(getContext(),"Added Notification!",Toast.LENGTH_SHORT).show();
}
}
public void initGoogleAPIClient()
{
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addApi(LocationServices.API)
.addConnectionCallbacks(connectionAddListener)
.addOnConnectionFailedListener(connectionFailedListener)
.build();
mGoogleApiClient.connect();
}
private GoogleApiClient.ConnectionCallbacks connectionAddListener = new GoogleApiClient.ConnectionCallbacks()
{
#Override
public void onConnected(Bundle bundle)
{
System.out.println("onConnected");
try{
LocationServices.GeofencingApi.addGeofences(
mGoogleApiClient,
getGeofencingRequest(),
getGeofencePendingIntent()
).setResultCallback(new ResultCallback<Status>()
{
#Override
public void onResult(Status status)
{
if (status.isSuccess())
{
System.out.println("Saving Geofence");
}
else
{
System.out.println("Registering geofence failed: " + status.getStatusMessage() + " : " + status.getStatusCode());
}
}
});
}
catch (SecurityException securityException)
{
// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
System.out.println("Error " + securityException);
}
}
#Override
public void onConnectionSuspended(int i)
{
System.out.println("onConnectionSuspended");
}
};
private GoogleApiClient.OnConnectionFailedListener connectionFailedListener =
new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult connectionResult)
{
System.out.println("onConnectionFailed");
}
};
public void createGeofences(double latitude, double longitude)
{
String id = UUID.randomUUID().toString();
Geofence fence = new Geofence.Builder()
.setRequestId(id)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
.setCircularRegion(latitude, longitude, 200)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.build();
mGeofenceList.add(fence);
}
private GeofencingRequest getGeofencingRequest()
{
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
builder.addGeofences(mGeofenceList);
return builder.build();
}
private PendingIntent getGeofencePendingIntent()
{
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null)
{
return mGeofencePendingIntent;
}
Intent intent = new Intent(getActivity(), GeofenceTransitionsIntentService.class);
intent.putExtra("extra", title_string);
intent.putStringArrayListExtra("extra2", ingredient_list);
return PendingIntent.getService(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
This seems to work fine on every device I tested on except for a user testing on a Nexus 5 6.0.1 who reports that when he launches a notification request, the map shows briefly and then disappears immediately after that. I initially thought that this might have something to do with the permission so I asked him to manually turn on his location permission in the app settings but he got the same result. Does anyone have a clue as to whats going on here? I can't seem to figure out why it works on multiple other devices even on the same firmware but it's not showing up for him.

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();

how to update latitude and longitude through a background service at regular intervals?

I have written a background service to insert latitude , longitude and some other details into my sqlite database based on the time limit set in my AlarmManager.
I am using GoogleApiClient to calculate latitude and longitude , but i am facing some problems.
Problem
When i am travelling outside without net , the latitude and longitude is not getting updated at regular intervals. The data is getting inserted in my sqlite at regular intervals but latitude and longitude remains same even after half an hour though i am travelling some about 10 kms.
I want the latitude and longitude to change while i am travelling like auto update.
I wanted to know if the FusedLocationApi calculates latitude longitude properly even if i am not connected to the internet , if yes then i need some suggestions to improve the code that i have tried.
Code i have tried.
AlarmManagerService.java
public class AlarmManagerService extends Service implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static final String TAG = "AlarmManagerService";
AlarmReceiver alarmReceiver;
DriverDbHelper driverDbHelper;
Handler handler;
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private Location mLastLocation;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
// boolean flag to toggle periodic location updates
private boolean mRequestingLocationUpdates = false;
private LocationRequest mLocationRequest;
// Location updates intervals in sec
private static int UPDATE_INTERVAL = 120000; // 2 mins
private static int FATEST_INTERVAL = 60000; // 1 min
private static int DISPLACEMENT = 10; // 10 meters
public Activity activity;
protected String mLastUpdateTime;
String areaName0, areaName1, areaName2, areaName3, fullAreaName,
sessionMobileNo, sessionDriverName, sessionDID, sessiondriverUserId,
date, time, dateTime, doc, trac_transId;
double latitude, longitude;
PowerManager.WakeLock mWakeLock;
SessionManager session;
ConnectionDetector cd;
Boolean isInternet = false;
String sync_no = "No";
String sync_yes = "Yes";
public AlarmManagerService() {
alarmReceiver = new AlarmReceiver();
driverDbHelper = new DriverDbHelper(this);
cd = new ConnectionDetector(this);
}
public void setActivity(Activity activity) {
this.activity = activity;
}
#Override
public void onCreate() {
super.onCreate();
try {
driverDbHelper.open(AlarmManagerService.this);
} catch (Exception e) {
e.printStackTrace();
}
Log.d("Service created", "Alarm Service Created");
// First we need to check availability of play services
if (checkPlayServices()) {
// Building the GoogleApi client
buildGoogleApiClient();
createLocationRequest();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
PowerManager mgr = (PowerManager)
getSystemService(Context.POWER_SERVICE);
if (this.mWakeLock == null) {
this.mWakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakeLock");
}
if (!this.mWakeLock.isHeld()) {
this.mWakeLock.acquire();
}
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
Log.d("Service started", "Alarm Service Started");
handler = new Handler(Looper.myLooper());
handler.post(new Runnable() {
#Override
public void run() {
postDatabaseDetails();
}
});
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("Service started", "Alarm Service Destroyed");
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
mGoogleApiClient.disconnect();
}
if (this.mWakeLock != null) {
this.mWakeLock.release();
this.mWakeLock = null;
}
}
private void displayLocation() {
if (mLastLocation != null) {
latitude = mLastLocation.getLatitude();
longitude = mLastLocation.getLongitude();
List<Address> addressList = null;
try {
Geocoder gcd = new Geocoder(getBaseContext(),
Locale.getDefault());
addressList = gcd.getFromLocation(mLastLocation.getLatitude(),
mLastLocation.getLongitude(), 1);
if (addressList != null && addressList.size() > 0) {
Address address = addressList.get(0);
areaName0 = address.getLocality(); // city name
areaName1 = address.getSubLocality();
areaName2 = address.getAdminArea();// statename
//areaName3 = address.getFeatureName(); plot no
//areaName3 = address.getCountryCode();// IN
areaName3 = address.getThoroughfare();
fullAreaName = areaName3 + "\n" + areaName1 + "\n" +
areaName0 + "," + areaName2;
} else {
Log.i("Location ", "Location null");
}
} catch (IOException e1) {
Log.e("HomePage", "IO Exception in getFromLocation()");
e1.printStackTrace();
} catch (IllegalArgumentException e2) {
// Error message to post in the log
String errorString = "Illegal arguments " +
Double.toString(mLastLocation.getLatitude()) + " , " +
Double.toString(mLastLocation.getLongitude()) +
" passed to address service";
Log.e("HomePage", errorString);
e2.printStackTrace();
}
}
}
/**
* Creating google api client object
*/
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Creating location request object
*/
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
//mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
/**
* Method to verify google play services on the device
*/
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, activity,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Log.i("Google play services", "Device not supported");
activity.finish();
}
return false;
}
return true;
}
/**
* Starting the location updates
*/
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
/**
* Stopping location updates
*/
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
#Override
public void onConnected(Bundle bundle) {
// Once connected with google api, get the location
//displayLocation();
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
if (mLastLocation == null) {
mLastLocation =
LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
displayLocation();
}
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
Log.d("Location changed ", "Location changed " + mLastLocation);
Log.d("Last updated time", "Last updated location " + mLastUpdateTime);
// Displaying the new location on UI
displayLocation();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ connectionResult.getErrorCode());
}
public void postDatabaseDetails() {
session = new SessionManager(getApplicationContext());
HashMap<String, String> user = session.getUserDetails();
sessionMobileNo = user.get(SessionManager.KEY_MOBILENO);
sessionDriverName = user.get(SessionManager.KEY_NAME);
sessionDID = user.get(SessionManager.KEY_DEVICEID);
sessiondriverUserId = user.get(SessionManager.KEY_DRIVERUSERID);
Calendar in = Calendar.getInstance();
Date dt = new Date();
in.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat stf = new SimpleDateFormat("HH:mm:ss");
date = sdf.format(dt);
time = stf.format(dt);
String timeval = time.toString();
String dateval = date.toString();
dateTime = date.toString() + " " + time.toString();
doc = sessionDID + "" + dateTime;
isInternet = cd.isConnectingToInternet();
if (isInternet) {
long id = driverDbHelper.insertDriverDetails(doc, sessionDID,
sessiondriverUserId, latitude, longitude,
fullAreaName, dateTime, "DEMO", sync_no, dateval, timeval);
postDriverDetails();
Log.d("GPS", "Service started after 2 mins with internet");
} else {
Log.d("Internet status", "No internet available for service");
long id = driverDbHelper.insertDriverDetails(doc, sessionDID,
sessiondriverUserId, latitude, longitude,
"NA", dateTime, "DEMO", sync_no, dateval, timeval);
Log.d("GPS", "Service started after 2 mins without internet");
}
}
I am calling this service from the activity HomePage.java , but from where do i have to call the below code , from onStart() or after setContentView(R.layout.home)?
try {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MINUTE, 2);
AlarmManager am = (AlarmManager)
getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(Home_Page.this, AlarmManagerService.class);
PendingIntent pi = PendingIntent.getService(Home_Page.this, 0, i,0);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), EXEC_INTERVAL, pi);
} catch (Exception e) {
e.printStackTrace();
}
I hope i can get some suggestions to improve the above service code as i want it to run smoothly in background updating the latitude and longitude at regular intervals.

Starting a BroadcastReceiver from activity

I'm trying to start a BroadcastReceiver from an activity - and it seems the receiver doesnt start and I dont get any output in logCat for it.
Im trying to start the receiver by doing this:
Intent intent = new Intent();
intent.setAction(getPackageName()+".mybroadcast");
sendBroadcast(intent);
Also here is my receiver class:
public class TriggerReceiver extends BroadcastReceiver implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private Vibrator v;
private CountDownTimer timer;
private final long INTERVAL = 1000;
private final long TWO_MINUTES = INTERVAL * 60 * 2;
// === variables
private Context context;
private final String TAG = TriggerReceiver.class.getSimpleName();
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
Log.e(TAG, "Trigger receiver starting");
v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
mRequestingLocationUpdates = false;
buildGoogleApiClient();
mGoogleApiClient.connect();
}
//
private void startTimer(final Location location) {
String message = context.getString(R.string.emergency_text).replace("/location here/", getMapLink(location));
sendSMS(message);
showNotification();
Log.e(TAG, " sending sms and this is the location " + location.getLatitude() + " " + location.getLongitude());
timer = new CountDownTimer(TWO_MINUTES, INTERVAL) {
#Override
public void onTick(long millisUntilFinished) {
Log.e(TAG, "Tick " + (millisUntilFinished / 1000));
int elapsedTime = (int) ((millisUntilFinished / 1000) % 60);
int minutes = (int) ((millisUntilFinished / 1000) / 60);
Log.e(TAG, elapsedTime + " | " + minutes);
if (minutes == 2) {
minutes = 1;
elapsedTime = 60;
}
}
//TODO start activity and pass extras to intent
#Override
public void onFinish() {
startTimer(mCurrentLocation);
}
}.start();
}
private void sendSMS(String message) {
ArrayList<Contact> contacts = ((BaseActivity) context).getContacts();
for (Contact contact : contacts) {
sendSMSmsg(contact.getNumber(), message);
}
}
private void stopTimer() {
timer.cancel();
}
/*location*/
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
/**
* Stores parameters for requests to the FusedLocationProviderApi.
*/
protected LocationRequest mLocationRequest, quickLocationRequest;
/**
* Represents a geographical location.
*/
protected Location mCurrentLocation, mLastLocation;
protected Boolean mRequestingLocationUpdates;
/**
* Builds a GoogleApiClient. Uses the {#code #addApi} method to request the
* LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
protected void createLocationRequest() {
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(110000);
mLocationRequest.setFastestInterval(55000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
protected void doQuickLocationUpdate() {
quickLocationRequest = new LocationRequest();
quickLocationRequest.setInterval(1000);
quickLocationRequest.setFastestInterval(500);
quickLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, quickLocationRequest, this);
}
protected void stopLocationUpdates() {
//TODO add this in onbackpresses and onStop
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "Connected to GoogleApiClient");
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
startTimer(mLastLocation);
} else {
doQuickLocationUpdate();
}
if (mCurrentLocation == null) {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
Log.d(TAG, "onConnected mCurrentLocation = " + mCurrentLocation.getLatitude());
}
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
if (quickLocationRequest != null) {
quickLocationRequest = null;
}
if (timer == null) {
startTimer(location);
}
Log.d(TAG, "onLocationChanged mCurrentLocation = " + mCurrentLocation.getLatitude());
}
#Override
public void onConnectionSuspended(int cause) {
// The connection to Google Play services was lost for some reason. We call connect() to
// attempt to re-establish the connection.
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
}
public void sendSMSmsg(String phoneNumber, String message) {
v.vibrate(50);
// ArrayList<PendingIntent> sentPendingIntents = new ArrayList<PendingIntent>();
// ArrayList<PendingIntent> deliveredPendingIntents = new ArrayList<PendingIntent>();
// PendingIntent sentPI = PendingIntent.getBroadcast(context, 0,
// new Intent(context, SmsSentReceiver.class), 0);
// PendingIntent deliveredPI = PendingIntent.getBroadcast(context, 0,
// new Intent(context, SmsDeliveredReceiver.class), 0);
// try {
// SmsManager sms = SmsManager.getDefault();
// ArrayList<String> mSMSMessage = sms.divideMessage(message);
// for (int i = 0; i < mSMSMessage.size(); i++) {
// sentPendingIntents.add(i, sentPI);
// deliveredPendingIntents.add(i, deliveredPI);
// }
// sms.sendMultipartTextMessage(phoneNumber, null, mSMSMessage,
// sentPendingIntents, deliveredPendingIntents);
//
// } catch (Exception e) {
// e.printStackTrace();
// }
}
public void showNotification() {
NotificationCompat.Builder mBuilder;
if (Build.VERSION.SDK_INT >= 16) {
mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.sosicon)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentTitle(context.getString(R.string.app_name))
.setAutoCancel(true)
.setContentText(context.getString(R.string.notification_text));
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent();
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(10142, mBuilder.build());
}
}
public String getMapLink(Location location) {
if (location != null) {
Log.d(TAG, "http://maps.google.com/maps?z=12&t=m&q=loc:" + location.getLatitude() + "+" + location.getLongitude());
return "http://maps.google.com/maps?z=12&t=m&q=loc:" + location.getLatitude() + "+" + location.getLongitude();
} else {
return null;
}
}
//
}
and also the declaration in the manifest:
<receiver
android:name=".TriggerReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="PACKAGENAME.mybroadcast" />
</intent-filter>
</receiver>
So what can be wrong here and why is the receiver not starting?
Thanks

Google Maps android get longitude-latitude by moving a marker in the map

Hi i am developping an android application in which i need the user to choose a location by mouving a parker so i can get the informations i need exactly like this but in an android application.
I did some researchs but i'm still new so i couldn't find anything close to this.
Can anyone point me to the right direction ?
What i need to do is to create a mouving cursor in a simple google map that could give me long+lat data. all i coud do is put some static locations in my map.
Are you looking something like in the images below..
Here, if we drag marker on map it will automatically update the current lat, longs..
Here is the full complete solution with the code.
1.) Create a class AppUtils
public class AppUtils {
public class LocationConstants {
public static final int SUCCESS_RESULT = 0;
public static final int FAILURE_RESULT = 1;
public static final String PACKAGE_NAME = "your package name";
public static final String RECEIVER = PACKAGE_NAME + ".RECEIVER";
public static final String RESULT_DATA_KEY = PACKAGE_NAME + ".RESULT_DATA_KEY";
public static final String LOCATION_DATA_EXTRA = PACKAGE_NAME + ".LOCATION_DATA_EXTRA";
public static final String LOCATION_DATA_AREA = PACKAGE_NAME + ".LOCATION_DATA_AREA";
public static final String LOCATION_DATA_CITY = PACKAGE_NAME + ".LOCATION_DATA_CITY";
public static final String LOCATION_DATA_STREET = PACKAGE_NAME + ".LOCATION_DATA_STREET";
}
public static boolean hasLollipop() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
}
public static boolean isLocationEnabled(Context context) {
int locationMode = 0;
String locationProviders;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
return locationMode != Settings.Secure.LOCATION_MODE_OFF;
} else {
locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
return !TextUtils.isEmpty(locationProviders);
}
}
}
2.) create another class FetchAddressIntentService
This class will fetch the address and point to that particular location which user is going to type on Google AutocompleteTextView..
public class FetchAddressIntentService extends IntentService {
private static final String TAG = "FetchAddressIS";
/**
* The receiver where results are forwarded from this service.
*/
protected ResultReceiver mReceiver;
/**
* This constructor is required, and calls the super IntentService(String)
* constructor with the name for a worker thread.
*/
public FetchAddressIntentService() {
// Use the TAG to name the worker thread.
super(TAG);
}
/**
* Tries to get the location address using a Geocoder. If successful, sends an address to a
* result receiver. If unsuccessful, sends an error message instead.
* Note: We define a {#link ResultReceiver} in * MainActivity to process content
* sent from this service.
* <p>
* This service calls this method from the default worker thread with the intent that started
* the service. When this method returns, the service automatically stops.
*/
#Override
protected void onHandleIntent(Intent intent) {
String errorMessage = "";
mReceiver = intent.getParcelableExtra(AppUtils.LocationConstants.RECEIVER);
// Check if receiver was properly registered.
if (mReceiver == null) {
Log.wtf(TAG, "No receiver received. There is nowhere to send the results.");
return;
}
// Get the location passed to this service through an extra.
Location location = intent.getParcelableExtra(AppUtils.LocationConstants.LOCATION_DATA_EXTRA);
// Make sure that the location data was really sent over through an extra. If it wasn't,
// send an error error message and return.
if (location == null) {
errorMessage = getString(R.string.no_location_data_provided);
Log.wtf(TAG, errorMessage);
deliverResultToReceiver(AppUtils.LocationConstants.FAILURE_RESULT, errorMessage, null);
return;
}
// Errors could still arise from using the Geocoder (for example, if there is no
// connectivity, or if the Geocoder is given illegal location data). Or, the Geocoder may
// simply not have an address for a location. In all these cases, we communicate with the
// receiver using a resultCode indicating failure. If an address is found, we use a
// resultCode indicating success.
// The Geocoder used in this sample. The Geocoder's responses are localized for the given
// Locale, which represents a specific geographical or linguistic region. Locales are used
// to alter the presentation of information such as numbers or dates to suit the conventions
// in the region they describe.
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
// Address found using the Geocoder.
List<Address> addresses = null;
try {
// Using getFromLocation() returns an array of Addresses for the area immediately
// surrounding the given latitude and longitude. The results are a best guess and are
// not guaranteed to be accurate.
addresses = geocoder.getFromLocation(
location.getLatitude(),
location.getLongitude(),
// In this sample, we get just a single address.
1);
} catch (IOException ioException) {
// Catch network or other I/O problems.
errorMessage = getString(R.string.service_not_available);
Log.e(TAG, errorMessage, ioException);
} catch (IllegalArgumentException illegalArgumentException) {
// Catch invalid latitude or longitude values.
errorMessage = getString(R.string.invalid_lat_long_used);
Log.e(TAG, errorMessage + ". " +
"Latitude = " + location.getLatitude() +
", Longitude = " + location.getLongitude(), illegalArgumentException);
}
// Handle case where no address was found.
if (addresses == null || addresses.size() == 0) {
if (errorMessage.isEmpty()) {
errorMessage = getString(R.string.no_address_found);
Log.e(TAG, errorMessage);
}
deliverResultToReceiver(AppUtils.LocationConstants.FAILURE_RESULT, errorMessage, null);
} else {
Address address = addresses.get(0);
ArrayList<String> addressFragments = new ArrayList<String>();
for (int i = 0; i < address.getMaxAddressLineIndex(); i++) {
addressFragments.add(address.getAddressLine(i));
}
deliverResultToReceiver(AppUtils.LocationConstants.SUCCESS_RESULT,
TextUtils.join(System.getProperty("line.separator"), addressFragments), address);
//TextUtils.split(TextUtils.join(System.getProperty("line.separator"), addressFragments), System.getProperty("line.separator"));
}
}
/**
* Sends a resultCode and message to the receiver.
*/
private void deliverResultToReceiver(int resultCode, String message, Address address) {
try {
Bundle bundle = new Bundle();
bundle.putString(AppUtils.LocationConstants.RESULT_DATA_KEY, message);
bundle.putString(AppUtils.LocationConstants.LOCATION_DATA_AREA, address.getSubLocality());
bundle.putString(AppUtils.LocationConstants.LOCATION_DATA_CITY, address.getLocality());
bundle.putString(AppUtils.LocationConstants.LOCATION_DATA_STREET, address.getAddressLine(0));
mReceiver.send(resultCode, bundle);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.) Create your MapActivity in this we are going to display our map
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener {
private GoogleMap mMap;
private GoogleApiClient mGoogleApiClient;
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
private static String TAG = "MAP LOCATION";
Context mContext;
TextView mLocationMarkerText;
public LatLng mCenterLatLong;
/**
* Receiver registered with this activity to get the response from FetchAddressIntentService.
*/
private AddressResultReceiver mResultReceiver;
/**
* The formatted location address.
*/
protected String mAddressOutput;
protected String mAreaOutput;
protected String mCityOutput;
protected String mStateOutput;
EditText mLocationAddress;
TextView mLocationText;
private static final int REQUEST_CODE_AUTOCOMPLETE = 1;
Toolbar mToolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
mContext = this;
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mLocationMarkerText = (TextView) findViewById(R.id.locationMarkertext);
mLocationAddress = (EditText) findViewById(R.id.Address); //sss
mLocationText = (TextView) findViewById(R.id.Locality); //sss
mToolbar = (Toolbar) findViewById(R.id.toolbar); //sss
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setTitle(getResources().getString(R.string.app_name));
mLocationText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openAutocompleteActivity();
}
});
mapFragment.getMapAsync(this);
mResultReceiver = new AddressResultReceiver(new Handler());
if (checkPlayServices()) {
if (!AppUtils.isLocationEnabled(mContext)) {
// notify user
AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
dialog.setMessage("Location not enabled!");
dialog.setPositiveButton("Open location settings", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(myIntent);
}
});
dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
// TODO Auto-generated method stub
}
});
dialog.show();
}
buildGoogleApiClient();
} else {
Toast.makeText(mContext, "Location not supported in this device", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
Log.d(TAG, "OnMapReady");
mMap = googleMap;
mMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
#Override
public void onCameraChange(CameraPosition cameraPosition) {
Log.d("Camera postion change" + "", cameraPosition + "");
mCenterLatLong = cameraPosition.target;
mMap.clear();
try {
Location mLocation = new Location("");
mLocation.setLatitude(mCenterLatLong.latitude);
mLocation.setLongitude(mCenterLatLong.longitude);
startIntentService(mLocation);
mLocationMarkerText.setText("Lat : " + mCenterLatLong.latitude + "," + "Long : " + mCenterLatLong.longitude);
} catch (Exception e) {
e.printStackTrace();
}
}
});
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
}
#Override
public void onConnected(Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
changeMap(mLastLocation);
Log.d(TAG, "ON connected");
} else
try {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
} catch (Exception e) {
e.printStackTrace();
}
try {
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
try {
if (location != null)
changeMap(location);
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#Override
protected void onStart() {
super.onStart();
try {
mGoogleApiClient.connect();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onStop() {
super.onStop();
try {
} catch (RuntimeException e) {
e.printStackTrace();
}
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
//finish();
}
return false;
}
return true;
}
private void changeMap(Location location) {
Log.d(TAG, "Reaching map" + mMap);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
// check if map is created successfully or not
if (mMap != null) {
mMap.getUiSettings().setZoomControlsEnabled(false);
LatLng latLong;
latLong = new LatLng(location.getLatitude(), location.getLongitude());
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(latLong).zoom(15).tilt(70).build();
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
mMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
mLocationMarkerText.setText("Lat : " + location.getLatitude() + "," + "Long : " + location.getLongitude());
startIntentService(location);
} else {
Toast.makeText(getApplicationContext(),
"Sorry! unable to create maps", Toast.LENGTH_SHORT)
.show();
}
}
/**
* Receiver for data sent from FetchAddressIntentService.
*/
class AddressResultReceiver extends ResultReceiver {
public AddressResultReceiver(Handler handler) {
super(handler);
}
/**
* Receives data sent from
* FetchAddressIntentService and updates the UI in MainActivity.
*/
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Display the address string or an error message sent from the intent service.
mAddressOutput = resultData.getString(AppUtils.LocationConstants.RESULT_DATA_KEY);
mAreaOutput = resultData.getString(AppUtils.LocationConstants.LOCATION_DATA_AREA);
mCityOutput = resultData.getString(AppUtils.LocationConstants.LOCATION_DATA_CITY);
mStateOutput = resultData.getString(AppUtils.LocationConstants.LOCATION_DATA_STREET);
displayAddressOutput();
// Show a toast message if an address was found.
if (resultCode == AppUtils.LocationConstants.SUCCESS_RESULT) {
// showToast(getString(R.string.address_found));
}
}
}
/**
* Updates the address in the UI.
*/
protected void displayAddressOutput() {
// mLocationAddressTextView.setText(mAddressOutput);
try {
if (mAreaOutput != null)
// mLocationText.setText(mAreaOutput+ "");
mLocationAddress.setText(mAddressOutput);
//mLocationText.setText(mAreaOutput);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Creates an intent, adds location data to it as an extra, and starts the intent service for
* fetching an address.
*/
protected void startIntentService(Location mLocation) {
// Create an intent for passing to the intent service responsible for fetching the address.
Intent intent = new Intent(this, FetchAddressIntentService.class);
// Pass the result receiver as an extra to the service.
intent.putExtra(AppUtils.LocationConstants.RECEIVER, mResultReceiver);
// Pass the location data as an extra to the service.
intent.putExtra(AppUtils.LocationConstants.LOCATION_DATA_EXTRA, mLocation);
// Start the service. If the service isn't already running, it is instantiated and started
// (creating a process for it if needed); if it is running then it remains running. The
// service kills itself automatically once all intents are processed.
startService(intent);
}
private void openAutocompleteActivity() {
try {
// The autocomplete activity requires Google Play Services to be available. The intent
// builder checks this and throws an exception if it is not the case.
Intent intent = new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_FULLSCREEN)
.build(this);
startActivityForResult(intent, REQUEST_CODE_AUTOCOMPLETE);
} catch (GooglePlayServicesRepairableException e) {
// Indicates that Google Play Services is either not installed or not up to date. Prompt
// the user to correct the issue.
GoogleApiAvailability.getInstance().getErrorDialog(this, e.getConnectionStatusCode(),
0 /* requestCode */).show();
} catch (GooglePlayServicesNotAvailableException e) {
// Indicates that Google Play Services is not available and the problem is not easily
// resolvable.
String message = "Google Play Services is not available: " +
GoogleApiAvailability.getInstance().getErrorString(e.errorCode);
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
}
}
/**
* Called after the autocomplete activity has finished to return its result.
*/
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Check that the result was from the autocomplete widget.
if (requestCode == REQUEST_CODE_AUTOCOMPLETE) {
if (resultCode == RESULT_OK) {
// Get the user's selected place from the Intent.
Place place = PlaceAutocomplete.getPlace(mContext, data);
// TODO call location based filter
LatLng latLong;
latLong = place.getLatLng();
//mLocationText.setText(place.getName() + "");
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(latLong).zoom(15).tilt(70).build();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
return;
}
mMap.setMyLocationEnabled(true);
mMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
}
} else if (resultCode == PlaceAutocomplete.RESULT_ERROR) {
Status status = PlaceAutocomplete.getStatus(mContext, data);
} else if (resultCode == RESULT_CANCELED) {
// Indicates that the activity closed before a selection was made. For example if
// the user pressed the back button.
}
}
}
4.) Changes in Manifest
provide all the necessary internet permissions.
Don't forget to add these two things
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="Your google map api key" />
and,
<service
android:name=".FetchAddressIntentService"
android:exported="false" />
That's it, You're done with the code part!!
Just Run it..
Utilize draggable markers, via the onMarkerDragEnd method
#Override
public void onMarkerDragEnd(Marker marker) {
// TODO Auto-generated method stub
}
Within that method you could do something like
LatLng position = marker.getPosition();
double latitude = position.latitude;
double longitude = position.longitude;
There you have it. .........
#Override
public void onMapReady(GoogleMap googleMap)
{
mMap = googleMap;
mMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener()
{
#Override
public void onCameraChange(CameraPosition cameraPosition)
{
mCenterLatLong = cameraPosition.target;
mMap.clear();
try
{
Location mLocation = new Location("");
mLocation.setLatitude(mCenterLatLong.latitude);
mLocation.setLongitude(mCenterLatLong.longitude);
startIntentService(mLocation);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
}

Categories

Resources