Как асинхронно читать JSON и использовать его данные в Android? - PullRequest
0 голосов
/ 19 мая 2018

Я пытаюсь загрузить код по ссылке как JSON (JSON Link: https://api.myjson.com/bins/ehzqu) и отрендерить его. Вот код:

public class FetchJSON extends AsyncTask<Void,Void,Void> {
    String data = "";
    String id, name, address, lat, lng, type = "";

    @Override
    protected Void doInBackground(Void... voids) {
        Log.i("", "TEST");
        try {
            URL url = new URL("https://api.myjson.com/bins/ehzqu");
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            InputStream inputStream = httpURLConnection.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line = "";
            while(line!=null){
                line = bufferedReader.readLine();
                data = data + line;
            }
            Log.i("", "TEST2");
            JSONArray JA = new JSONArray(data);
            for( int i = 0 ; i < JA.length();i++)
            {
                JSONObject JO = (JSONObject) JA.get(i);
                //Log.i("", JO.toString());

                id = (String) JO.get("id");
                name = (String) JO.get("name");
                address = (String) JO.get("address");

                lat = JO.get("lat").toString();
                lng = JO.get("lng").toString();
                Log.i("JSON Values", lat + " " + lng);  //////////////////////////
                type = (String) JO.get("type");
            }
            Log.i("", "TEST3");

        } catch (MalformedURLException e) {
            e.printStackTrace();

        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }


        return null;
    }


    @Override
    protected void onPostExecute(Void aVoid) {

        TrackDifferentLocation.data.setText(this.data);


        super.onPostExecute(aVoid);
    }

    public void printLat()
    {
        Log.i("", lat);
    }

    public String getLat (){
        return lat;
    }
    public String getLng (){
        return lng;
    }
    public String getName (){
        return name;
    }
    public String getAddress (){
        return address;
    }
    public String getID (){
        return id;
    }
    public String getType (){
        return type;
    }
}

В другом классе у меня тогда естьследующее;

public class TrackDifferentLocation extends AppCompatActivity implements OnMapReadyCallback {

    private GoogleMap mMap;

    String json_string;
    public static TextView data;

    @Override
    protected void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Toast.makeText(this, "Tracking location...", Toast.LENGTH_LONG).show();
        setContentView(R.layout.activity_track_different_location);
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map_fragment);
        mapFragment.getMapAsync(this);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        Log.i("", "onMapReady()");
        FetchJSON f = new FetchJSON();

        // f.execute();
        // f.printLat();
        //Log.i("", f.getLat());
        //Log.i("", f.getLng());

        double latitude = Double.valueOf(f.getLat());
        double longitude = Double.valueOf(f.getLng());
        LatLng latlng = new LatLng(latitude,longitude);
        //Log.d("Marker: ", m.getTitle());
        mMap.addMarker(new MarkerOptions().position(latlng));
    }

    //Part of menu see following
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == android.R.id.home){
            //ends the activity
            this.finish();
        }
        switch (item.getItemId()) {
            case R.id.mapTypeNone:
                mMap.setMapType(GoogleMap.MAP_TYPE_NONE);
                break;
            case R.id.mapTypeNormal:
                mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                break;
            case R.id.mapTypeTerrain:
                mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
                break;
            case R.id.mapTypeSatellite:
                mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
                break;
            case R.id.mapTypeHybrid:
                mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                break;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

Но после запуска этого кода приложение на Android падаетКод работает отлично. Обратите внимание, я удалил имена импорта и пакета для этого вопроса.

РЕДАКТИРОВАТЬ:

public class TrackDifferentLocation extends AppCompatActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    LatLng mLatlng;
    String json_string;
    public static TextView data;
    LatLng latLng = null;

    @Override
    protected void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Toast.makeText(this, "Tracking location...", Toast.LENGTH_LONG).show();
        setContentView(R.layout.activity_track_different_location);
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map_fragment);
        mapFragment.getMapAsync(this);
            getSupportActionBar().setDisplayShowHomeEnabled(true);
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        //new FetchJSON.execute(); //Not valid syntax
        FetchJSON f = new FetchJSON();
    }

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    Log.i("", "onMapReady()");
    displayMarkers();
}
    private void displayMarkers(){
        if(mMap == null) return;
        if(mLatlng == null) return;

        mMap.addMarker(new MarkerOptions().position(mLatlng));
    }

    //Part of menu see following
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == android.R.id.home){
            //ends the activity
            this.finish();
        }
        switch (item.getItemId()) {
            case R.id.mapTypeNone:
                mMap.setMapType(GoogleMap.MAP_TYPE_NONE);
                break;
            case R.id.mapTypeNormal:
                mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                break;
            case R.id.mapTypeTerrain:
                mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
                break;
            case R.id.mapTypeSatellite:
                mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
                break;
            case R.id.mapTypeHybrid:
                mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                break;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }
    class FetchJSON extends AsyncTask<String, Integer, LatLng> {
        String JSONStr = "";
        String name, address, type = "";
        String lat = "";
        String lng = "";
        String id = "";
        //double lat, lng;
        int idInt;
        double latDouble = -1;
        double lngDouble = -1;

        protected LatLng doInBackground(String... args) {
            //LatLng latLng = null;
            try {
                URL url = new URL("https://api.myjson.com/bins/ehzqu");
                HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                InputStream inputStream = httpURLConnection.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                String line = "";
                while (line != null) {
                    line = bufferedReader.readLine();
                    JSONStr = JSONStr + line;
                }
                Log.i("", "TEST2");

                JSONObject obj = new JSONObject(JSONStr);
                JSONArray array = obj.getJSONArray("server response");
                for (int i = 0; i < array.length(); i++) {
                    JSONObject o = array.getJSONObject(i);
                    id = o.optString("id");
                    name = o.optString("name");
                    address = o.optString("address");
                    lat = o.optString(lat);
                    lng = o.optString("lng");
                    latDouble = Double.parseDouble(lat);
                    lngDouble = Double.parseDouble(lng);

                    latLng = new LatLng(latDouble, lngDouble);

                    Log.i("JSON Values", lat + " " + lng);
                    type = o.optString("type");
                }
            } catch (Exception ex) {
                Log.e(TAG, "FetchJSON --- " + ex.getMessage());
            }
            return latLng;
        }

        protected void onPostExecute(LatLng latLng) {
            if (latLng != null) {
                mLatlng = latLng;
                displayMarkers();
            }
        }
        private void displayMarkers(){
            if(mMap == null) return;
            if(mLatlng == null) return;

            mMap.addMarker(new MarkerOptions().position(mLatlng));
        }
}
}

Ответы [ 2 ]

0 голосов
/ 20 мая 2018

Данные, которые вы указали в своей ссылке, не являются JSONArray.

{"ответ сервера": [{"id": "991", "name": "GPSname","address": "GPSaddress", "lat": "52.948616", "lng": "- 1.169131", "type": "GPStype"}]}

Это JSONObjectс JSONArray дочерним.

.

РЕДАКТИРОВАТЬ

Создать переменную класса для значений Latlng.

Latlng mLatlng;

Теперь в вашем методе onCreate() добавьте: loadLocation();

Вот новый код:

 @Override
 public void onMapReady(GoogleMap googleMap) {
     mMap = googleMap;

     displayMarker();
 }


 private void loadLocation() {
     new FetchJSON().execute();
 }


 class FetchJSON extends AsyncTask<String, Integer, LatLng> {

     @Override
     protected LatLng doInBackground(String... params) {
         LatLng latLng = null;
         try {
             URL url = new URL("https://api.myjson.com/bins/ehzqu");
             HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
             InputStream inputStream = httpURLConnection.getInputStream();
             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

             StringBuilder stringBuilder = new StringBuilder();
             String line = "";
             while ((line = bufferedReader.readLine()) != null) {
                 stringBuilder.append(line).append("\n");
             }
             bufferedReader.close();

             String json = stringBuilder.toString();

             Log.e(TAG, "Return = " + json);
             String lat= "";
             String lng= "";
             JSONObject obj = new JSONObject(json);
             JSONArray array = obj.getJSONArray("server response");
             for(int i = 0; i < array.length(); i++){
                 JSONObject o = array.getJSONObject(i);

                 lat = o.optString("lat");
                 lng = o.optString("lng");
             }

             Log.e(TAG, "Lat = " + lat);
             Log.e(TAG, "lng = " + lng);

             double latDouble = Double.parseDouble(lat);
             double lngDouble = Double.parseDouble(lng);

             latLng = new LatLng(latDouble, lngDouble);
         }
         catch (Exception ex) {
             Log.e(TAG, "doInBackground --- " + ex.getMessage());
         }
         return latLng;
     }


     @Override
     protected void onPostExecute(LatLng latLng) {
         try{
             if(latLng != null){
                 mLatLng = latLng;
                 displayMarker();
             }

         }
         catch(Exception ex){
             Log.e(TAG, "onPostExecute" + ex.getMessage());
         }
     }

 }

 private void displayMarker(){
     if(mMap == null) return;
     if(mLatLng == null) return;

     MarkerOptions markerOption = new MarkerOptions();
     markerOption.position(mLatLng);
     mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mLatLng, zoomFactor));
     mMap.addMarker(markerOption);
 }

Результат на моем устройстве:

enter image description here

Когда ваш GoogleMap будет готов, он вызовет displayMarkers().Если «mLatLng» равен null из-за того, что FetchJSON не завершено, ничего не происходит.

Вы можете вызвать FetchJSON из метода onMapReady(), как это предлагается, но почему бы не загрузить данные вфоновый поток, пока ваша система готовит GoogleMap?

0 голосов
/ 19 мая 2018

FetchJSON - это асинхронная задача, поэтому, когда вы пытаетесь получить доступ к f.getLat(), она еще не имеет значения, поскольку задача еще не завершена, вам нужно дождаться завершения объекта FetchJSON, прежде чем пытаться получить доступ к получателю getLat().,

Я полагаю, что вы, вероятно, можете что-то сделать по этим линиям :

передать карту объекту FetchJSON:

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    Log.i("", "onMapReady()");
    FetchJSON f = new FetchJSON(mMap);
}

и установить маркерв вашем FetchJSON, когда широта и долгота известны:

@Override
protected Void doInBackground(Void... voids) {
    ....
    lat = JO.get("lat").toString();
    lng = JO.get("lng").toString();
    type = (String) JO.get("type");

    // Set the marker here:
    double latitude = Double.valueOf(f.getLat());
    double longitude = Double.valueOf(f.getLng());
    LatLng latlng = new LatLng(latitude,longitude);
    mMap.addMarker(new MarkerOptions().position(latlng));
    ....
}

Или лучше использовать , вероятно, делать это в методе onPostExecute, который вызывается после метода doInBackground( См. API здесь ):

LatLng latlng = null;

@Override
protected Long doInBackground(URL... urls) {
    ...
    double latitude = Double.valueOf(f.getLat());
    double longitude = Double.valueOf(f.getLng());
    latlng = new LatLng(latitude,longitude);
    ....
}

@Override
protected void onPostExecute(Long result) {
    if(latlng != null)
        mMap.addMarker(new MarkerOptions().position(latlng));
}

Кроме того, вы неправильно читаете JSON , вы ожидаете JSONArray, когда он на самом деле является JSONObject, сJSONArray внутри.Этот пример работает для JSON, который вы получаете по вашей ссылке:

String data = "{\"server response\":[{\"id\":\"991\",\"name\":\"GPSname\",\"address\":\"GPSaddress\",\"lat\":\"52.948616\",\"lng\":\"-1.169131\",\"type\":\"GPStype\"}]}";
Log.i("TAG", data);

String id, name, address, lat, lng, type;
try {
    JSONObject json = new JSONObject(data);
    JSONArray serverResponse = json.getJSONArray("server response");

    for (int i = 0; i < serverResponse.length(); i++) {
        JSONObject JO = (JSONObject) serverResponse.get(i);
        id = (String) JO.get("id");
        name = (String) JO.get("name");
        address = (String) JO.get("address");

        lat = JO.get("lat").toString();
        lng = JO.get("lng").toString();
        type = (String) JO.get("type");

        Log.i("TAG", String.format(
            "JSON Values: id=%s, name=%s, address=%s, lat=%s, lng=%s, type=%s", 
            id, name, address, lat, lng, type));
    }
} catch (Exception e) {
    Log.e("TAG", "exception", e);
}

Распечатывает

JSON Values: id=991, name=GPSname, address=GPSaddress, lat=52.948616, lng=-1.169131, type=GPStype
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...