Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialAndrew Pritykin
6,574 PointsMaking Stormy Location Aware using Google Play Services
I was looking into the documentation Google has on getting the last known location of the users device https://developer.android.com/training/location/retrieve-current.html. I tried to implement it but now when the app loads and on refresh, I am not getting coordinates. It returns 0,0 for lat,long.
Here is my MainActivity:
package com.leetinsider.skymate;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
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.LocationServices;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import butterknife.BindView;
import butterknife.ButterKnife;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
public static final String TAG = MainActivity.class.getSimpleName();
public CurrentWeather mCurrentWeather;
protected GoogleApiClient mGoogleApiClient;
protected Location mLastLocation;
double latitude;
double longitude;
@BindView(R.id.timeLabel) TextView mTimeLabel;
@BindView(R.id.temperatureLabel) TextView mTemperatureLabel;
@BindView(R.id.humidityValue) TextView mHumidityValue;
@BindView(R.id.precipValue) TextView mPrecipValue;
@BindView(R.id.summaryTextView) TextView mSummaryLabel;
@BindView(R.id.iconImageView) ImageView mIconImageView;
@BindView(R.id.refreshImageView) ImageView mRefreshImageView;
@BindView(R.id.progressBar) ProgressBar mProgressBar;
@BindView(R.id.locationLabel) TextView mLocationLabel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Import view variables
ButterKnife.bind(this);
buildGoogleApiClient();
// Set default progressbar to invisible
mProgressBar.setVisibility(View.INVISIBLE);
// Create onClick for the refresh button
mRefreshImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getForecast(latitude, longitude);
}
});
getForecast(latitude, longitude);
}
private synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
private void getForecast(double latitude, double longitude) {
// Compose the Forecast IO url into separate variables
String apiKey = "4d0e45683b7534f37310e7e716272643";
String forecastUrl = "https://api.forecast.io/forecast/" + apiKey +
"/" + latitude + "," + longitude;
// Check if network is available using isNetworkAvailable(). True then fire GET Request
// Else display Toast message of no network.
if (isNetworkAvailable()) {
// Check the status of progress bar and update refresh image
toggleRefresh();
// Start a new http client request to GET JSON data
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(forecastUrl)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
toggleRefresh();
}
});
alertUserAboutError("Failure!", "There seems to be an issue getting current weather.");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
runOnUiThread(new Runnable() {
@Override
public void run() {
toggleRefresh();
}
});
try {
String jsonData = response.body().string();
Log.v(TAG, jsonData);
if (response.isSuccessful()) {
//If response is good, get current weather from json
mCurrentWeather = getCurrentDetails(jsonData);
// After parsing JSON data, update the views with data on UiThread
runOnUiThread(new Runnable() {
@Override
public void run() {
updateDisplay();
}
});
} else {
// Dialog text appear if there is an issue with connecting to the service
alertUserAboutError("Sorry!", "There was an error");
}
} catch (IOException e) {
Log.e(TAG, "Exception caught: ", e);
} catch (JSONException e) {
Log.e(TAG, "Exception caught: ", e);
}
}
});
} else {
alertUserAboutError("Network!", "Device not connected to network. Please verify " +
"network connectivity or signal.");
}
}
private void toggleRefresh() {
//Hide Refresh Button - Show Spinner
if (mProgressBar.getVisibility() == View.INVISIBLE) {
mProgressBar.setVisibility(View.VISIBLE);
mRefreshImageView.setVisibility(View.INVISIBLE);
}
//Show Refresh Button - Hide Spinner
else {
mProgressBar.setVisibility(View.INVISIBLE);
mRefreshImageView.setVisibility(View.VISIBLE);
}
}
private void updateDisplay() {
mTemperatureLabel.setText(mCurrentWeather.getTemperature() + "");
mTimeLabel.setText("At " + mCurrentWeather.getFormattedTime() + " it will be");
mHumidityValue.setText(mCurrentWeather.getHumidity() + "");
mPrecipValue.setText(mCurrentWeather.getPrecipChance() + "%");
mSummaryLabel.setText(mCurrentWeather.getSummary());
Drawable drawable = getResources().getDrawable(mCurrentWeather.getIconId());
mIconImageView.setImageDrawable(drawable);
}
private CurrentWeather getCurrentDetails(String jsonData) throws JSONException {
// New JSON object named forecast that takes the jsonData as parameter
JSONObject forecast = new JSONObject(jsonData);
// Set variables from the JSON key value
String timezone = forecast.getString("timezone");
Log.i(TAG, "From JSON object " + timezone);
JSONObject currently = forecast.getJSONObject("currently");
CurrentWeather currentWeather = new CurrentWeather();
currentWeather.setHumidity(currently.getDouble("humidity"));
currentWeather.setTime(currently.getLong("time"));
currentWeather.setIcon(currently.getString("icon"));
currentWeather.setPrecipChance(currently.getDouble("precipProbability"));
currentWeather.setSummary(currently.getString("summary"));
currentWeather.setTemperature(currently.getDouble("temperature"));
currentWeather.setTimeZone(timezone);
Log.d(TAG, currentWeather.getFormattedTime());
return currentWeather;
}
private boolean isNetworkAvailable() {
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
if (networkInfo != null && networkInfo.isConnected()) {
isAvailable = true;
}
return isAvailable;
}
private void alertUserAboutError(String alertTitle, String alertBody) {
Bundle messageArgs = new Bundle();
// Use the arguments to set up the bundle
messageArgs.putString(AlertDialogFragment.TITLE_ID, alertTitle);
messageArgs.putString(AlertDialogFragment.MESSAGE_ID, alertBody);
AlertDialogFragment dialog = new AlertDialogFragment();
dialog.setArguments(messageArgs);
dialog.show(getFragmentManager(), "error_dialog");
}
// ********** Methods below deal with Google Play API Location **************
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
@Override
public void onConnected(@Nullable Bundle bundle) {
// Provides a simple way of getting a device's location and is well suited for
// applications that do not require a fine-grained location and that do not need location
// updates. Gets the best and most recent location currently available, which may be null
// in rare cases when a location is not available.
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
latitude = mLastLocation.getLatitude();
longitude = mLastLocation.getLongitude();
} else {
Toast.makeText(this, "No location detected", Toast.LENGTH_LONG).show();
}
}
@Override
public void onConnectionSuspended(int i) {
// The connection to Google Play services was lost for some reason. We call connect() to
// attempt to re-establish the connection
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode());
}
}
1 Answer
Seth Kroger
56,413 PointsI would suggest putting a breakpoint at the top of onConnected() since it seems to be the only place where you let latitude and longitude. Then step through the method in the debugger to get a better idea where the issue is.
Andrew Pritykin
6,574 PointsAndrew Pritykin
6,574 PointsThanks for the tip Seth Kroger I will return with more info once I debug or if I solve it myself.