I have a very frustrating error that I cannot explain. I created an Android application that uses Android AppCompat to make it compatible with older versions. Here is my main activity layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:orientation="vertical"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.music.urgames.geo.MainActivity">
<!-- Line with Latitude and Longitude -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#color/colorPrimaryDark"
android:paddingTop="5dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingBottom="5dp">
<!--Latitude-->
<TextView
android:id="#+id/lat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="Lat: " />
<!--Longitude-->
<TextView
android:id="#+id/lon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="Long: " />
</LinearLayout>
<!--GoogleMap fragment-->
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.google.android.gms.maps.MapFragment"
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
My Main Class
public class MainActivity extends FragmentActivity
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(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
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();
}
// 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);
}
}
private Marker geoFenceMarker;
private void markerForGeofence(LatLng latLng) {
Log.i(TAG, "markerForGeofence("+latLng+")");
String title = latLng.latitude + ", " + latLng.longitude;
// Define marker options
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE))
.title(title);
if ( map!=null ) {
// Remove last geoFenceMarker
if (geoFenceMarker != null)
geoFenceMarker.remove();
geoFenceMarker = map.addMarker(markerOptions);
}
}
// Start Geofence creation process
private void startGeofence() {
Log.i(TAG, "startGeofence()");
if( geoFenceMarker != null ) {
Geofence geofence = createGeofence( geoFenceMarker.getPosition(), GEOFENCE_RADIUS );
GeofencingRequest geofenceRequest = createGeofenceRequest( geofence );
addGeofence( geofenceRequest );
} else {
Log.e(TAG, "Geofence marker is null");
}
}
private static final long GEO_DURATION = 60 * 60 * 1000;
private static final String GEOFENCE_REQ_ID = "My Geofence";
private static final float GEOFENCE_RADIUS = 500.0f; // in meters
// Create a Geofence
private Geofence createGeofence( LatLng latLng, float radius ) {
Log.d(TAG, "createGeofence");
return new Geofence.Builder()
.setRequestId(GEOFENCE_REQ_ID)
.setCircularRegion( latLng.latitude, latLng.longitude, radius)
.setExpirationDuration( GEO_DURATION )
.setTransitionTypes( Geofence.GEOFENCE_TRANSITION_ENTER
| 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 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() ) {
saveGeofence();
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( geoFenceMarker.getPosition())
.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() {
Log.d(TAG, "recoverGeofenceMarker");
SharedPreferences sharedPref = getPreferences( Context.MODE_PRIVATE );
if ( sharedPref.contains( KEY_GEOFENCE_LAT ) && sharedPref.contains( KEY_GEOFENCE_LON )) {
double lat = Double.longBitsToDouble( sharedPref.getLong( KEY_GEOFENCE_LAT, -1 ));
double lon = Double.longBitsToDouble( sharedPref.getLong( KEY_GEOFENCE_LON, -1 ));
LatLng latLng = new LatLng( lat, lon );
markerForGeofence(latLng);
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()");
if ( geoFenceMarker != null)
geoFenceMarker.remove();
if ( geoFenceLimits != null )
geoFenceLimits.remove();
}
}
<!--GoogleMap fragment-->
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.google.android.gms.maps.MapFragment"
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
The error I am getting is
03-13 18:00:04.105 16410-16410/com.music.urgames.geo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.music.urgames.geo, PID: 16410
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.music.urgames.geo/com.music.urgames.geo.MainActivity}: android.view.InflateException: Binary XML file line #44: Binary XML file line #44: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2423)
The geo Translation class
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_ENTER ||
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_ENTER )
status = "Entering ";
else 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 = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
stackBuilder = TaskStackBuilder.create(this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
stackBuilder.addParentStack(MainActivity.class);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
stackBuilder.addNextIntent(notificationIntent);
}
PendingIntent notificationPendingIntent = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
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) {
android.support.v4.app.NotificationCompat.Builder notificationBuilder = new android.support.v4.app.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.";
}
}
}
Looks like you have two LinearLayouts but you are only closing one
Related
I am trying to locate the user's location once, so I am using the merged location provider. The problem I have is that when I use it for the first time I locate the location but then if I turn off the GPS and press the text to locate again, it does not locate me again. What could be the problem that makes it work the first time? Many thanks.
public class DatosUbicacion extends Fragment {
private TextView tvLocalizar;
private FusedLocationProviderClient proveedor;
private LocationManager locationManager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View vista = inflater.inflate(R.layout.fragment_ubicacion, container, false);
ids(vista);
locationManager=()requireActivity().getSystemService(Context.Location_Service);
proveedor = LocationServices.getFusedLocationProviderClient(getActivity());
tvLocalizar.setOnClickListener(v -> permiso);
return vista;
private void permiso() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(requireActivity(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
obtenerUbicacion();
} else if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
dialogo();
} else if (!shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
dialogoConfiguracion();
} else {
dialogo();
}
} else {
obtenerUbicacion();
}
}
#SuppressLint("MissingPermission")
public void obtenerUbicacion() {
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(1000);
locationRequest.setWaitForAccurateLocation(true);
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
proveedor.getLastLocation().addOnSuccessListener(location -> {
if (location != null) {
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
Log.d("UBICACION", location.getLatitude() + "" + location.getLongitude());
} else {
proveedor.requestLocationUpdates(locationRequest, miUbicacionCallback, Looper.myLooper());
}
}).addOnFailureListener(e -> {
Toast.makeText(requireContext(), "error" + e.getMessage(), Toast.LENGTH_SHORT).show();
});
} else {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
Task<LocationSettingsResponse> tarea = LocationServices.getSettingsClient(requireContext()).checkLocationSettings(builder.build());
tarea.addOnFailureListener(e -> {
if (e instanceof ResolvableApiException) {
try {
IntentSenderRequest intentSenderRequest = new IntentSenderRequest.Builder(((ResolvableApiException) e).getResolution()).build();
contratoGps.launch(intentSenderRequest);
} catch (Throwable trowable) {
Log.e("gps", trowable.getMessage());
}
}
});
}
}
private LocationCallback miUbicacionCallback = new LocationCallback() {
#Override
public void onLocationResult(#NonNull LocationResult resultado) {
if (resultado == null) {
return;
}
Log.d("UBICACION", resultado.getLastLocation().getLatitude() + “ ” + resultado.getLastLocation().getLongitude());
};
private void dialogo(){
Dialog dialog = new Dialog(requireContext(), R.style.Theme_AppCompat_Light_Dialog_Alert);
dialog.setContentView(R.layout.dialog_camara);
Objects.requireNonNull(dialog.getWindow()).setBackgroundDrawableResource(android.R.color.transparent);
Button btnOk = dialog.findViewById(R.id.btn_ok);
Button btnCancelar = dialog.findViewById(R.id.btn_cancelar);
TextView permiso = dialog.findViewById(R.id.tv_permiso);
dialog.show();
btnOk.setOnClickListener(v -> {
this.contratoUbicacion.launch(Manifest.permission.ACCESS_FINE_LOCATION);
dialog.dismiss();
});
btnCancelar.setOnClickListener(v -> dialog.dismiss());
dialog.setCancelable(false);
}
private void dialogoConfiguracion() {
Dialog dialog = new Dialog(requireContext(), R.style.Theme_AppCompat_Light_Dialog_Alert);
dialog.setContentView(R.layout.dialog_ubicacion);
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
Button ok = dialog.findViewById(R.id.btn_ok);
Button cancel = dialog.findViewById(R.id.btn_cancelar);
TextView permiso = dialog.findViewById(R.id.tv_permiso);
dialog.show();
ok.setOnClickListener(v -> {
configuracion();
});
cancel.setOnClickListener(v -> dialog.dismiss());
dialog.setCancelable(false);
}
private void configuracion() {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", requireActivity().getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
ActivityResultLauncher<String> contratoUbicacion = registerForActivityResult(new ActivityResultContracts.RequestPermission(), resultado -> {
if (resultado) {
obtenerUbicacion();
} else {
Toast.makeText(requireContext(), "se necesitan permisos de ubicacion", Toast.LENGTH_SHORT).show();
}
});
ActivityResultLauncher<IntentSenderRequest> contratoGps = registerForActivityResult(new ActivityResultContracts.StartIntentSenderForResult(), resultado -> {
if (result.getResultCode() == Activity.RESULT_OK) {
obtenerUbicacion();
}
});
private void ids(View vista){
tvLocalizar = vista.findViewById(R.id.tv_localizar);
}
}
Xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/cl_ubicacion"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="#color/plataforma"
tools:context=".preusuario.registro2.DatosUbicacion">
<TextView
android:id="#+id/tv_localizar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Obtener mi ubicacion actual"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Well, you have checked GPS_PROVIDER but you also need to check LocationManager.NETWORK_PROVIDER. So, you can get location status via Network when GPS is Off.
First of all, you need to check the permmissions and, also request the new permmissions if not granted.
// method to check
// if location is enabled
public boolean isLocationEnabled() {
LocationManager locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
// method to request for permissions
public void requestPermissions() {
ActivityCompat.requestPermissions(FutureClientsMeet.this, new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_ID);
}
In your obtenerUbicacion() use something like below:
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
// check if location is enabled
if (isLocationEnabled()) {
locationProviderClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
Location location = task.getResult();
if (location == null) {
requestNewLocationData();
} else {
CurrentLat = String.valueOf(location.getLatitude());
CurrentLng = String.valueOf(location.getLongitude());
}
}
});
} else {
Toast.makeText(getApplicationContext(), "Please turn on" + " your location...", Toast.LENGTH_LONG).show();
}
} else {
requestPermissions();
}
Then, add requestNewLocationData() and LocationCallback to update the new location.
public LocationCallback mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
Location mLastLocation = locationResult.getLastLocation();
if (mLastLocation != null) {
//here you can get new location
Lat = mLastLocation.getLatitude();
Lng = mLastLocation.getLongitude();
}
}
};
#SuppressLint("MissingPermission")
public void requestNewLocationData() {
// Initializing LocationRequest
// object with appropriate methods
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(5);
mLocationRequest.setFastestInterval(0);
mLocationRequest.setNumUpdates(1);
// setting LocationRequest
// on FusedLocationClient
locationProviderClient = LocationServices.getFusedLocationProviderClient(getApplicationContext());
locationProviderClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}
I am a novice in Android development. I tried to develop an Android app which will show a Google Map with a fixed Geofence Area and the current location of the concerned person. Whenever he / she leaves or enters that particular geofence region a notification will be shown. After searching various forums and stackoverflow for ideas I somehow manged to develop the application. But I am now facing the problem that it shows the notfication about the Entry / exit of Geofence area only when the app is open. If it is minimized and swiped out it doesn't run in background. I used GeofenceTransitionsJobIntentService for geofence transition changes. I think that I had done some silly mistake so it's not working in background. So please help me out from this problem.
Here's the full code. Any ideas where I'm going wrong ? Thanks in Advance
My codes:
GeofenceTransitionsJobIntentService.Java
public class GeofenceTransitionsJobIntentService extends JobIntentService {
private static final int JOB_ID = 573;
private static final String TAG = "GeofenceTransitionsIS";
private static final String CHANNEL_ID = "channel_01";
/**
* Convenience method for enqueuing work in to this service.
*/
public static void enqueueWork(Context context, Intent intent) {
enqueueWork(context, GeofenceTransitionsJobIntentService.class, JOB_ID, intent);
}
/**
* Handles incoming intents.
* #param intent sent by Location Services. This Intent is provided to Location
* Services (inside a PendingIntent) when addGeofences() is called.
*/
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
protected void onHandleWork(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = GeofenceErrorMessages.getErrorString(this,
geofencingEvent.getErrorCode());
Log.e(TAG, errorMessage);
return;
}
// Get the transition type.
int geofenceTransition = geofencingEvent.getGeofenceTransition();
// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
// Get the geofences that were triggered. A single event can trigger multiple geofences.
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
// Get the transition details as a String.
String geofenceTransitionDetails = getGeofenceTransitionDetails(geofenceTransition,
triggeringGeofences);
// Send notification and log the transition details.
sendNotification(geofenceTransitionDetails);
Log.i(TAG, geofenceTransitionDetails);
} else {
// Log the error.
Log.e(TAG, getString(R.string.geofence_transition_invalid_type, geofenceTransition));
}
}
/**
* Gets transition details and returns them as a formatted string.
*
* #param geofenceTransition The ID of the geofence transition.
* #param triggeringGeofences The geofence(s) triggered.
* #return The transition details formatted as String.
*/
private String getGeofenceTransitionDetails(
int geofenceTransition,
List<Geofence> triggeringGeofences) {
String geofenceTransitionString = getTransitionString(geofenceTransition);
// Get the Ids of each geofence that was triggered.
ArrayList<String> triggeringGeofencesIdsList = new ArrayList<>();
for (Geofence geofence : triggeringGeofences) {
triggeringGeofencesIdsList.add(geofence.getRequestId());
}
String triggeringGeofencesIdsString = TextUtils.join(", ", triggeringGeofencesIdsList);
return geofenceTransitionString + ": " + triggeringGeofencesIdsString;
}
/**
* Posts a notification in the notification bar when a transition is detected.
* If the user clicks the notification, control goes to the MainActivity.
*/
private void sendNotification(String notificationDetails) {
// Get an instance of the Notification manager
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Android O requires a Notification Channel.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.app_name);
// Create the channel for the notification
NotificationChannel mChannel =
new NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH);
// Set the Notification Channel for the Notification Manager.
mNotificationManager.createNotificationChannel(mChannel);
}
// Create an explicit content Intent that starts the main Activity.
Intent notificationIntent = new Intent(getApplicationContext(), MapsActivity.class);
// Construct a task stack.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Add the main Activity to the task stack as the parent.
stackBuilder.addParentStack(MapsActivity.class);
// Push the content Intent onto the stack.
stackBuilder.addNextIntent(notificationIntent);
// Get a PendingIntent containing the entire back stack.
PendingIntent notificationPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Get a notification builder that's compatible with platform versions >= 4
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
// Define the notification settings.
builder.setSmallIcon(R.drawable.ic_launcher)
// In a real app, you may want to use a library like Volley
// to decode the Bitmap.
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher))
.setColor(Color.RED)
.setOngoing(false)
.setPriority(Notification.PRIORITY_DEFAULT)
.setContentTitle(notificationDetails)
.setTicker(notificationDetails)
.setContentText(getString(R.string.geofence_transition_notification_text))
.setContentIntent(notificationPendingIntent);
// Set the Channel ID for Android O.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(CHANNEL_ID); // Channel ID
}
// Dismiss notification once the user touches it.
builder.setAutoCancel(true);
// Issue the notification
mNotificationManager.notify(0, builder.build());
}
/**
* Maps geofence transition types to their human-readable equivalents.
*
* #param transitionType A transition type constant defined in Geofence
* #return A String indicating the type of transition
*/
private String getTransitionString(int transitionType) {
switch (transitionType) {
case Geofence.GEOFENCE_TRANSITION_ENTER:
return getString(R.string.geofence_transition_entered);
case Geofence.GEOFENCE_TRANSITION_EXIT:
return getString(R.string.geofence_transition_exited);
default:
return getString(R.string.unknown_geofence_transition);
}
}
}
GeofenceBroadcastReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class GeofenceBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Enqueues a JobIntentService passing the context and intent as parameters
GeofenceTransitionsJobIntentService.enqueueWork(context, intent);
}
}
MapsActivity.java
public class MapsActivity extends AppCompatActivity implements
GoogleMap.OnMyLocationButtonClickListener, OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener, OnCompleteListener<Void>
{
private static final String TAG = MapsActivity.class.getSimpleName();
static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
static final int RADIUS = 500;
private LocationManager locationManager;
private String provider;
private Location location;
private GoogleMap mMap;
private Circle circle;
private PendingIntent geofencePendingIntent;
private GeofencingClient geofencingClient;
private GoogleApiClient googleApiClient;
private boolean isContinue = false;
private boolean isGPS = false;
private LocationRequest locationRequest;
private final int UPDATE_INTERVAL = 2 * 60 * 1000;
private final int FASTEST_INTERVAL = 20 * 1000;
private final int NOTIFICATION_RESPONSIVENESS_TIME = 10000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
geofencingClient = LocationServices.getGeofencingClient(this);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
createGoogleApi();
new GpsUtils(this).turnGPSOn(new GpsUtils.onGpsListener() {
#Override
public void gpsStatus(boolean isGPSEnable) {
// turn on GPS
isGPS = isGPSEnable;
}
});
if (!checkPermissions()) {
requestPermissions();
}
}
#Override
public void onMapReady(GoogleMap googleMap)
{
Log.d(TAG,"onMapReady()");
mMap = googleMap;
mMap.setOnMyLocationButtonClickListener(this);
addGeofence(getMyLocation(), RADIUS);
drawCircle(getMyLocation(), RADIUS);
markerForGeofence(getMyLocation());
}
private void createGoogleApi()
{
if(googleApiClient==null)
{
googleApiClient=new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}
#Override
public void onStart() {
super.onStart();
googleApiClient.connect();
if (checkPermissions()) {
// removeGeofence();
addGeofence(getMyLocation(), RADIUS);
// drawCircle(getMyLocation(), RADIUS);
// markerForGeofence(getMyLocation());
} else {
requestPermissions();
}
}
#Override
public void onStop() {
super.onStop();
googleApiClient.disconnect();
}
#Override
public void onConnected(#Nullable Bundle bundle)
{
Log.i(TAG, "onConnected()");
getLastKnownLocation();
addGeofence(getMyLocation(), RADIUS);
drawCircle(getMyLocation(), RADIUS);
markerForGeofence(getMyLocation());
}
#Override
public void onConnectionSuspended(int i)
{
Log.w(TAG, "onConnectionSuspended()");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult)
{
Log.w(TAG, "onConnectionFailed()");
}
// Get last known location
private void getLastKnownLocation() {
Log.d(TAG, "getLastKnownLocation()");
if ( checkPermissions() ) {
location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if ( location != null ) {
Log.i(TAG, "LasKnown location. " +
"Long: " + location.getLongitude() +
" | Lat: " + location.getLatitude());
writeLocation();
startLocationUpdates();
} else {
Log.w(TAG, "No location retrieved yet");
startLocationUpdates();
}
}
else requestPermissions();
}
// 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 ( checkPermissions() )
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged ["+location+"]");
location = location;
writeActualLocation(location);
addGeofence(getMyLocation(), RADIUS);
}
// Write location coordinates on UI
private void writeActualLocation(Location location) {
markerLocation(new LatLng(location.getLatitude(), location.getLongitude()));
}
private void writeLocation() {
writeActualLocation(location);
}
private Marker locationMarker;
// Create a Location Marker
private void markerLocation(LatLng latLng) {
Log.i(TAG, "markerLocation("+latLng+")");
String title = "Your Current Location("+latLng.latitude + ", " + latLng.longitude+")";
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.title(title);
if ( mMap!=null ) {
// Remove the anterior marker
if ( locationMarker != null )
locationMarker.remove();
locationMarker = mMap.addMarker(markerOptions);
float zoom = 14f;
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, zoom);
mMap.animateCamera(cameraUpdate);
}
}
private Marker geoFenceMarker;
// Create a marker for the geofence creation
private void markerForGeofence(LatLng latLng) {
Log.i(TAG, "markerForGeofence("+latLng+")");
String title = "Your Geofence Area("+latLng.latitude + ", " + latLng.longitude+")";
// Define marker options
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE))
.title(title);
if ( mMap!=null ) {
// Remove last geoFenceMarker
if (geoFenceMarker != null)
geoFenceMarker.remove();
geoFenceMarker = mMap.addMarker(markerOptions);
}
}
/**
* Return the current state of the permissions needed.
*/
private boolean checkPermissions() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED )
{
return false;
}
else
{
return true;
}
}
private void requestPermissions() {
boolean shouldProvideRationale =
ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION);
boolean shouldProvideRationale1 =
ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION);
// Provide an additional rationale to the user. This would happen if the user denied the
// request previously, but didn't check the "Don't ask again" checkbox.
if (shouldProvideRationale || shouldProvideRationale1) {
Log.i(TAG, "Displaying permission rationale to provide additional context.");
Snackbar.make(
findViewById(R.id.activity_main),
R.string.permission_rationale,
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.ok, new View.OnClickListener() {
#Override
public void onClick(View view) {
// Request permission
ActivityCompat.requestPermissions(MapsActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
})
.show();
} else {
Log.i(TAG, "Requesting permission");
// Request permission. It's possible this can be auto answered if device policy
// sets the permission in a given state or the user denied the permission
// previously and checked "Never ask again".
ActivityCompat.requestPermissions(MapsActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_BACKGROUND_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
}
// For creating GeoFence.
private Geofence createGeofence(LatLng latLng, int radiusMeters) {
return new Geofence.Builder()
// Set the request ID of the geofence. This is a string to identify this
// geofence.
.setRequestId("1")
.setCircularRegion(latLng.latitude, latLng.longitude, radiusMeters)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setNotificationResponsiveness(NOTIFICATION_RESPONSIVENESS_TIME)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
.build();
}
private GeofencingRequest getGeofencingRequest(LatLng latLng, int radiusMeters) {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_EXIT);
builder.addGeofence(createGeofence(latLng, radiusMeters));
return builder.build();
}
/**
* Callback received when a permissions request has been completed.
*/
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
Log.i(TAG, "onRequestPermissionResult");
if (requestCode == MY_PERMISSIONS_REQUEST_LOCATION) {
if (grantResults.length <= 0) {
// If user interaction was interrupted, the permission request is cancelled and you
// receive empty arrays.
Log.i(TAG, "User interaction was cancelled.");
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED && grantResults[2] == PackageManager.PERMISSION_GRANTED) {
// Permission was granted.
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED) {
getLastKnownLocation();
}
} else {
// Permission denied.
// setButtonsState(false);
Snackbar.make(
findViewById(R.id.activity_main),
R.string.permission_denied_explanation,
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.settings, new View.OnClickListener() {
#Override
public void onClick(View view) {
// Build intent that displays the App settings screen.
Intent intent = new Intent();
intent.setAction(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package",
BuildConfig.APPLICATION_ID, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}).show();
}
}
}
#Override
public boolean onMyLocationButtonClick() {
// Return false so that we don't consume the event and the default behavior still occurs
// (the camera animates to the user's current position).
/* if (circle != null)
circle.remove();
drawCircle(getMyLocation(), RADIUS);*/
return false;
}
private void drawCircle(LatLng latLng, int radius) {
circle = mMap.addCircle(new CircleOptions()
.center(latLng)
.radius(radius)
.strokeWidth(0f)
.fillColor(0x55FF0000));
}
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (geofencePendingIntent != null) {
return geofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceBroadcastReceiver.class);
geofencePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return geofencePendingIntent;
}
private void removeGeofence() {
geofencingClient.removeGeofences(getGeofencePendingIntent()).addOnCompleteListener(this);
}
private void addGeofence(LatLng latLng, int radiusMeters) {
geofencingClient.addGeofences(getGeofencingRequest(latLng, radiusMeters), getGeofencePendingIntent())
.addOnCompleteListener(this);
}
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
} else {
}
}
}
Run Foreground service, when App goes to background. This solves your problem.
On Android 8.0 (API level 26) and higher, if an app is running in the background while monitoring a geofence, then the device responds to geofencing events every couple of minutes. To learn how to adapt your app to these response limits, see Background Location Limits.
You might need to run a sticky foreground service for your app to be running continuously.
My geofence is trigering actions once when i open map. Basically i want it to show a toast and make a button visible once i enter a circle and show a toast and make a button invisible once i leave the circle. I can't find a solution so maybe you guys can help.
Here's my code:
public class MapActivity extends AppCompatActivity implements OnMapReadyCallback, Geofence {
#Override
public void onMapReady(GoogleMap googleMap) {
Toast.makeText(this, "Map is Ready", Toast.LENGTH_SHORT).show();
Log.d(TAG, "onMapReady: Map is ready");
mMap = googleMap;
if (mLocationPermissionsGranted) {
try {
boolean success = googleMap.setMapStyle(
MapStyleOptions.loadRawResourceStyle(
this, R.raw.mapstyle));
if (!success) {
Log.e(TAG, "Style parsing failed.");
}
} catch (Resources.NotFoundException e) {
Log.e(TAG, "Can't find style. Error: ", e);
}
getDeviceLocation();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mMap.setMyLocationEnabled(true);
}
for (LatLng latLng : InfoArea) {
mMap.addCircle(new CircleOptions()
.center(latLng)
.radius(5)
.strokeColor(0xffff0000)
.fillColor(0x44ff0000)
.strokeWidth(1));
}
Geofencesetup(); //calling geofence setup
}
private static final String TAG = "MapActivity";
private static final String FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
private static final String COURSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
private static final int PERMISSION_CODE = 1234;
private static final float DEFAULT_ZOOM = 15f;
//vars
private Boolean mLocationPermissionsGranted = false;
private GoogleMap mMap;
private FusedLocationProviderClient mFusedLocationProviderClient;
private List<LatLng> InfoArea;
private String GEOFENCE_KEY = "451";
PendingIntent pendingIntent;
GeofencingClient geofencingClient;
Button infobut;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
getLocationPermission();
pendingIntent = PendingIntent.getBroadcast(this,0,
new Intent(".ACTION_RECEIVE_GEOFENCE"),PendingIntent.FLAG_UPDATE_CURRENT);
geofencingClient = LocationServices.getGeofencingClient(this);
infobut = findViewById(R.id.Speak);
}
private void getDeviceLocation() {
Log.d(TAG, "getDeviceLocation: getting the current location");
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
try {
if (mLocationPermissionsGranted) {
final Task location = mFusedLocationProviderClient.getLastLocation();
location.addOnCompleteListener(new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
if (task.isSuccessful()) {
Log.d(TAG, "onComplete: found location!");
final Location currentLocation = (Location) task.getResult();
moveCamera(new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()),
DEFAULT_ZOOM);
} else {
Log.d(TAG, "onComplete: current location is null");
Toast.makeText(MapActivity.this, "unable to get current location", Toast.LENGTH_SHORT).show();
}
}
});
}
} catch (SecurityException e) {
Log.e(TAG, "getDeviceLocation: SecurityException: " + e.getMessage());
}
}
private void moveCamera(LatLng latLng, float zoom) {
Log.d(TAG, "moveCamera: moving camera to: lat: " + latLng.latitude + ", lng: " + latLng.longitude);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoom));
}
private void initMap() {
Log.d(TAG, "initMap: initializing map");
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(MapActivity.this);
initArea();
}
private void initArea() {
InfoArea = new ArrayList<>();
InfoArea.add(new LatLng(54.021410, 23.954885));
}
private void Geofencesetup(){ //Part of the problem
Geofence.Builder geofencecreator = new Geofence.Builder();
geofencecreator.setRequestId(GEOFENCE_KEY);
geofencecreator.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT);
geofencecreator.setCircularRegion(54.021410, 23.954885, 10); //latlng and radius of the circle
geofencecreator.setExpirationDuration(Geofence.NEVER_EXPIRE);
GeofencingRequest.Builder geoBuilder = new GeofencingRequest.Builder();
geoBuilder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER | GeofencingRequest.INITIAL_TRIGGER_EXIT);
geoBuilder.addGeofence(geofencecreator.build());
Task task = geofencingClient.addGeofences(geoBuilder.build(), pendingIntent);
task.addOnSuccessListener(new OnSuccessListener() {
#Override
public void onSuccess(Object o) {
Log.i(TAG,"You're inside the zone");
activityinsidecircleMaker();
}
});
task.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.i(TAG,"You're outside the zone");
activityoutsidecircleMaker();
}
});
} //................................................................................
private void activityinsidecircleMaker(){ //the toast and the button i want it to show when user is inside a circle
Toast.makeText(this,"You're inside a circle",Toast.LENGTH_SHORT).show();
infobut.setVisibility(View.VISIBLE);
}
private void activityoutsidecircleMaker(){ //the toast and the button i want it to show when user is outside a circle(in this case button should become invisible)
Toast.makeText(this,"You are now outside the circle",Toast.LENGTH_SHORT).show();
infobut.setVisibility(View.INVISIBLE);
}//.............................................................................................
private void getLocationPermission() {
Log.d(TAG, "getLocationPermission: getting location permissions");
String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION};
if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
COURSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mLocationPermissionsGranted = true;
initMap();
} else {
ActivityCompat.requestPermissions(this,
permissions,
PERMISSION_CODE);
}
} else {
ActivityCompat.requestPermissions(this,
permissions,
PERMISSION_CODE);
}
}
#Override
public String getRequestId() {
return null;
}
The actions that i want my program to do when user is inside or outside the circle are marked like this: //......... , so you guys could see it better. Also i think that is where the problem actually is i just can't find a way to solve it
I had created a tracking apps using Firebase. The apps have 2 type user log in user's (driver & parent) with different layout and different task.
Driver user will updated their location on Firebase database continuously into their own root of their tree.
Parent user will retrieve the data continuously to be shown on map layout and geofence layout as a latlng for the geofence coordinate.
My problem is on the geofence activity. The button 'Start Geofence' will toast " Geofence Successfully Added " and it is done perfectly. But when I click the button, its seems to get the value of latlng only static position while the data are continuously updated according to the Driver user's location.
I have done testing on mock situation. My friends log in as driver and drive from location A to location B (my location) and I log in as parent to track my friends location. When I click 'Start Geofence' button, the text " Geofence Successfully Added " are successfully toasted. But my geofence alarm not trigerred when my friends are near to location B. But when I click again, the alarm are triggered.
I assume that my geofence only take the CURRENT latlng data when I press/click the button 'Start Geofence', not continuously get updated latlng data from Firebase Database.
Can someone explain me why?
I need to use the location of the driver as my geofence coordinate, so it will be a moving geofence.
Here my ParentsActivity.java
public class ParentActivity extends AppCompatActivity implements ValueEventListener, GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener, ResultCallback<Status> {
private static final String TAG = "ParentActivity";
private Button btnTrack, btnGeofence, signout;
private FirebaseAuth auth;
private DatabaseReference databaseReference;
private GoogleApiClient googleApiClient;
private Location lastLocation;
double lat;
double lng;
LatLng latLng;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Get Firebase auth instance
auth = FirebaseAuth.getInstance();
if (auth.getCurrentUser() == null) {
startActivity(new Intent(ParentActivity.this, LoginActivity.class));
finish();
}
databaseReference = FirebaseDatabase.getInstance().getReference().child("yKlWu19vhqQXfL2tDlBNfMSduMe2");
// set the view now
setContentView(R.layout.activity_parent);
btnTrack = (Button) findViewById(R.id.btn_track);
btnGeofence = (Button) findViewById(R.id.btn_geo);
signout = (Button) findViewById(R.id.sign_out);
btnTrack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(ParentActivity.this, MapsActivity.class));
}
});
signout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
auth.signOut();
finish();
startActivity(new Intent(ParentActivity.this, LoginActivity.class));
}
});
btnGeofence.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startGeofence();
}
});
createGoogleApi();
}
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
lat = dataSnapshot.child("location/latitude").getValue(Double.class);
lng = dataSnapshot.child("location/longitude").getValue(Double.class);
latLng = new LatLng(lat, lng);
}
// 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
public void onCancelled(DatabaseError databaseError) {
}
#Override
protected void onStart() {
super.onStart();
databaseReference.addValueEventListener(this);
googleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
googleApiClient.disconnect();
}
// GoogleApiClient.ConnectionCallbacks connected
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.i(TAG, "onConnected()");
getLastKnownLocation();
}
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());
startLocationUpdates();
} else {
Log.w(TAG, "No location retrieved yet");
startLocationUpdates();
}
}
else askPermission();
}
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 * 60;
private final int FASTEST_INTERVAL = 1000 * 30;
// 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;
}
// 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, android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED );
}
// Asks for permission
private void askPermission() {
Log.d(TAG, "askPermission()");
ActivityCompat.requestPermissions(
this,
new String[] { android.Manifest.permission.ACCESS_FINE_LOCATION },
100
);
}
// 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 100: {
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()");
}
// 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()");
}
private static final long GEO_DURATION = 60 * 60 * 1000;
private static final String GEOFENCE_REQ_ID = "My Geofence";
private static final float GEOFENCE_RADIUS_IN_METERS = 300; // in meters
// Create a Geofence
private Geofence createGeofence(double latitude, double longitude, float radius ) {
Log.d(TAG, "createGeofence");
return new Geofence.Builder()
.setRequestId(GEOFENCE_REQ_ID)
.setCircularRegion( latitude, longitude, radius)
.setExpirationDuration( GEO_DURATION )
.setTransitionTypes( Geofence.GEOFENCE_TRANSITION_ENTER
| 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 final int GEOFENCE_REQ_CODE = 0;
private PendingIntent createGeofencePendingIntent() {
Intent intent = new Intent( this, GeofenceTransitionIntentService.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() ) {
Toast.makeText(getApplicationContext(), "GEOFENCE SUCCESSFUL ADDED", Toast.LENGTH_SHORT).show();
return;
} else {
Toast.makeText(getApplicationContext(), "ERROR", Toast.LENGTH_SHORT).show();
return;// inform about fail
}
}
// Start Geofence creation process
private void startGeofence() {
Log.i(TAG, "startGeofence()");
Geofence geofence = createGeofence(lat, lng, GEOFENCE_RADIUS_IN_METERS );
GeofencingRequest geofenceRequest = createGeofenceRequest( geofence );
addGeofence( geofenceRequest );
}
Here my GeofenceIntentService.java
public class GeofenceTransitionIntentService extends IntentService {
private static final String TAG = "GeofenceTransitionIS";
public GeofenceTransitionIntentService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
Log.i(TAG, "onHandleIntent");
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
//String errorMessage = GeofenceErrorMessages.getErrorString(this,
// geofencingEvent.getErrorCode());
Log.e(TAG, "Goefencing Error " + geofencingEvent.getErrorCode());
return;
}
// Get the transition type.
int geofenceTransition = geofencingEvent.getGeofenceTransition();
Log.i(TAG, "geofenceTransition = " + geofenceTransition + " Enter : " + Geofence.GEOFENCE_TRANSITION_ENTER + "Exit : " + Geofence.GEOFENCE_TRANSITION_EXIT);
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geofenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL){
showNotification("Entered", "Entered the Location");
playAlarm();
Toast.makeText(getApplicationContext(), " Van Nearby", Toast.LENGTH_SHORT).show();
}
else if(geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
Log.i(TAG, "Showing Notification...");
showNotification("Exited", "Exited the Location");
Toast.makeText(getApplicationContext(), "Van Exited", Toast.LENGTH_SHORT).show();
} else {
// Log the error.
showNotification("Error", "Error");
Log.e(TAG, "Error ");
}
}
public void showNotification(String text, String bigText) {
// 1. Create a NotificationManager
NotificationManager notificationManager =
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
// 2. Create a PendingIntent for AllGeofencesActivity
Intent intent = new Intent(getApplicationContext(), ParentActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// 3. Create and send a notification
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.icon_a)
.setContentTitle("Notification!")
.setContentText(text)
.setContentIntent(pendingNotificationIntent)
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND)
.setStyle(new NotificationCompat.BigTextStyle().bigText(bigText))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.build();
notificationManager.notify(0, notification);
}
private void playAlarm() {
Intent i = new Intent(getBaseContext(), AlarmActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
and here my AlarmActivity.java
public class AlarmActivity extends Activity {
private MediaPlayer mMediaPlayer;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
this.setFinishOnTouchOutside(false);
setContentView(R.layout.activity_alarm);
playAlarm();
}
private void playAlarm() {
mMediaPlayer = MediaPlayer.create(getApplicationContext(),
R.raw.intruder_alarm);
mMediaPlayer.setLooping(true);
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer arg0) {
mMediaPlayer.start();
}
});
}
public void dismissAlarm(View view) {
mMediaPlayer.release();
this.finish();
}
I'm trying to get latlong using only GPS. If I use NetworkManager I'm getting location latlong but if use gps, GPS_PROVIDER I'm getting null location.
Please tell me how to get gps location using GPS_PROVIDER.
Code.
public class GPSTracker extends Service implements LocationListener {
private final Context mContext;
// flag for GPS status
boolean isGPSEnabled = false;
// flag for network status
boolean isNetworkEnabled = false;
// flag for GPS status
boolean canGetLocation = false;
Location location; // location
double latitude; // latitude
double longitude; // longitude
// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute
// Declaring a Location Manager
protected LocationManager locationManager;
public GPSTracker(Context context) {
this.mContext = context;
getLocation();
}
public Location getLocation() {
try {
locationManager = (LocationManager) mContext
.getSystemService(LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
/*isNetworkEnabled = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
*/
if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled
} else {
this.canGetLocation = true;
/*if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}*/
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
}
return location;
}
/**
* Stop using GPS listener Calling this function will stop using GPS in your
* app.
* */
public void stopUsingGPS() {
if (locationManager != null) {
locationManager.removeUpdates(GPSTracker.this);
}
}
/**
* Function to get latitude
* */
public double getLatitude() {
if (location != null) {
latitude = location.getLatitude();
}
// return latitude
return latitude;
}
/**
* Function to get longitude
* */
public double getLongitude() {
if (location != null) {
longitude = location.getLongitude();
}
// return longitude
return longitude;
}
/**
* Function to check GPS/wifi enabled
*
* #return boolean
* */
public boolean canGetLocation() {
return this.canGetLocation;
}
/**
* Function to show settings alert dialog On pressing Settings button will
* lauch Settings Options
* */
public void showSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
// Setting DialogHelp Title
alertDialog.setTitle("GPS is settings");
// Setting DialogHelp Message
alertDialog
.setMessage("GPS is not enabled. Do you want to go to settings menu?");
// On pressing Settings button
alertDialog.setPositiveButton("Settings",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
#Override
public void onLocationChanged(Location location) {
Log.d("location",location.getLatitude()+" "+location.getLongitude());
float bestAccuracy = -1f;
if (location.getAccuracy() != 0.0f
&& (location.getAccuracy() < bestAccuracy) || bestAccuracy == -1f) {
locationManager.removeUpdates(this);
}
bestAccuracy = location.getAccuracy();
Log.d("location",location.getLatitude()+" "+location.getLongitude());
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
public float getAccurecy()
{
return location.getAccuracy();
}
}
**FusedLocationProviderApi**
public class LocationActivity extends Activity implements
LocationListener,GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "LocationActivity";
private static final long INTERVAL = 1000 * 10;
private static final long FASTEST_INTERVAL = 1000 * 5;
Button btnFusedLocation;
TextView tvLocation;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mCurrentLocation;
String mLastUpdateTime;
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate ...............................");
//show error dialog if GoolglePlayServices not available
if (!isGooglePlayServicesAvailable()) {
finish();
}
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
setContentView(R.layout.activity_main);
tvLocation = (TextView) findViewById(R.id.tvLocation);
btnFusedLocation = (Button) findViewById(R.id.btnShowLocation);
btnFusedLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
updateUI();
}
});
}
#Override
public void onStart() {
super.onStart();
Log.d(TAG, "onStart fired ..............");
mGoogleApiClient.connect();
}
#Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop fired ..............");
mGoogleApiClient.disconnect();
Log.d(TAG, "isConnected ...............: " + mGoogleApiClient.isConnected());
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
return false;
}
}
#Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected - isConnected ...............: " + mGoogleApiClient.isConnected());
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) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "Connection failed: " + connectionResult.toString());
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Firing onLocationChanged..............................................");
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateUI();
}
private void updateUI() {
Log.d(TAG, "UI update initiated .............");
if (null != mCurrentLocation) {
String lat = String.valueOf(mCurrentLocation.getLatitude());
String lng = String.valueOf(mCurrentLocation.getLongitude());
tvLocation.setText("At Time: " + mLastUpdateTime + "\n" +
"Latitude: " + lat + "\n" +
"Longitude: " + lng + "\n" +
"Accuracy: " + mCurrentLocation.getAccuracy() + "\n" +
"Provider: " + mCurrentLocation.getProvider());
} else {
Log.d(TAG, "location is null ...............");
}
}
#Override
protected void onPause() {
super.onPause();
stopLocationUpdates();
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
Log.d(TAG, "Location update stopped .......................");
}
#Override
public void onResume() {
super.onResume();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
Log.d(TAG, "Location update resumed .....................");
}
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".LocationActivity"
android:background="#ffffa6c7">
<TextView
android:text="#string/locationTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textView"
android:layout_centerHorizontal="true" />
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Show Location"
android:id="#+id/btnShowLocation"
android:layout_toEndOf="#+id/textView"
android:layout_marginTop="53dp"
android:layout_below="#+id/textView"
android:layout_alignParentStart="true"
android:layout_centerHorizontal="true"
android:background="#ffff1a7c"
android:textColor="#ffffffff" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/tvLocation"
android:layout_alignParentBottom="true"
android:layout_marginBottom="134dp"
android:layout_alignParentEnd="true" />
</RelativeLayout>