2

I'm working on a map app for android (Google Maps API 2), my goal is two things. There, some of which I managed to do one.

1: Center and follow the user's position. (Successful) 2: Get markers from external JSON source and display on the map. As well as update their position continuously.

I found a piece of code here: https://gist.github.com/saxman/5347195

I put together the code with my code that comes from 1. Function 1 still works, but logcat says it can not find the file I have specified. That's because it does not exist. I do not know how the JSON structure should look like, CORS is enabled on the server side to fetch JSON should not be any danger.

However, I wonder if anyone knows how the JSON structure should look like, because I do not know how to figure it out. In addition, so maybe this code is not working, hence the question can be updated if the JSON structure is complete, but the markers do not appear, for example.

How would the JSON look like? It's impossible for me to figure out.

MainActivity.java

package com.billstrom.yolo;

import android.annotation.TargetApi;
import android.app.Dialog;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.widget.TextView;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 
 */

@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class MainActivity extends FragmentActivity implements LocationListener {

    private static final String LOG_TAG = "Example";

    private static final String SERVICE_URL = "http://codele.se/app/blackcab/drivers.json";

    protected GoogleMap map;

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

        // Getting Google Play availability status
        int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getBaseContext());

        // Showing status
        if(status!=ConnectionResult.SUCCESS){ // Google Play Services are not available

            int requestCode = 10;
            Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this, requestCode);
            dialog.show();

        }else { // Google Play Services are available   

            // Getting reference to the SupportMapFragment of activity_main.xml
            SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);

            // Getting GoogleMap object from the fragment
            map = fm.getMap();

            // Enabling MyLocation Layer of Google Map
            map.setMyLocationEnabled(true); 



             // Getting LocationManager object from System Service LOCATION_SERVICE
            LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

            // Creating a criteria object to retrieve provider
            Criteria criteria = new Criteria();

            // Getting the name of the best provider
            String provider = locationManager.getBestProvider(criteria, true);

            // Getting Current Location
            Location location = locationManager.getLastKnownLocation(provider);

            if(location!=null){
                    onLocationChanged(location);
            }

            locationManager.requestLocationUpdates(provider, 20000, 0, this);
        }

    }

     @Override
        protected void onResume() {
            super.onResume();
            setUpMapIfNeeded();
        }

     private void setUpMapIfNeeded() {
            if (map == null) {
                map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                        .getMap();
                if (map != null) {
                    setUpMap();
                }
            }
        }
     private void setUpMap() {
            // Retrieve the city data from the web service
            // In a worker thread since it's a network operation.
            new Thread(new Runnable() {
                public void run() {
                    try {
                        retrieveAndAddCities();
                    } catch (IOException e) {
                        Log.e(LOG_TAG, "Cannot retrive cities", e);
                        return;
                    }
                }
            }).start();
        }

        protected void retrieveAndAddCities() throws IOException {
            HttpURLConnection conn = null;
            final StringBuilder json = new StringBuilder();
            try {
                // Connect to the web service
                URL url = new URL(SERVICE_URL);
                conn = (HttpURLConnection) url.openConnection();
                InputStreamReader in = new InputStreamReader(conn.getInputStream());

                // Read the JSON data into the StringBuilder
                int read;
                char[] buff = new char[1024];
                while ((read = in.read(buff)) != -1) {
                    json.append(buff, 0, read);
                }
            } catch (IOException e) {
                Log.e(LOG_TAG, "Error connecting to service", e);
                throw new IOException("Error connecting to service", e);
            } finally {
                if (conn != null) {
                    conn.disconnect();
                }
            }

            // Create markers for the city data.
            // Must run this on the UI thread since it's a UI operation.
            runOnUiThread(new Runnable() {
                public void run() {
                    try {
                        createMarkersFromJson(json.toString());
                    } catch (JSONException e) {
                        Log.e(LOG_TAG, "Error processing JSON", e);
                    }
                }
            });
        }

        void createMarkersFromJson(String json) throws JSONException {
            // De-serialize the JSON string into an array of city objects
            JSONArray jsonArray = new JSONArray(json);
            for (int i = 0; i < jsonArray.length(); i++) {
                // Create a marker for each city in the JSON data.
                JSONObject jsonObj = jsonArray.getJSONObject(i);
                map.addMarker(new MarkerOptions()
                    .title(jsonObj.getString("name"))
                    .snippet(Integer.toString(jsonObj.getInt("population")))
                    .position(new LatLng(
                            jsonObj.getJSONArray("latlng").getDouble(0),
                            jsonObj.getJSONArray("latlng").getDouble(1)
                     ))
                );
            }
        }

    @Override
    public void onLocationChanged(Location location) {

        TextView tvLocation = (TextView) findViewById(R.id.tv_location);

        // Getting latitude of the current location
        double latitude = location.getLatitude();

        // Getting longitude of the current location
        double longitude = location.getLongitude();     

        // Creating a LatLng object for the current location
        LatLng latLng = new LatLng(latitude, longitude);

        // Showing the current location in Google Map
        map.moveCamera(CameraUpdateFactory.newLatLng(latLng));

        // Zoom in the Google Map
        map.animateCamera(CameraUpdateFactory.zoomTo(15));      


        // Setting latitude and longitude in the TextView tv_location
        tvLocation.setText("Latitude:" +  latitude  + ", Longitude:"+ longitude );      

    }

    @Override
    public void onProviderDisabled(String provider) {
        // TODO Auto-generated method stub      
    }

    @Override
    public void onProviderEnabled(String provider) {
        // TODO Auto-generated method stub      
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        // TODO Auto-generated method stub      
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}

logcat output

07-01 16:27:40.787: E/Black Cab(17968): Error connecting to service
07-01 16:27:40.787: E/Black Cab(17968): java.io.FileNotFoundException: http://codele.se/app/blackcab/drivers.json
07-01 16:27:40.787: E/Black Cab(17968):     at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:186)
07-01 16:27:40.787: E/Black Cab(17968):     at com.billstrom.yolo.MainActivity.retrieveAndAddCities(MainActivity.java:133)
07-01 16:27:40.787: E/Black Cab(17968):     at com.billstrom.yolo.MainActivity$1.run(MainActivity.java:117)
07-01 16:27:40.787: E/Black Cab(17968):     at java.lang.Thread.run(Thread.java:856)
07-01 16:27:40.787: E/Black Cab(17968): Cannot retrive cities
07-01 16:27:40.787: E/Black Cab(17968): java.io.IOException: Error connecting to service
07-01 16:27:40.787: E/Black Cab(17968):     at com.billstrom.yolo.MainActivity.retrieveAndAddCities(MainActivity.java:143)
07-01 16:27:40.787: E/Black Cab(17968):     at com.billstrom.yolo.MainActivity$1.run(MainActivity.java:117)
07-01 16:27:40.787: E/Black Cab(17968):     at java.lang.Thread.run(Thread.java:856)
07-01 16:27:40.787: E/Black Cab(17968): Caused by: java.io.FileNotFoundException: http://codele.se/app/blackcab/drivers.json
07-01 16:27:40.787: E/Black Cab(17968):     at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:186)
07-01 16:27:40.787: E/Black Cab(17968):     at com.billstrom.yolo.MainActivity.retrieveAndAddCities(MainActivity.java:133)
07-01 16:27:40.787: E/Black Cab(17968):     ... 2 more
4

1 回答 1

4

最终答案:

首先,作为一个建议,Json在 Java 中非常容易使用,尤其是如果您使用mapper。因此,不要担心使您的服务器端数据与您在其他地方找到的代码示例完美匹配——在客户端上更改内容真的要容易得多。

记得抓住那个FileNotFoundException。如果将来出现问题,即使在修复了您的页面之后,它也会被抛出并使您的应用程序崩溃。我个人不喜欢那个特定的客户这样做,我更喜欢自己处理状态代码。永远不要假设在 QA 中有效的 http 通信会在生产过程中保持完美:要防御。

在所有这些附带条件之后,您的 json 可能看起来像:[{"name": "bobbins driver", "latlng": [90, 180], "population": "012345"}, {"name": "barbara", "latlng": [0, -180], "population": "65432"}...].

请参阅文档了解 aLatLng是什么。

至于你的跟进,这个话题太宽泛了。现在,使用 latlng 参数对地图图块进行许多请求,并让您的服务器仅发送附近的图块。随着事情变得越来越有趣,如果您需要实时更新,有一些为此设计的协议,或者您可以使用具有高瓷砖刷新率的谷歌地图“瓷砖服务器”模式 - 0UrlTileProvider开始,或者这可以成为未来的SO问题。

祝你好运。

于 2013-07-01T21:36:48.273 回答