Issue
I am trying to download code from a link as JSON(JSON Link: https://api.myjson.com/bins/ehzqu) and render it. Here is the code:
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;
}
}
In another class, I then have the following;
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);
}
But upon running this code, the application on android, crashes.
If I hard-code the latitude and longitude as set figures in the getLat/getLng functions, the code works perfectly. Please note, I have removed the import and package names for this question.
EDIT:
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));
}
}
}
Solution
The data you showed in your link is not an JSONArray
.
{"server response":[{"id":"991","name":"GPSname","address":"GPSaddress","lat":"52.948616","lng":"-1.169131","type":"GPStype"}]}
It is a JSONObject
with a JSONArray
child.
.
EDIT
Create a class variable for the Latlng
values.
Latlng mLatlng;
Now in your onCreate()
method add:
loadLocation();
Here is the new code:
@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);
}
The result on my device:
When your GoogleMap is ready it will call displayMarkers()
. If the "mLatLng" is null
because the FetchJSON
is not finished it nothing happens.
You could call FetchJSON
from the onMapReady()
method as suggested, but why not download the data in a background thread while you system is getting the GoogleMap ready?
Answered By - Barns
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.