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 trial

Android Build a Weather App (2015) Hooking Up the Model to the View Wrapping Up

Ragesh Kanagaraj
Ragesh Kanagaraj
3,637 Points

Accessing Location of user using Google Location API

I tried accessing users location, instead of hardcoding the Longitude and Latitude.

But when I access LastLocation.getLatitude() I am getting NullPointer Exception

I couldnt figure out why ?

Mycode :

       ``` if(isNetworkAvailable()){
            latitude=mLastLocation.getLatitude();
          longitude=mLastLocation.getLongitude();
        url="https://api.forecast.io/forecast/"+apiKey+"/"+latitude+","+longitude;
        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder().url(url).build();
        Call call=okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
             }```

My Logs:

com.google.android.gms.common.GooglePlayServicesUtil.zza
06-15 21:38:44.875    6565-6565/com.example.ragesh.myweather W/dalvikvm﹕ VFY: unable to resolve virtual method 238: Landroid/app/Notification$Builder;.setLocalOnly (Z)Landroid/app/Notification$Builder;
06-15 21:38:44.875    6565-6565/com.example.ragesh.myweather D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x00c2
06-15 21:38:44.878    6565-6565/com.example.ragesh.myweather I/dalvikvm﹕ Could not find method android.content.pm.PackageManager.getPackageInstaller, referenced from method com.google.android.gms.common.GooglePlayServicesUtil.zzh
06-15 21:38:44.878    6565-6565/com.example.ragesh.myweather W/dalvikvm﹕ VFY: unable to resolve virtual method 521: Landroid/content/pm/PackageManager;.getPackageInstaller ()Landroid/content/pm/PackageInstaller;
06-15 21:38:44.878    6565-6565/com.example.ragesh.myweather D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x000b
06-15 21:38:44.891    6565-6565/com.example.ragesh.myweather D/AndroidRuntime﹕ Shutting down VM
06-15 21:38:44.891    6565-6565/com.example.ragesh.myweather W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x419c6d40)
06-15 21:38:44.894    6565-6565/com.example.ragesh.myweather E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.ragesh.myweather, PID: 6565
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ragesh.myweather/com.example.ragesh.myweather.MainActivity}: java.lang.NullPointerException
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2198)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257)
            at android.app.ActivityThread.access$800(ActivityThread.java:139)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5086)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
            at com.example.ragesh.myweather.MainActivity.onCreate(MainActivity.java:85)
            at android.app.Activity.performCreate(Activity.java:5248)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257)
            at android.app.ActivityThread.access$800(ActivityThread.java:139)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5086)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)```

4 Answers

The truth of the matter is this... it is way more complicated than Ben makes it seem at the end of this course. Rather than, "If you feel like it, make your app location aware." they should have given some help on how to do it. Once you have set up your GoogleAPI and are using Location Services... all of the location data that will be stored in your Location object happens in the onConnected method. That means it is asynchronous, so you can't pull any information from that object from your main method (where all your weather data gets initialized). The ONLY way I was able to get any of it to work was to essentially take all the code out of the onCreate() method and put it in the onConnected() method. This REALLY screws up the "toggleRefresh()" though. It will keep going and going and going since the onConnected() code continues to execute as long as there is a connection with Google Play Services.

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this);

        buildGoogleApiClient();
        mGoogleApiClient.connect();

    }

and the onConnected() method...

@Override
    public void onConnected(Bundle bundle) {
        mProgressBar.setVisibility(View.INVISIBLE);

        getCurrentWeather();    //I used this name instead of getForecast()...

    }

The setting of your latitude and longitude can go inside the getForecast(), since it is within the onConnected() and will pull the user location.

private void getCurrentWeather() {
        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if (mLastLocation != null) {
            mLatitude = mLastLocation.getLatitude();
            mLongitude = mLastLocation.getLongitude();
        } else {
            Toast.makeText(MainActivity.this, "Could not find your location!", Toast.LENGTH_LONG).show();
        }
        String APIKey = "71e3dbfb4ebeb4dc3bcfb07097bb3645";
        String forecastUrl = "https://api.forecast.io/forecast/"
                + APIKey + "/"
                + mLatitude
                + ","
                + mLongitude;
        if (isNetworkAvailable()) {
            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(Request request, IOException e) {

                }

                @Override
                public void onResponse(Response response) throws IOException {
                    try {
                        String jsonData = response.body().string();
                        if (response.isSuccessful()) {
                            mCurrentWeather = getWeatherDetails(jsonData);
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    updateDisplay();
                                }
                            });
                        } else {
                            Toast.makeText(MainActivity.this, "There was an error.", Toast.LENGTH_LONG).show();
                        }
                    } catch (IOException e) {
                        Log.e(TAG, "Exception caught ", e);
                    } catch (JSONException e) {
                        Log.e(TAG, "Exception caught ", e);
                    }
                }
            });
        } else {
            Toast.makeText(this, "Network unavailable.", Toast.LENGTH_LONG).show();
        }
    }

All your other methods can stay the same.. the main thing is to keep the code you want to execute that includes your location in the onConnected()... This is the only way I could make it work for me. If Ben has any other ideas I would LOVE LOVE LOVE to hear them because I am lost as well.

Hao Tran
Hao Tran
17,264 Points

Did you initialize the mLastLocation variable?

I will add... I was able to get a refresh button to work as well by placing it in the onConnected()...

Joyce Chidiadi
Joyce Chidiadi
1,867 Points

I am still hooked on the @BindView method. My error says, "Cannot find method value" when I run the code.