简体   繁体   中英

Using sunrise/sunset REST API in Android. How to correctly pass the URL with obtained location coordinates?

I am making an Android application which gets the coordinates of the user's location and then uses those coordinates to talk to a REST API provided by - this website

I am fairly new with JSON parsing and REST API. I have used AsyncTask, Spring and Jackson for it by following this tutorial

My MainActivity.java looks like this -

package com.gamecodeschool.whereintheworld;

import android.content.Context;
import android.location.LocationListener;
import android.location.LocationManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.location.Criteria;
import android.location.Location;

import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import android.os.AsyncTask;

public class MainActivity extends AppCompatActivity implements LocationListener {

    private TextView txtLat;
    private TextView txtLong;
    private TextView txtSource;
    private LocationManager locationManager;
    private String provider;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        new HttpRequestTask().execute();
        setContentView(R.layout.activity_main);
        txtLat = (TextView) findViewById(R.id.txtLat);
        txtLong = (TextView) findViewById(R.id.txtLong);
        txtSource = (TextView) findViewById(R.id.txtSource);

        //Initialize locationManager
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        Criteria criteria = new Criteria();
        provider = locationManager.getBestProvider(criteria, false);
        Location location = locationManager.getLastKnownLocation(provider);

        //initialize the location
        if(location != null){
            txtSource.setText("Source = " +provider);
            onLocationChanged(location);
        }

    }
    //start updates when app starts/resumes
    @Override
    protected void onResume() {
        super.onResume();
        new HttpRequestTask().execute();
        locationManager.requestLocationUpdates
                (provider, 500, 1, this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        locationManager.removeUpdates(this);
    }

    @Override
    public void onLocationChanged(Location location) {
        double lat = location.getLatitude();
        double lng = location.getLongitude();
        txtLat.setText(String.valueOf(lat));
        txtLong.setText(String.valueOf(lng));
        txtSource.setText("Source = " + provider);
    }

    public String getCoordinates(Location location)
    {
        double latitude = location.getLatitude();
        double longitude = location.getLongitude();

        return ("lat="+latitude+"&lng="+longitude);

    }

    @Override
    public void onStatusChanged(String provider,
                                int status, Bundle extras) {
        txtSource.setText("Source = " + provider);
    }
    @Override
    public void onProviderEnabled(String provider) {

        txtSource.setText("Source = " + provider);
    }
    @Override
    public void onProviderDisabled(String provider) {

        txtSource.setText("Source = " + provider);
    }

    //USER DEFINED CLASS
    private class HttpRequestTask extends AsyncTask<Void, Void, sunrisedata> {



        @Override
        protected sunrisedata doInBackground(Void... params) {
            try {


                final String url = "http://api.sunrise-sunset.org/json?";
                RestTemplate restTemplate = new RestTemplate();
                restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
                sunrisedata greeting = restTemplate.getForObject(url, sunrisedata.class);
                return greeting;
            } catch (Exception e) {
                Log.e("MainActivity", e.getMessage(), e);
            }

            return null;
        }

        @Override
        protected void onPostExecute(sunrisedata greeting) {
            TextView greetingIdText = (TextView) findViewById(R.id.txtSunrise);

            greetingIdText.setText(greeting.getSunrise());

        }

    }


}

Here in this part of MainActivity.java

final String url = "http://api.sunrise-sunset.org/json?";

I want to pass the coordinates obtained from this part of the code -

public void onLocationChanged(Location location) {
        double lat = location.getLatitude();
        double lng = location.getLongitude();
        txtLat.setText(String.valueOf(lat));
        txtLong.setText(String.valueOf(lng));
        txtSource.setText("Source = " + provider);
    }

Because according to the REST API docs the GET request URL should be in this format -

http://api.sunrise-sunset.org/json?lat=36.7201600&lng=-4.4203400

What is the way in which I can retrieve the latitude and longitude and append it to the URL in the HttpRequestTask class's method -

protected sunrisedata doInBackground(Void... params) 

As of now the logcat error looks like this -

04-03 01:56:35.231 13842-1925/com.gamecodeschool.whereintheworld E/MainActivity: Could not read JSON: Unrecognized token 'Array': was expecting ('true', 'false' or 'null')
                                                                                     at [Source: buffer(com.android.okio.GzipSource@1713350c).inputStream(); line: 1, column: 11]; nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Array': was expecting ('true', 'false' or 'null')
                                                                                  at [Source: buffer(com.android.okio.GzipSource@1713350c).inputStream(); line: 1, column: 11]
                                                                                 org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unrecognized token 'Array': was expecting ('true', 'false' or 'null')
                                                                                     at [Source: buffer(com.android.okio.GzipSource@1713350c).inputStream(); line: 1, column: 11]; nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Array': was expecting ('true', 'false' or 'null')
                                                                                  at [Source: buffer(com.android.okio.GzipSource@1713350c).inputStream(); line: 1, column: 11]
                                                                                     at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readInternal(MappingJackson2HttpMessageConverter.java:126)
                                                                                     at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:147)
                                                                                     at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:76)
                                                                                     at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:484)
                                                                                     at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439)
                                                                                     at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:237)
                                                                                     at com.gamecodeschool.whereintheworld.MainActivity$HttpRequestTask.doInBackground(MainActivity.java:111)
                                                                                     at com.gamecodeschool.whereintheworld.MainActivity$HttpRequestTask.doInBackground(MainActivity.java:99)
                                                                                     at android.os.AsyncTask$2.call(AsyncTask.java:292)
                                                                                     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                                     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
                                                                                     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
                                                                                     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
                                                                                     at java.lang.Thread.run(Thread.java:818)
                                                                                  Caused by: com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Array': was expecting ('true', 'false' or 'null')
                                                                                  at [Source: buffer(com.android.okio.GzipSource@1713350c).inputStream(); line: 1, column: 11]
                                                                                     at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1524)
                                                                                     at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:557)
                                                                                     at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidToken(UTF8StreamJsonParser.java:3094)
                                                                                     at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2339)
                                                                                     at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:817)
                                                                                     at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:697)
                                                                                     at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:3031)
                                                                                     at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2978)
                                                                                     at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2158)
                                                                                     at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readInternal(MappingJackson2HttpMessageConverter.java:123)
                                                                                        ... 13 more
04-03 01:56:35.232 13842-13842/com.gamecodeschool.whereintheworld D/AndroidRuntime: Shutting down VM
04-03 01:56:35.233 13842-13842/com.gamecodeschool.whereintheworld E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                    Process: com.gamecodeschool.whereintheworld, PID: 13842
                                                                                    java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.gamecodeschool.whereintheworld.sunrisedata.getSunrise()' on a null object reference
                                                                                        at com.gamecodeschool.whereintheworld.MainActivity$HttpRequestTask.onPostExecute(MainActivity.java:124)
                                                                                        at com.gamecodeschool.whereintheworld.MainActivity$HttpRequestTask.onPostExecute(MainActivity.java:99)
                                                                                        at android.os.AsyncTask.finish(AsyncTask.java:636)
                                                                                        at android.os.AsyncTask.access$500(AsyncTask.java:177)
                                                                                        at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653)
                                                                                        at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                        at android.os.Looper.loop(Looper.java:135)
                                                                                        at android.app.ActivityThread.main(ActivityThread.java:5294)
                                                                                        at java.lang.reflect.Method.invoke(Native Method)
                                                                                        at java.lang.reflect.Method.invoke(Method.java:372)
                                                                                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
04-03 01:56:36.027 13842-2035/com.gamecodeschool.whereintheworld E/MainActivity: Could not read JSON: Unrecognized token 'Array': was expecting ('true', 'false' or 'null')
                                                                                     at [Source: buffer(com.android.okio.GzipSource@3969795b).inputStream(); line: 1, column: 11]; nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Array': was expecting ('true', 'false' or 'null')
                                                                                  at [Source: buffer(com.android.okio.GzipSource@3969795b).inputStream(); line: 1, column: 11]
                                                                                 org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unrecognized token 'Array': was expecting ('true', 'false' or 'null')
                                                                                     at [Source: buffer(com.android.okio.GzipSource@3969795b).inputStream(); line: 1, column: 11]; nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Array': was expecting ('true', 'false' or 'null')
                                                                                  at [Source: buffer(com.android.okio.GzipSource@3969795b).inputStream(); line: 1, column: 11]
                                                                                     at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readInternal(MappingJackson2HttpMessageConverter.java:126)
                                                                                     at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:147)
                                                                                     at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:76)
                                                                                     at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:484)
                                                                                     at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439)
                                                                                     at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:237)
                                                                                     at com.gamecodeschool.whereintheworld.MainActivity$HttpRequestTask.doInBackground(MainActivity.java:111)
                                                                                     at com.gamecodeschool.whereintheworld.MainActivity$HttpRequestTask.doInBackground(MainActivity.java:99)
                                                                                     at android.os.AsyncTask$2.call(AsyncTask.java:292)
                                                                                     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                                     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
                                                                                     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
                                                                                     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
                                                                                     at java.lang.Thread.run(Thread.java:818)
                                                                                  Caused by: com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Array': was expecting ('true', 'false' or 'null')
                                                                                  at [Source: buffer(com.android.okio.GzipSource@3969795b).inputStream(); line: 1, column: 11]
                                                                                     at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1524)
                                                                                     at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:557)
                                                                                     at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidToken(UTF8StreamJsonParser.java:3094)
                                                                                     at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2339)
                                                                                     at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:817)
                                                                                     at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:697)
                                                                                     at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:3031)
                                                                                     at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2978)
                                                                                     at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2158)
                                                                                     at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readInternal(MappingJackson2HttpMessageConverter.java:123)
                                                                                        ... 13 more

As far as I figured out this error is coming because the correct URL along with the latitudes and longitudes is not being passed to the website. Obviously the application is also crashing when run on the phone.

Another class which I created by following the tutorial on spring's website is - sunrisedata.java for storing the obtained JSON response looks like this -

package com.gamecodeschool.whereintheworld;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;


@JsonIgnoreProperties(ignoreUnknown=true)
public class sunrisedata {

    private String results;

    public String getSunrise(){

        return this.results;
    }

}

Please tell me how to correctly pass the lat and long values obtained in MainActivity class to the url in HttpRequestTask class and I just want to retrieve the sunrise data from JSON and ignore all other fields.

Getting the location of a user happens asynchronously which means you will have to wait until the location is returned to you from the LocationManager before you can make the request to get the sunrise/sunset data.

Right now, you are requesting the sunrise/subset data in onResume() which isn't correct. When you do the request here, it is possible that you won't have the location data yet.

It seems like you will want to fetch the sunrise/sunset data in onLocationChanged() . This method will have the location information you need to add to the url.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM