I have a problem with my code which should display the latitude and longitude of the current position. I have tried simply setting the text in TextView object, unfortunately, it displays mentioned values just one time (at the beginning). I would like to ask you how can I change this behavior to have "live" coordinates update.
There is my code
package com.example.currentplacedetailsonmap;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.android.libraries.places.api.Places;
import com.google.android.libraries.places.api.model.Place;
import com.google.android.libraries.places.api.model.PlaceLikelihood;
import com.google.android.libraries.places.api.net.FindCurrentPlaceRequest;
import com.google.android.libraries.places.api.net.FindCurrentPlaceResponse;
import com.google.android.libraries.places.api.net.PlacesClient;
import org.w3c.dom.Text;
import java.util.Arrays;
import java.util.List;
import static com.example.currentplacedetailsonmap.R.id.coordinates;
/**
* An activity that displays a map showing the place at the device's current location.
*/
public class MapsActivityCurrentPlace extends AppCompatActivity
implements OnMapReadyCallback {
private static final String TAG = MapsActivityCurrentPlace.class.getSimpleName();
private GoogleMap map;
// The entry point to the Places API.
private PlacesClient placesClient;
// The entry point to the Fused Location Provider.
private FusedLocationProviderClient fusedLocationProviderClient;
// A default location (Sydney, Australia) and default zoom to use when location permission is
// not granted.
private final LatLng defaultLocation = new LatLng(-33.8523341, 151.2106085);
private static final int DEFAULT_ZOOM = 15;
private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
private boolean locationPermissionGranted;
// The geographical location where the device is currently located. That is, the last-known
// location retrieved by the Fused Location Provider.
private Location lastKnownLocation;
// Keys for storing activity state.
// [START maps_current_place_state_keys]
private static final String KEY_CAMERA_POSITION = "camera_position";
private static final String KEY_LOCATION = "location";
// [END maps_current_place_state_keys]
// Used for selecting the current place.
private static final int M_MAX_ENTRIES = 5;
private String[] likelyPlaceNames;
private String[] likelyPlaceAddresses;
private List[] likelyPlaceAttributions;
private LatLng[] likelyPlaceLatLngs;
// [START maps_current_place_on_create]
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// [START_EXCLUDE silent]
// [START maps_current_place_on_create_save_instance_state]
// Retrieve location and camera position from saved instance state.
if (savedInstanceState != null) {
lastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION);
}
// [END maps_current_place_on_create_save_instance_state]
// [END_EXCLUDE]
// Retrieve the content view that renders the map.
setContentView(R.layout.activity_maps);
// [START_EXCLUDE silent]
// Construct a PlacesClient
Places.initialize(getApplicationContext(), BuildConfig.MAPS_API_KEY);
placesClient = Places.createClient(this);
// Construct a FusedLocationProviderClient.
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
// Build the map.
// [START maps_current_place_map_fragment]
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
// [END maps_current_place_map_fragment]
// [END_EXCLUDE]
}
// [END maps_current_place_on_create]
/**
* Saves the state of the map when the activity is paused.
*/
// [START maps_current_place_on_save_instance_state]
#Override
protected void onSaveInstanceState(Bundle outState) {
if (map != null) {
outState.putParcelable(KEY_CAMERA_POSITION, map.getCameraPosition());
outState.putParcelable(KEY_LOCATION, lastKnownLocation);
}
super.onSaveInstanceState(outState);
}
// [END maps_current_place_on_save_instance_state]
/**
* Sets up the options menu.
* #param menu The options menu.
* #return Boolean.
*/
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.current_place_menu, menu);
return true;
}
/**
* Handles a click on the menu option to get a place.
* #param item The menu item to handle.
* #return Boolean.
*/
// [START maps_current_place_on_options_item_selected]
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.option_get_place) {
showCurrentPlace();
}
return true;
}
// [END maps_current_place_on_options_item_selected]
/**
* Manipulates the map when it's available.
* This callback is triggered when the map is ready to be used.
*/
// [START maps_current_place_on_map_ready]
#Override
public void onMapReady(GoogleMap map) {
this.map = map;
// [START_EXCLUDE]
// [START map_current_place_set_info_window_adapter]
// Use a custom info window adapter to handle multiple lines of text in the
// info window contents.
this.map.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
#Override
// Return null here, so that getInfoContents() is called next.
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
// Inflate the layouts for the info window, title and snippet.
View infoWindow = getLayoutInflater().inflate(R.layout.custom_info_contents,
(FrameLayout) findViewById(R.id.map), false);
TextView title = infoWindow.findViewById(R.id.title);
title.setText(marker.getTitle());
TextView snippet = infoWindow.findViewById(R.id.snippet);
snippet.setText(marker.getSnippet());
return infoWindow;
}
});
// [END map_current_place_set_info_window_adapter]
// Prompt the user for permission.
getLocationPermission();
// [END_EXCLUDE]
// Turn on the My Location layer and the related control on the map.
updateLocationUI();
// Get the current location of the device and set the position of the map.
getDeviceLocation();
}
// [END maps_current_place_on_map_ready]
/**
* Gets the current location of the device, and positions the map's camera.
*/
// [START maps_current_place_get_device_location]
private void getDeviceLocation() {
/*
* Get the best and most recent location of the device, which may be null in rare
* cases when a location is not available.
*/
try {
if (locationPermissionGranted) {
Task<Location> locationResult = fusedLocationProviderClient.getLastLocation();
locationResult.addOnCompleteListener(this, new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
if (task.isSuccessful()) {
// Set the map's camera position to the current location of the device.
lastKnownLocation = task.getResult();
if (lastKnownLocation != null) {
TextView coordinates = (TextView) findViewById(R.id.coordinates);
LatLng latLng = new LatLng(lastKnownLocation.getLatitude(),
lastKnownLocation.getLongitude());
coordinates.setText(latLng.toString());
map.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(lastKnownLocation.getLatitude(),
lastKnownLocation.getLongitude()), DEFAULT_ZOOM));
}
} else {
Log.d(TAG, "Current location is null. Using defaults.");
Log.e(TAG, "Exception: %s", task.getException());
map.moveCamera(CameraUpdateFactory
.newLatLngZoom(defaultLocation, DEFAULT_ZOOM));
map.getUiSettings().setMyLocationButtonEnabled(false);
}
}
});
}
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage(), e);
}
}
// [END maps_current_place_get_device_location]
/**
* Prompts the user for permission to use the device location.
*/
// [START maps_current_place_location_permission]
private void getLocationPermission() {
/*
* Request location permission, so that we can get the location of the
* device. The result of the permission request is handled by a callback,
* onRequestPermissionsResult.
*/
if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
locationPermissionGranted = true;
} else {
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
}
// [END maps_current_place_location_permission]
/**
* Handles the result of the request for location permissions.
*/
// [START maps_current_place_on_request_permissions_result]
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
locationPermissionGranted = false;
switch (requestCode) {
case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
locationPermissionGranted = true;
}
}
}
updateLocationUI();
}
// [END maps_current_place_on_request_permissions_result]
/**
* Prompts the user to select the current place from a list of likely places, and shows the
* current place on the map - provided the user has granted location permission.
*/
// [START maps_current_place_show_current_place]
private void showCurrentPlace() {
if (map == null) {
return;
}
if (locationPermissionGranted) {
// Use fields to define the data types to return.
List<Place.Field> placeFields = Arrays.asList(Place.Field.NAME, Place.Field.ADDRESS,
Place.Field.LAT_LNG);
// Use the builder to create a FindCurrentPlaceRequest.
FindCurrentPlaceRequest request =
FindCurrentPlaceRequest.newInstance(placeFields);
// Get the likely places - that is, the businesses and other points of interest that
// are the best match for the device's current location.
#SuppressWarnings("MissingPermission") final
Task<FindCurrentPlaceResponse> placeResult =
placesClient.findCurrentPlace(request);
placeResult.addOnCompleteListener (new OnCompleteListener<FindCurrentPlaceResponse>() {
#Override
public void onComplete(#NonNull Task<FindCurrentPlaceResponse> task) {
if (task.isSuccessful() && task.getResult() != null) {
FindCurrentPlaceResponse likelyPlaces = task.getResult();
// Set the count, handling cases where less than 5 entries are returned.
int count;
if (likelyPlaces.getPlaceLikelihoods().size() < M_MAX_ENTRIES) {
count = likelyPlaces.getPlaceLikelihoods().size();
} else {
count = M_MAX_ENTRIES;
}
int i = 0;
likelyPlaceNames = new String[count];
likelyPlaceAddresses = new String[count];
likelyPlaceAttributions = new List[count];
likelyPlaceLatLngs = new LatLng[count];
for (PlaceLikelihood placeLikelihood : likelyPlaces.getPlaceLikelihoods()) {
// Build a list of likely places to show the user.
likelyPlaceNames[i] = placeLikelihood.getPlace().getName();
likelyPlaceAddresses[i] = placeLikelihood.getPlace().getAddress();
likelyPlaceAttributions[i] = placeLikelihood.getPlace()
.getAttributions();
likelyPlaceLatLngs[i] = placeLikelihood.getPlace().getLatLng();
i++;
if (i > (count - 1)) {
break;
}
}
// Show a dialog offering the user the list of likely places, and add a
// marker at the selected place.
MapsActivityCurrentPlace.this.openPlacesDialog();
}
else {
Log.e(TAG, "Exception: %s", task.getException());
}
}
});
} else {
// The user has not granted permission.
Log.i(TAG, "The user did not grant location permission.");
// Add a default marker, because the user hasn't selected a place.
map.addMarker(new MarkerOptions()
.title(getString(R.string.default_info_title))
.position(defaultLocation)
.snippet(getString(R.string.default_info_snippet)));
// Prompt the user for permission.
getLocationPermission();
}
}
// [END maps_current_place_show_current_place]
/**
* Displays a form allowing the user to select a place from a list of likely places.
*/
// [START maps_current_place_open_places_dialog]
private void openPlacesDialog() {
// Ask the user to choose the place where they are now.
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// The "which" argument contains the position of the selected item.
LatLng markerLatLng = likelyPlaceLatLngs[which];
String markerSnippet = likelyPlaceAddresses[which];
if (likelyPlaceAttributions[which] != null) {
markerSnippet = markerSnippet + "\n" + likelyPlaceAttributions[which];
}
// Add a marker for the selected place, with an info window
// showing information about that place.
map.addMarker(new MarkerOptions()
.title(likelyPlaceNames[which])
.position(markerLatLng)
.snippet(markerSnippet));
// Position the map's camera at the location of the marker.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(markerLatLng,
DEFAULT_ZOOM));
}
};
}
// [END maps_current_place_open_places_dialog]
/**
* Updates the map's UI settings based on whether the user has granted location permission.
*/
// [START maps_current_place_update_location_ui]
private void updateLocationUI() {
if (map == null) {
return;
}
try {
if (locationPermissionGranted) {
map.setMyLocationEnabled(true);
map.getUiSettings().setMyLocationButtonEnabled(true);
} else {
map.setMyLocationEnabled(false);
map.getUiSettings().setMyLocationButtonEnabled(false);
lastKnownLocation = null;
getLocationPermission();
}
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage());
}
}
// [END maps_current_place_update_location_ui]
}
Especially part with my failed textbox update
private void getDeviceLocation() {
/*
* Get the best and most recent location of the device, which may be null in rare
* cases when a location is not available.
*/
try {
if (locationPermissionGranted) {
Task<Location> locationResult = fusedLocationProviderClient.getLastLocation();
locationResult.addOnCompleteListener(this, new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
if (task.isSuccessful()) {
// Set the map's camera position to the current location of the device.
lastKnownLocation = task.getResult();
if (lastKnownLocation != null) {
TextView coordinates = (TextView) findViewById(R.id.coordinates);
LatLng latLng = new LatLng(lastKnownLocation.getLatitude(),
lastKnownLocation.getLongitude());
coordinates.setText(latLng.toString());
map.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(lastKnownLocation.getLatitude(),
lastKnownLocation.getLongitude()), DEFAULT_ZOOM));
}
} else {
Log.d(TAG, "Current location is null. Using defaults.");
Log.e(TAG, "Exception: %s", task.getException());
map.moveCamera(CameraUpdateFactory
.newLatLngZoom(defaultLocation, DEFAULT_ZOOM));
map.getUiSettings().setMyLocationButtonEnabled(false);
}
}
});
}
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage(), e);
}
}
Thanks in advance for your responses.
Related
The app crashes when I write mNavigationView.setNavigationItemSelectedListener(this); in the code
and if it is not added it removes the functionality of the item in the navigation bar. Which method I should run in a background thread to reduce the effect on the main thread.
import android.app.Activity;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.SwipeRefreshLayout;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.eggheadgames.aboutbox.AboutConfig;
import com.eggheadgames.aboutbox.IAnalytic;
import com.eggheadgames.aboutbox.IDialog;
import com.eggheadgames.aboutbox.activity.AboutActivity;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class EarthquakeActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener, SwipeRefreshLayout.OnRefreshListener, LoaderManager.LoaderCallbacks<List<Earthquake>>, NavigationView.OnNavigationItemSelectedListener {
public static final String MyPrefs = "MyPrefs";
private DrawerLayout mdrawerlayout;
private ActionBarDrawerToggle mToogle;
/** URL for earthquake data from the USGS dataset */
private static final String USGS_REQUEST_URL = "https://earthquake.usgs.gov/fdsnws/event/1/query";
/**
* Constant value for the earthquake loader ID. We can choose any integer.
* This really only comes into play if you're using multiple loaders.
*/
private static final int EARTHQUAKE_LOADER_ID = 1;
/** Adapter for the list of earthquakes */
private EarthquakeAdapter mAdapter;
/** TextView that is displayed when the list is empty */
private TextView mEmptyStateTextView;
SwipeRefreshLayout swipe;
private static final String LOG_TAG = EarthquakeActivity.class.getSimpleName();
private ListView earthquakeListView;
private static final String TWITTER_USER_NAME = "vaibhav_khulbe";
private static final String WEB_HOME_PAGE = "https://about.me/vaibhav_khulbe";
private static final String APP_PUBLISHER = "https://play.google.com/store/apps/developer?id=Vaibhav%20Khulbe&hl=en";
private static final String EMAIL_ADDRESS = "khulbevaibhavdev#gmail.com";
private static final String EMAIL_SUBJECT = "Quake Info app acknowledgements and/or issues";
private static final String EMAIL_BODY = "Please explain your experience with this app here...This may include bugs" +
" or issues you may be facing or what you liked about the app along with improvements. :) (MAKE SURE to clear out these lines before sending the mail to us)";
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.earthquake_activity);
mdrawerlayout=(DrawerLayout)findViewById(R.id.drawer);
mToogle=new ActionBarDrawerToggle(this,mdrawerlayout,R.string.open,R.string.close);
mdrawerlayout.addDrawerListener(mToogle);
mToogle.syncState();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
NavigationView mNavigationView=(NavigationView)findViewById(R.id.navigation_view);
mNavigationView.setNavigationItemSelectedListener(this);
swipe = findViewById(R.id.swiperefresh);
swipe.setOnRefreshListener(this);
swipe.setColorSchemeColors(getResources().getColor(R.color.colorAccent));
/* Start the intro only once */
SharedPreferences sp = getSharedPreferences(MyPrefs, Context.MODE_PRIVATE);
if (!sp.getBoolean("first", false)) {
SharedPreferences.Editor editor = sp.edit();
editor.putBoolean("first", true);
editor.apply();
Intent intent = new Intent(this, IntroActivity.class);
startActivity(intent);
}
//Call and launch About activity
initAboutActivity();
// Find a reference to the {#link ListView} in the layout
earthquakeListView = (ListView) findViewById(R.id.list);
mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
earthquakeListView.setEmptyView(mEmptyStateTextView);
// Create a new adapter that takes an empty list of earthquakes as input
mAdapter = new EarthquakeAdapter(this, new ArrayList<Earthquake>());
// Set the adapter on the {#link ListView}
// so the list can be populated in the user interface
earthquakeListView.setAdapter(mAdapter);
// Obtain a reference to the SharedPreferences file for this app
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
// And register to be notified of preference changes
// So we know when the user has adjusted the query settings
prefs.registerOnSharedPreferenceChangeListener(this);
// Set an item click listener on the ListView, which sends an intent to a web browser
// to open a website with more information about the selected earthquake.
earthquakeListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
// Find the current earthquake that was clicked on
Earthquake currentEarthquake = mAdapter.getItem(position);
// Convert the String URL into a URI object (to pass into the Intent constructor)
Uri earthquakeUri = Uri.parse(currentEarthquake.getUrl());
// Create a new intent to view the earthquake URI
Intent websiteIntent = new Intent(Intent.ACTION_VIEW, earthquakeUri);
// Send the intent to launch a new activity
startActivity(websiteIntent);
}
});
getSupportLoaderManager().initLoader(EARTHQUAKE_LOADER_ID, null, this);
}
/*Code to launch About activity */
public void initAboutActivity()
{
/* Create About activity */
AboutConfig aboutConfig = AboutConfig.getInstance();
aboutConfig.appName = getString(R.string.app_name);
aboutConfig.appIcon = R.mipmap.ic_launcher;
aboutConfig.version = "1.0.0";
aboutConfig.author = "Vaibhav Khulbe";
aboutConfig.aboutLabelTitle = "About";
aboutConfig.packageName = getApplicationContext().getPackageName();
aboutConfig.appPublisher = APP_PUBLISHER;
aboutConfig.twitterUserName = TWITTER_USER_NAME;
aboutConfig.webHomePage = WEB_HOME_PAGE;
aboutConfig.dialog = new IDialog() {
#Override
public void open(AppCompatActivity appCompatActivity, String url, String tag) {
// handle custom implementations of WebView. It will be called when user click to web items. (Example: "Privacy", "Acknowledgments" and "About")
}
};
aboutConfig.analytics = new IAnalytic() {
#Override
public void logUiEvent(String s, String s1) {
// handle log events.
}
#Override
public void logException(Exception e, boolean b) {
// handle exception events.
}
};
// set it only if aboutConfig.analytics is defined.
aboutConfig.logUiEventName = "Log";
// Contact Support email details
aboutConfig.emailAddress = EMAIL_ADDRESS;
aboutConfig.emailSubject = EMAIL_SUBJECT;
aboutConfig.emailBody = EMAIL_BODY;
aboutConfig.shareMessage = getString(R.string.share_message);
aboutConfig.sharingTitle = getString(R.string.sharing_title);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals(getString(R.string.settings_min_magnitude_key)) ||
key.equals(getString(R.string.settings_order_by_key))){
// Clear the ListView as a new query will be kicked off
mAdapter.clear();
// Hide the empty state text view as the loading indicator will be displayed
mEmptyStateTextView.setVisibility(View.GONE);
// Show the loading indicator while new data is being fetched
View loadingIndicator = findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.VISIBLE);
// Restart the loader to requery the USGS as the query settings have been updated
getSupportLoaderManager().restartLoader(EARTHQUAKE_LOADER_ID, null, this);
}
}
#Override
public Loader<List<Earthquake>> onCreateLoader(int i, Bundle bundle) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
String minMagnitude = sharedPrefs.getString(
getString(R.string.settings_min_magnitude_key),
getString(R.string.settings_min_magnitude_default));
String orderBy = sharedPrefs.getString(
getString(R.string.settings_order_by_key),
getString(R.string.settings_order_by_default)
);
String region = sharedPrefs.getString(
getString(R.string.settings_narrow_by_region_key),
getString(R.string.settings_narrow_by_region_default)
);
String radius = sharedPrefs.getString(
getString(R.string.settings_maximum_radius_key),
getString(R.string.settings_maximum_radius_default)
);
List<Country> countries = new ArrayList<>();
try {
countries = Utils.generateCountryList(this);
} catch (IOException e) {
e.printStackTrace();
}
Double latitude = 0.0;
Double longitude = 0.0;
for (Country country : countries) {
if(country.getName().equalsIgnoreCase(region)){
latitude = country.getLatitude();
longitude = country.getLongitude();
}
}
Uri baseUri = Uri.parse(USGS_REQUEST_URL);
Uri.Builder uriBuilder = baseUri.buildUpon();
uriBuilder.appendQueryParameter("format", "geojson");
uriBuilder.appendQueryParameter("limit", "100");
uriBuilder.appendQueryParameter("minmag", minMagnitude);
uriBuilder.appendQueryParameter("orderby", orderBy);
if(latitude != 0.0 && longitude != 0.0){
uriBuilder.appendQueryParameter("latitude", String.valueOf(latitude.intValue()));
uriBuilder.appendQueryParameter("longitude", String.valueOf(longitude.intValue()));
uriBuilder.appendQueryParameter("maxradius", radius);
}
String url = uriBuilder.toString();
return new EarthquakeLoader(this, url);
}
#Override
public void onLoadFinished(Loader<List<Earthquake>> loader, List<Earthquake> earthquakes) {
swipe.setRefreshing(false);
// Hide loading indicator because the data has been loaded
View loadingIndicator = findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.GONE);
if (earthquakes != null && !earthquakes.isEmpty()) {
this.showResults(earthquakes);
} else {
this.hideResults();
}
}
#Override
public void onLoaderReset(Loader<List<Earthquake>> loader) {
// Loader reset, so we can clear out our existing data.
mAdapter.clear();
}
/**
* method to show results
*/
private void showResults(List<Earthquake> earthquakeList) {
mAdapter.clear();
earthquakeListView.setVisibility(View.VISIBLE);
mEmptyStateTextView.setVisibility(View.GONE);
mAdapter.setNotifyOnChange(false);
mAdapter.setNotifyOnChange(true);
mAdapter.addAll(earthquakeList);
}
/**
* method to hide results also checks internet connection
*/
private void hideResults() {
earthquakeListView.setVisibility(View.GONE);
mEmptyStateTextView.setVisibility(View.VISIBLE);
// Get a reference to the ConnectivityManager to check state of network connectivity
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
// Get details on the currently active default data network
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
mEmptyStateTextView.setText(R.string.no_earthquakes);
Log.e(LOG_TAG, "no earthquakes data");
} else {
mEmptyStateTextView.setText(R.string.no_internet_connection);
Log.e(LOG_TAG, "no internet");
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mToogle.onOptionsItemSelected(item)){
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onRefresh() {
getSupportLoaderManager().restartLoader(EARTHQUAKE_LOADER_ID, null, this);
Toast.makeText(this, R.string.list_refreshed, Toast.LENGTH_SHORT).show();
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
Intent settingsIntent = new Intent(this, SettingsActivity.class);
startActivity(settingsIntent);
return true;
}
if (id == R.id.action_about) {
Intent actionIntent = new Intent(this, AboutActivity.class);
startActivity(actionIntent);
return true;
}
if (id == R.id.action_did_you_feel_it){
Intent feelItIntent = new Intent(this, DidYouFeel.class);
startActivity(feelItIntent);
return true;
}
if (id == R.id.action_more_apps){
Uri uri = Uri.parse( "https://play.google.com/store/apps/developer?id=Vaibhav+Khulbe" );
startActivity( new Intent( Intent.ACTION_VIEW, uri ) );
}
if (id == R.id.fork_project){
Uri uri = Uri.parse( "https://github.com/Kvaibhav01/Quake-Info" );
startActivity( new Intent( Intent.ACTION_VIEW, uri ) );
}
if (id == R.id.notification){
Intent notificationIntent = new Intent(this, EarthquakeNotification.class);
startActivity(notificationIntent);
}
return true;
}
}
I think it can be done by running the method in a background thread but I am not sure how to do that. Thanks for helping
you can use sample code like this:
((MainActivity)context).runOnUiThread(new Runnable() {
public void run() {
//run another thread
}
});
or if you are familiar with RxJava you can use it.
consider that most of the time you should perform a function that you will call it after the click, not the click method.
I am trying to make a google place autocomplete adapter. But im getting the following error: Ive been sstuck on this for 2 days now :( so any help would be greatly appreciated!!
cant pass mGeoDataClient
The error i am recieving
Here is my MapClass:
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.AutoCompleteTextView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.location.places.PlaceDetectionClient;
import com.google.android.gms.location.places.GeoDataClient;
import com.google.android.gms.location.places.Places;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MapActivity extends AppCompatActivity implements OnMapReadyCallback {
protected GeoDataClient mGeoDataClient;
private PlaceDetectionClient mPlaceDetectionClient;
private static final LatLngBounds BOUNDS_GREATER_SYDNEY = new LatLngBounds(
new LatLng(-34.041458, 150.790100), new LatLng(-33.682247, 151.383362));
#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(mLocationPermissionGranted){
init();
}
}
private static final String TAG = "MapActivity";
private static final String FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
private static final String COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1234;
private static final float DEFAULT_ZOOM = 15f;
//widgets
private AutoCompleteTextView mSearchText;
private boolean mLocationPermissionGranted = false;
private GoogleMap mMap;
private FusedLocationProviderClient mFusedLocationProviderClient;
private PlaceAutocompleteAdapter mplaceAutocompleteAdapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
mSearchText = (AutoCompleteTextView) findViewById(R.id.input_search);
getLocationPermission();
}
private void init(){
mPlaceDetectionClient = Places.getPlaceDetectionClient(this);
mGeoDataClient = Places.getGeoDataClient(this);
mSearchText.setAdapter(mplaceAutocompleteAdapter);
Log.d(TAG, "init: initializing");
mplaceAutocompleteAdapter = new PlaceAutocompleteAdapter(this, mGeoDataClient, BOUNDS_GREATER_SYDNEY, null);
mSearchText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
if(actionId == EditorInfo.IME_ACTION_SEARCH
|| actionId == EditorInfo.IME_ACTION_DONE
|| keyEvent.getAction() == KeyEvent.ACTION_DOWN
|| keyEvent.getAction() == KeyEvent.KEYCODE_ENTER){
//execute our method for searching
geoLocate();
}
return false;
}
});
}
private void geoLocate(){
Log.d(TAG, "geoLocate: geolocating");
String searchString = mSearchText.getText().toString();
Geocoder geocoder = new Geocoder(MapActivity.this);
List<Address> list = new ArrayList<>();
try{
list = geocoder.getFromLocationName(searchString, 1);
}catch (IOException e){
Log.e(TAG, "geoLocate: IOException: " + e.getMessage() );
}
if(list.size() > 0){
Address address = list.get(0);
Log.d(TAG, "geoLocate: found a location: " + address.toString());
//Toast.makeText(this, address.toString(), Toast.LENGTH_SHORT).show();
}
}
private void moveCamera(LatLng latLng, float zoom){
Log.d(TAG, "moveCamera: moving te 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);
}
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(),
COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED){
mLocationPermissionGranted = true;
initMap();
}else {
ActivityCompat.requestPermissions(this,
permissions,LOCATION_PERMISSION_REQUEST_CODE);
}
}else {
ActivityCompat.requestPermissions(this,
permissions,LOCATION_PERMISSION_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
Log.d(TAG, "onRequestPermissionResult: called");
mLocationPermissionGranted = false;
switch (requestCode){
case LOCATION_PERMISSION_REQUEST_CODE:{
if(grantResults.length > 0){
for (int i = 0; i < grantResults.length; i++){
if (grantResults[i] != PackageManager.PERMISSION_GRANTED){
mLocationPermissionGranted = false;
Log.d(TAG, "onRequestPermissionResult: permission failed ");
return;
}
}
Log.d(TAG, "onRequestPermissionResult: permission failed ");
mLocationPermissionGranted = true;
//initialize our map
initMap();
}
}
}
}
}
Here is my app build gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.tw276.ghkjhk"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:support-media-compat:28.0.0 '
implementation 'com.android.support:support-v4:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.google.android.libraries.places:places-compat:1.0.0'
implementation 'com.google.android.gms:play-services-location:16.0.0'
implementation 'com.google.android.gms:play-services-maps:16.1.0'
implementation 'com.google.maps.android:android-maps-utils:0.5'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.android.volley:volley:1.1.1'
implementation 'com.android.support:design:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
and here is my adapter class:
import android.content.Context;
import android.graphics.Typeface;
import android.text.style.CharacterStyle;
import android.text.style.StyleSpan;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.data.DataBufferUtils;
import com.google.android.gms.location.places.AutocompleteFilter;
import com.google.android.gms.location.places.AutocompletePrediction;
import com.google.android.gms.location.places.AutocompletePredictionBufferResponse;
import com.google.android.gms.location.places.GeoDataClient;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.tasks.RuntimeExecutionException;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.Tasks;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Adapter that handles Autocomplete requests from the Places Geo Data Client.
* {#link AutocompletePrediction} results from the API are frozen and stored directly in this
* adapter. (See {#link AutocompletePrediction#freeze()}.)
*/
public class PlaceAutocompleteAdapter
extends ArrayAdapter<AutocompletePrediction> implements Filterable {
private static final String TAG = "PlaceAutocomplete";
private static final CharacterStyle STYLE_BOLD = new StyleSpan(Typeface.BOLD);
/**
* Current results returned by this adapter.
*/
private ArrayList<AutocompletePrediction> mResultList;
/**
* Handles autocomplete requests.
*/
private GeoDataClient mGeoDataClient;
/**
* The bounds used for Places Geo Data autocomplete API requests.
*/
private LatLngBounds mBounds;
/**
* The autocomplete filter used to restrict queries to a specific set of place types.
*/
private AutocompleteFilter mPlaceFilter;
/**
* Initializes with a resource for text rows and autocomplete query bounds.
*
* #see android.widget.ArrayAdapter#ArrayAdapter(android.content.Context, int)
*/
public PlaceAutocompleteAdapter(Context context, GeoDataClient geoDataClient,
LatLngBounds bounds, AutocompleteFilter filter) {
super(context, android.R.layout.simple_expandable_list_item_2, android.R.id.text1);
mGeoDataClient = geoDataClient;
mBounds = bounds;
mPlaceFilter = filter;
}
/**
* Sets the bounds for all subsequent queries.
*/
public void setBounds(LatLngBounds bounds) {
mBounds = bounds;
}
/**
* Returns the number of results received in the last autocomplete query.
*/
#Override
public int getCount() {
return mResultList.size();
}
/**
* Returns an item from the last autocomplete query.
*/
#Override
public AutocompletePrediction getItem(int position) {
return mResultList.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = super.getView(position, convertView, parent);
// Sets the primary and secondary text for a row.
// Note that getPrimaryText() and getSecondaryText() return a CharSequence that may contain
// styling based on the given CharacterStyle.
AutocompletePrediction item = getItem(position);
TextView textView1 = (TextView) row.findViewById(android.R.id.text1);
TextView textView2 = (TextView) row.findViewById(android.R.id.text2);
textView1.setText(item.getPrimaryText(STYLE_BOLD));
textView2.setText(item.getSecondaryText(STYLE_BOLD));
return row;
}
/**
* Returns the filter for the current set of autocomplete results.
*/
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
// We need a separate list to store the results, since
// this is run asynchronously.
ArrayList<AutocompletePrediction> filterData = new ArrayList<>();
// Skip the autocomplete query if no constraints are given.
if (constraint != null) {
// Query the autocomplete API for the (constraint) search string.
filterData = getAutocomplete(constraint);
}
results.values = filterData;
if (filterData != null) {
results.count = filterData.size();
} else {
results.count = 0;
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
// The API returned at least one result, update the data.
mResultList = (ArrayList<AutocompletePrediction>) results.values;
notifyDataSetChanged();
} else {
// The API did not return any results, invalidate the data set.
notifyDataSetInvalidated();
}
}
#Override
public CharSequence convertResultToString(Object resultValue) {
// Override this method to display a readable result in the AutocompleteTextView
// when clicked.
if (resultValue instanceof AutocompletePrediction) {
return ((AutocompletePrediction) resultValue).getFullText(null);
} else {
return super.convertResultToString(resultValue);
}
}
};
}
/**
* Submits an autocomplete query to the Places Geo Data Autocomplete API.
* Results are returned as frozen AutocompletePrediction objects, ready to be cached.
* Returns an empty list if no results were found.
* Returns null if the API client is not available or the query did not complete
* successfully.
* This method MUST be called off the main UI thread, as it will block until data is returned
* from the API, which may include a network request.
*
* #param constraint Autocomplete query string
* #return Results from the autocomplete API or null if the query was not successful.
* #see GeoDataClient#getAutocompletePredictions(String, LatLngBounds, AutocompleteFilter)
* #see AutocompletePrediction#freeze()
*/
private ArrayList<AutocompletePrediction> getAutocomplete(CharSequence constraint) {
Log.i(TAG, "Starting autocomplete query for: " + constraint);
// Submit the query to the autocomplete API and retrieve a PendingResult that will
// contain the results when the query completes.
Task<AutocompletePredictionBufferResponse> results =
mGeoDataClient.getAutocompletePredictions(constraint.toString(), mBounds,
mPlaceFilter);
// This method should have been called off the main UI thread. Block and wait for at most
// 60s for a result from the API.
try {
Tasks.await(results, 60, TimeUnit.SECONDS);
} catch (ExecutionException | InterruptedException | TimeoutException e) {
e.printStackTrace();
}
try {
AutocompletePredictionBufferResponse autocompletePredictions = results.getResult();
Log.i(TAG, "Query completed. Received " + autocompletePredictions.getCount()
+ " predictions.");
// Freeze the results immutable representation that can be stored safely.
return DataBufferUtils.freezeAndClose(autocompletePredictions);
} catch (RuntimeExecutionException e) {
// If the query did not complete successfully return null
Toast.makeText(getContext(), "Error contacting API: " + e.toString(),
Toast.LENGTH_SHORT).show();
Log.e(TAG, "Error getting autocomplete prediction API call", e);
return null;
}
}
}
The exact class the PlaceAutocompleteAdapter constructor expects is
com.google.android.gms.location.places.GeoDataClient
While you're importing, erroneously
com.google.android.libraries.places.compat.GeoDataClient
inside your MapActivity class
Ok, so I was recently working on a small project for my own personal preference, and along the way I implemented a small bit of code that did not work. So, as most people would do, I deleted it. But later, I experienced the same glitch that the code prior was causing, but when I checked, it was not there! I may just be plain stupid, blind, or maybe both, but I keep getting only one card in the recyclerView to show up! Feel free to call me stupid if you can find an answer, and I thank you very much in advance.
P.S. Yes, I am very new to Java, so remember this before you decide to roast me.
My MainActivity:
package com.example.whateverthefuckyouwant;
//Imports, in case you couldn't tell
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.api.GoogleApiClient;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.GooglePlayServicesAvailabilityIOException;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.ExponentialBackOff;
import com.google.api.services.sheets.v4.SheetsScopes;
import com.google.api.services.sheets.v4.model.*;
import android.Manifest;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions;
public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {
GoogleAccountCredential mCredential;
ProgressDialog mProgress;
static final int REQUEST_ACCOUNT_PICKER = 1000;
static final int REQUEST_AUTHORIZATION = 1001;
static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
static final int REQUEST_PERMISSION_GET_ACCOUNTS = 1003;
private static final String PREF_ACCOUNT_NAME = "accountName";
private static final String[] SCOPES = {SheetsScopes.SPREADSHEETS_READONLY };
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
//ArrayList holding data from the Google Sheets API
ArrayList<Team> teamAF;
//Number of cards that the user has cycled through
int cardNumber = 1;
//Integers for direction of swipe. 8 = Right, 4 = Left
int RIGHT = 8;
int LEFT = 4;
boolean first = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize credentials and service object.
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff());
//Create Recycler View
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
//Specific size of Cards
mRecyclerView.setHasFixedSize(true);
//Design choices using LinearLayoutManager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
//Create teamAF array list
teamAF = new ArrayList<>();
//Ads another card, so as to make an infinite number of cards
teamAF.add(new Team());
//Creating and setting mAdapter with teamAF
mAdapter = new MyAdapter(teamAF);
mRecyclerView.setAdapter(mAdapter);
//Swipe code for cardView
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
//Don't know what onMove does
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
Toast.makeText(MainActivity.this, "on Move", Toast.LENGTH_SHORT).show();
return false;
}
// Direction 4 = left, Direction 8 = right
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
//Prints swipeDir integer into console
Log.e(".", swipeDir + "");
//Sets variables to null, so they can be reset later
Team t = null;
//String s is reset to a string of code that enables it to check the string in the API with your answer.
String s = "";
//Code for answer. swipeDir == Left(4); Right(8).
if (swipeDir == LEFT) {
//Sets s
s = ((TextView) viewHolder.itemView.findViewById(R.id.left)).getText().toString();
} else if (swipeDir == RIGHT) {
//checks the answer swiped with he API
s = ((TextView) viewHolder.itemView.findViewById(R.id.right)).getText().toString();
}
//Removes card from array
t = teamAF.remove(mRecyclerView.getChildAdapterPosition(viewHolder.itemView));
//Adds some nice animation effect
mAdapter.notifyItemRemoved(mRecyclerView.getChildAdapterPosition(viewHolder.itemView));
//Sends a toast message saying "correct" or "incorrect"
if(t.checkAnswer(s)) {
Toast.makeText(MainActivity.this, "Correct!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "Incorrect!", Toast.LENGTH_SHORT).show();
}
if(first) {
//This make the recyclerView shuffle
Collections.shuffle(teamAF, new Random());
first = false;
}
//Adding one, so the cards can go on forever
cardNumber++;
//Calls the methods
mAdapter = new MyAdapter(teamAF);
mRecyclerView.setAdapter(mAdapter);
//This is a 'benchmark' type 'achievement'
if (cardNumber == 50) {
Toast.makeText(getApplicationContext(), "You Reached 50 Points Without Losing! You're Doing Great!", Toast.LENGTH_SHORT).show();
} else if (cardNumber == 100) {
Toast.makeText(getApplicationContext(), "You Reached 100 Points Without Losing! You're A Genius!", Toast.LENGTH_SHORT).show();
}
}
};
//Allows the swiping inside the recyclerView
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(mRecyclerView);
//Calls the google API
mProgress = new ProgressDialog(this);
mProgress.setMessage("Loading...");
getResultsFromApi();
}
//The green was commented from the site
/**
* Attempt to call the API, after verifying that all the preconditions are
* satisfied. The preconditions are: Google Play Services installed, an
* account was selected and the device currently has online access. If any
* of the preconditions are not satisfied, the app will prompt the user as
* appropriate.
*/
private void getResultsFromApi() {
if (! isGooglePlayServicesAvailable()) {
acquireGooglePlayServices();
} else if (mCredential.getSelectedAccountName() == null) {
chooseAccount();
} else if (! isDeviceOnline()) {
System.out.println("No network connection available.");
} else {
new MakeRequestTask(mCredential).execute();
}
}
/**
* Attempts to set the account used with the API credentials. If an account
* name was previously saved it will use that one; otherwise an account
* picker dialog will be shown to the user. Note that the setting the
* account to use with the credentials object requires the app to have the
* GET_ACCOUNTS permission, which is requested here if it is not already
* present. The AfterPermissionGranted annotation indicates that this
* function will be rerun automatically whenever the GET_ACCOUNTS permission
* is granted.
*/
#AfterPermissionGranted(REQUEST_PERMISSION_GET_ACCOUNTS)
private void chooseAccount() {
if (EasyPermissions.hasPermissions(
this, Manifest.permission.GET_ACCOUNTS)) {
String accountName = getPreferences(Context.MODE_PRIVATE)
.getString(PREF_ACCOUNT_NAME, null);
if (accountName != null) {
mCredential.setSelectedAccountName(accountName);
getResultsFromApi();
} else {
// Start a dialog from which the user can choose an account
startActivityForResult(
mCredential.newChooseAccountIntent(),
REQUEST_ACCOUNT_PICKER);
}
} else {
// Request the GET_ACCOUNTS permission via a user dialog
EasyPermissions.requestPermissions(
this,
"This app needs to access your Google account (via Contacts).",
REQUEST_PERMISSION_GET_ACCOUNTS,
Manifest.permission.GET_ACCOUNTS);
}
}
/**
* Called when an activity launched here (specifically, AccountPicker
* and authorization) exits, giving you the requestCode you started it with,
* the resultCode it returned, and any additional data from it.
* #param requestCode code indicating which activity result is incoming.
* #param resultCode code indicating the result of the incoming
* activity result.
* #param data Intent (containing result data) returned by incoming
* activity result.
*/
#Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case REQUEST_GOOGLE_PLAY_SERVICES:
if (resultCode != RESULT_OK) {
} else {
getResultsFromApi();
}
break;
case REQUEST_ACCOUNT_PICKER:
if (resultCode == RESULT_OK && data != null &&
data.getExtras() != null) {
String accountName =
data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
SharedPreferences settings =
getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_ACCOUNT_NAME, accountName);
editor.apply();
mCredential.setSelectedAccountName(accountName);
getResultsFromApi();
}
}
break;
case REQUEST_AUTHORIZATION:
if (resultCode == RESULT_OK) {
getResultsFromApi();
}
break;
}
}
/**
* Respond to requests for permissions at runtime for API 23 and above.
* #param requestCode The request code passed in
* requestPermissions(android.app.Activity, String, int, String[])
* #param permissions The requested permissions. Never null.
* #param grantResults The grant results for the corresponding permissions
* which is either PERMISSION_GRANTED or PERMISSION_DENIED. Never null.
*/
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(
requestCode, permissions, grantResults, this);
}
/**
* Callback for when a permission is granted using the EasyPermissions
* library.
* #param requestCode The request code associated with the requested
* permission
* #param list The requested permission list. Never null.
*/
#Override
public void onPermissionsGranted(int requestCode, List<String> list) {
// Do nothing.
}
/**
* Callback for when a permission is denied using the EasyPermissions
* library.
* #param requestCode The request code associated with the requested
* permission
* #param list The requested permission list. Never null.
*/
#Override
public void onPermissionsDenied(int requestCode, List<String> list) {
// Do nothing.
}
/**
* Checks whether the device currently has a network connection.
* #return true if the device has a network connection, false otherwise.
*/
private boolean isDeviceOnline() {
ConnectivityManager connMgr =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
/**
* Check that Google Play services APK is installed and up to date.
* #return true if Google Play Services is available and up to
* date on this device; false otherwise.
*/
private boolean isGooglePlayServicesAvailable() {
GoogleApiAvailability apiAvailability =
GoogleApiAvailability.getInstance();
final int connectionStatusCode =
apiAvailability.isGooglePlayServicesAvailable(this);
return connectionStatusCode == ConnectionResult.SUCCESS;
}
/**
* Attempt to resolve a missing, out-of-date, invalid or disabled Google
* Play Services installation via a user dialog, if possible.
*/
private void acquireGooglePlayServices() {
GoogleApiAvailability apiAvailability =
GoogleApiAvailability.getInstance();
final int connectionStatusCode =
apiAvailability.isGooglePlayServicesAvailable(this);
if (apiAvailability.isUserResolvableError(connectionStatusCode)) {
showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
}
}
/**
* Display an error dialog showing that Google Play Services is missing
* or out of date.
* #param connectionStatusCode code describing the presence (or lack of)
* Google Play Services on this device.
*/
void showGooglePlayServicesAvailabilityErrorDialog(
final int connectionStatusCode) {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
Dialog dialog = apiAvailability.getErrorDialog(
MainActivity.this,
connectionStatusCode,
REQUEST_GOOGLE_PLAY_SERVICES);
dialog.show();
}
/**
* An asynchronous task that handles the Google Sheets API call.
* Placing the API calls in their own task ensures the UI stays responsive.
*/
private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
private com.google.api.services.sheets.v4.Sheets mService = null;
private Exception mLastError = null;
MakeRequestTask(GoogleAccountCredential credential) {
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
mService = new com.google.api.services.sheets.v4.Sheets.Builder(
transport, jsonFactory, credential)
.setApplicationName("Google Sheets API Android Quickstart")
.build();
}
/**
* Background task to call Google Sheets API.
* #param params no parameters needed for this task.
*/
#Override
protected List<String> doInBackground(Void... params) {
try {
return getDataFromApi();
} catch (Exception e) {
mLastError = e;
cancel(true);
return null;
}
}
/**
* Fetch a list of names and majors of students in a sample spreadsheet:
* https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
* #return List of names and majors
*/
private List<String> getDataFromApi() throws IOException {
String spreadsheetId = "1KlflsDsBn0lhGT87OuRuy_RGOuBP2jBU5zpqn_UIYT0";
String range = "Sheet1!A2:B";
List<String> results = new ArrayList<String>();
ValueRange response = this.mService.spreadsheets().values()
.get(spreadsheetId, range)
.execute();
List<List<Object>> values = response.getValues();
for (List row : values) {
//Obtains the row from the Google Sheet
teamAF.add(new Team(row.get(0).toString(), row.get(1).toString()));
}
//Shuffle the cards with the data on them.
Collections.shuffle(teamAF, new Random());
/*for(String s : results) {
Log.e("HERE", s);
}*/
return results;
}
#Override
protected void onPreExecute() {
//mOutputText.setText("");
mProgress.show();
}
#Override
protected void onPostExecute(List<String> output) {
mProgress.hide();
if (output == null || output.size() == 0) {
//mOutputText.setText("No results returned.");
} else {
output.add(0, "Data retrieved using the Google Sheets API:");
//mOutputText.setText(TextUtils.join("\n", output));
}
}
#Override
protected void onCancelled() {
mProgress.hide();
if (mLastError != null) {
if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
showGooglePlayServicesAvailabilityErrorDialog(
((GooglePlayServicesAvailabilityIOException) mLastError)
.getConnectionStatusCode());
} else if (mLastError instanceof UserRecoverableAuthIOException) {
startActivityForResult(
((UserRecoverableAuthIOException) mLastError).getIntent(),
MainActivity.REQUEST_AUTHORIZATION);
} else {
//mOutputText.setText("The following error occurred:\n"
//+ mLastError.getMessage());
}
} else {
//mOutputText.setText("Request cancelled.");
}
}
}
}
My Adapter:
package com.example.whateverthefuckyouwant;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Random;
/**
* Created by ebuttikofer20 on 1/20/17.
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ArrayList<Team> mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView mTextView;
public TextView left;
public TextView right;
public ViewHolder(View v) {
super(v);
mTextView = (TextView) v.findViewById(R.id.info_text);
left = (TextView) v.findViewById(R.id.left);
right = (TextView) v.findViewById(R.id.right);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(ArrayList<Team> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your data at this position
// - replace the contents of the view with that element
holder.mTextView.setText(mDataset.get(position).getTeamName());
Random gen = new Random();
if(gen.nextBoolean()) {
lefter = mDataset.get(position).getTeamNumber();
righter = mDataset.get(gen.nextInt(mDataset.size())).getTeamNumber();
holder.left.setText(lefter);
holder.right.setText(righter);
} else {
righter = mDataset.get(
position).getTeamNumber();
lefter = mDataset.get(gen.nextInt(mDataset.size())).getTeamNumber();
holder.right.setText(righter);
holder.left.setText(lefter);
}
}
String righter;
String lefter;
public String getLeft() {
return lefter;
}
public String getRighter() {
return righter;
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.size();
}
}
set your parent layout's height in your R.layout.my_text_view file to wrap_content
I had the same challenge but i had to set my parent layout height to android:layout_height="wrap_content"
That worked for me so well
I have created an Android app that has a user login and registration linked to my Firebase database.
I am trying to use Geofire to store and display the users that are logged in on a map, I have used the SF vehicle example and if I'm honest I don't understand it that much. I have used the exact same code to test and see if it worked and I get the error in the image provided.
I am looking for help with writing a function to detect the logged in user's location and display it on the map in real-time, updating as the user moves, I am stuck on this weeks now and have tried all there is out there (which is not a lot).
Some help would be greatly appreciated, any further information needed just ask.
This is the code from the SF Vehicle example that I am using, the original is connected to the San Fransisco bus department and displaying them, so i need the code to write the location to my database and display them in the same way.
package nixer.nixer;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.geofire.GeoFire;
import com.firebase.geofire.GeoLocation;
import com.firebase.geofire.GeoQuery;
import com.firebase.geofire.GeoQueryEventListener;
import com.firebase.geofire.LocationCallback;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.*;
import java.util.HashMap;
import java.util.Map;
public class MapActivity extends AppCompatActivity implements GeoQueryEventListener, GoogleMap.OnCameraChangeListener {
private Firebase mRef;
private String mUserId;
private String itemsUrl;
private static final GeoLocation INITIAL_CENTER = new GeoLocation(53.349805, -6.260309 );
private static final int INITIAL_ZOOM_LEVEL = 14;
private static final String GEO_FIRE_REF = "https://nixer.firebaseio.com/";
private GoogleMap map;
private Circle searchCircle;
private GeoFire geoFire;
private GeoQuery geoQuery;
private Map<String,Marker> markers;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// setup map and camera position
SupportMapFragment mapFragment = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
this.map = mapFragment.getMap();
LatLng latLngCenter = new LatLng(INITIAL_CENTER.latitude, INITIAL_CENTER.longitude);
this.searchCircle = this.map.addCircle(new CircleOptions().center(latLngCenter).radius(1000));
this.searchCircle.setFillColor(Color.argb(66, 255, 0, 255));
this.searchCircle.setStrokeColor(Color.argb(66, 0, 0, 0));
this.map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLngCenter, INITIAL_ZOOM_LEVEL));
this.map.setOnCameraChangeListener(this);
Firebase.setAndroidContext(this);
// setup GeoFire
this.geoFire = new GeoFire(new Firebase(GEO_FIRE_REF));
// radius in km
this.geoQuery = this.geoFire.queryAtLocation(INITIAL_CENTER, 1);
// setup markers
this.markers = new HashMap<String, Marker>();
// Check Authentication
mRef = new Firebase(Constants.FIREBASE_URL);
if (mRef.getAuth() == null) {
loadLoginView();
}
try {
mUserId = mRef.getAuth().getUid();
} catch (Exception e) {
loadLoginView();
}
}
#Override
protected void onStop() {
super.onStop();
// remove all event listeners to stop updating in the background
this.geoQuery.removeAllListeners();
for (Marker marker: this.markers.values()) {
marker.remove();
}
this.markers.clear();
}
#Override
protected void onStart() {
super.onStart();
// add an event listener to start updating locations again
this.geoQuery.addGeoQueryEventListener(this);
}
#Override
public void onKeyEntered(String key, GeoLocation location) {
// Add a new marker to the map
Marker marker = this.map.addMarker(new MarkerOptions().position(new LatLng(location.latitude, location.longitude)));
this.markers.put(key, marker);
}
#Override
public void onKeyExited(String key) {
// Remove any old marker
Marker marker = this.markers.get(key);
if (marker != null) {
marker.remove();
this.markers.remove(key);
}
}
#Override
public void onKeyMoved(String key, GeoLocation location) {
// Move the marker
Marker marker = this.markers.get(key);
if (marker != null) {
this.animateMarkerTo(marker, location.latitude, location.longitude);
}
}
#Override
public void onGeoQueryReady() {
}
#Override
public void onGeoQueryError(FirebaseError error) {
new AlertDialog.Builder(this)
.setTitle("Error")
.setMessage("There was an unexpected error querying GeoFire: " + error.getMessage())
.setPositiveButton(android.R.string.ok, null)
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
// Animation handler for old APIs without animation support
private void animateMarkerTo(final Marker marker, final double lat, final double lng) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final long DURATION_MS = 3000;
final Interpolator interpolator = new AccelerateDecelerateInterpolator();
final LatLng startPosition = marker.getPosition();
handler.post(new Runnable() {
#Override
public void run() {
float elapsed = SystemClock.uptimeMillis() - start;
float t = elapsed/DURATION_MS;
float v = interpolator.getInterpolation(t);
double currentLat = (lat - startPosition.latitude) * v + startPosition.latitude;
double currentLng = (lng - startPosition.longitude) * v + startPosition.longitude;
marker.setPosition(new LatLng(currentLat, currentLng));
// if animation is not finished yet, repeat
if (t < 1) {
handler.postDelayed(this, 16);
}
}
});
}
private double zoomLevelToRadius(double zoomLevel) {
// Approximation to fit circle into view
return 16384000/Math.pow(2, zoomLevel);
}
#Override
public void onCameraChange(CameraPosition cameraPosition) {
// Update the search criteria for this geoQuery and the circle on the map
LatLng center = cameraPosition.target;
double radius = zoomLevelToRadius(cameraPosition.zoom);
this.searchCircle.setCenter(center);
this.searchCircle.setRadius(radius);
this.geoQuery.setCenter(new GeoLocation(center.latitude, center.longitude));
// radius in km
this.geoQuery.setRadius(radius/1000);
}
Update:
Firebase rules :
{
"rules": {
"users": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid",
"items": {
"$item_id": {
"title": {
".validate": "newData.isString() && newData.val().length > 0"
}
}
}
}
}
}
}
{
"rules": {
"users": {
"$uid": {
".read": true,
".write": true,
"items": {
"$item_id": {
"title": {
".validate": "newData.isString() && newData.val().length > 0"
}
}
}
}
}
}
}
I am a beginner and this may be programming basics that I am missing here, but this is the only way I'll learn these things.
Below is my MainActivity code. It is trying to get details of the last location and read them into a class which I defined (class is called UserCurrentAddress) so that I can use those details.
I have declared the UserCurrentAddress class in the MainActivity class and then instantiated in the onCreate. I then use a button click (onClickView) at the bottom of the code to connect the API and get the location. The "handleNewLocation" method eventually populates the UserCurrentAddress object (and this works successfully). However when I try to read those details from the UserCurrentAddress in the buttonClick event (just using a Toast) it comes back as null. If I put that toast in the "handleNewLocation" then it is correctly populated.
Why is it that the properties of the UserCurrentAddress are not visible from the buttonClick event?
I thought by declaring it in the Activity Class it would be visible throughout.
I realise I can probably do what I need to do within the "handleNewLocation" method, but it would be preferable to have access to those properties from outside that event.
I hope I've managed to explain my issue.
Code:
package com.example.android.trainingapp;
import android.content.IntentSender;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.model.LatLng;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
public class MainActivity extends AppCompatActivity
implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
View.OnClickListener{
private GoogleApiClient mGoogleAPIClient;
private UserCurrentAddress userCurrentAddress;
Button bFindLocation;
private LocationRequest mlocationRequest;
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bFindLocation = (Button) findViewById(R.id.show_location);
bFindLocation.setOnClickListener(this);
mGoogleAPIClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mlocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000)
.setFastestInterval(1 * 1000);
userCurrentAddress = new UserCurrentAddress(null, null, null, null, null, 0, 0, null);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onConnected(Bundle bundle) {
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleAPIClient);
if(location==null){
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleAPIClient, mlocationRequest, (LocationListener) this);
}
else{
handleNewLocation(location);
}
}
public void handleNewLocation(Location location){
double currentLatitude, currentLongitude;
String addressOne, addressTwo, streetNumber, country, fullAddress, postCode, myAdress;
currentLatitude = location.getLatitude();
currentLongitude = location.getLongitude();
LatLng latLng = new LatLng(currentLatitude, currentLongitude);
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
try {
List<Address> addresses = geocoder.getFromLocation(currentLatitude, currentLongitude, 1);
if(addresses != null){
Address returnedAddress = addresses.get(0);
StringBuilder strReturnedAddress = new StringBuilder();
for(int i=0; i < returnedAddress.getMaxAddressLineIndex(); i++){
strReturnedAddress.append(returnedAddress.getAddressLine(i)).append(" ");
}
streetNumber = returnedAddress.getSubThoroughfare();
addressOne = returnedAddress.getThoroughfare(); //Beech Rd
addressTwo = returnedAddress.getLocality(); //durban north
postCode = returnedAddress.getPostalCode();
country = returnedAddress.getCountryName();
myAdress = strReturnedAddress.toString();
userCurrentAddress.streetNumber = streetNumber;
userCurrentAddress.addressOne = addressOne;
userCurrentAddress.addressTwo = addressTwo;
userCurrentAddress.postCode = postCode;
userCurrentAddress.country =country ;
userCurrentAddress.latitude = currentLatitude;
userCurrentAddress.longitude = currentLongitude;
userCurrentAddress.fullAddress = myAdress;
Toast.makeText(this, userCurrentAddress.streetNumber, Toast.LENGTH_LONG).show();
}
else{
myAdress = "No Address Returned";
}
} catch (IOException e) {
e.printStackTrace();
myAdress = "Cannot get address";
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
/*
* Google Play services can resolve some errors it detects.
* If the error has a resolution, try sending an Intent to
* start a Google Play services activity that can resolve
* error.
*/
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
/*
* Thrown if Google Play services canceled the original
* PendingIntent
*/
} catch (IntentSender.SendIntentException e) {
// Log the error
e.printStackTrace();
}
} else {
/*
* If no resolution is available, display a dialog to the
* user with the error.
*/
}
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.show_location:
mGoogleAPIClient.connect();
Toast.makeText(this, userCurrentAddress.fullAddress, Toast.LENGTH_LONG).show();
}
}
}
From what you're describing, this line:
userCurrentAddress = new UserCurrentAddress(null, null, null, null, null, 0, 0, null);
must be getting executed after the handleNewLocation() call.
Try moving that line to a spot before the GoogleApiClient.Builder calls and see if that makes any difference.