使用JSON并为Android Maps API加载时创建标记

时间:2016-06-02 20:06:51

标签: android arrays json google-maps google-maps-markers

我在我的android项目中实现谷歌地图,它从URL中检索JSON数据以在地图中绘制标记,同时它还有一个搜索选项,其中包含google places API的自动完成地址,这里是我的代码。

import android.content.Context;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;

import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.maps.CameraUpdate;
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.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
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.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class MapsActivity extends FragmentActivity implements AdapterView.OnItemClickListener {

    LocationAddress add=new LocationAddress();
    DashboardActivity dObj=new DashboardActivity();

    public void onClickHome (View v)
    {
        final Intent intent = new Intent(getApplicationContext(), DashboardActivity.class);
        startActivity(intent);
    }

    class MyInfoWindowAdapter implements GoogleMap.InfoWindowAdapter {

        private final View myContentsView;

        MyInfoWindowAdapter(){
            myContentsView = getLayoutInflater().inflate(R.layout.custom_info_contents, null);
        }

        @Override
        public View getInfoContents(Marker arg0) {
            displayView(arg0);
            return myContentsView;
        }

        @Override
        public View getInfoWindow(Marker arg0) {

            return null;
        }

        public void displayView(Marker arg0) {

            String[] contents=arg0.getTitle().split("@");
            String title=contents[0];
            String address=contents[1];

            ((TextView)myContentsView.findViewById(R.id.title)).setText(title);
            ((TextView)myContentsView.findViewById(R.id.snippet)).setText(address);

        }

    }

   private static final String LOG_TAG = "myApp";
   private static final String SERVICE_URL = "JSON_DATA_URL";
   private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place";
   private static final String TYPE_AUTOCOMPLETE = "/autocomplete";
   private static final String OUT_JSON = "/json";

    //------------ make your specific key ------------
    private static final String API_KEY = "AIzaSyDKUpzHkox5q5-pcNYmRS-UT7izEvd6WtQ";

   protected GoogleMap map;
   private GoogleApiClient client;
   TextView latlongLocation;
   Marker marker;
   Button clear;
   AutoCompleteTextView autoCompView;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_maps);
       setUpMapIfNeeded();
       setTitleFromActivityLabel(R.id.title_text);

       client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();

       autoCompView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView);
       autoCompView.setAdapter(new GooglePlacesAutocompleteAdapter(this, R.layout.list_item));
       autoCompView.setOnItemClickListener(this);

       clear=(Button)findViewById(R.id.clear);
       clear.setOnClickListener(new View.OnClickListener() {
           public void onClick(View v) {
               autoCompView.setText("");
           }
       });

   }


    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
        String str = (String) adapterView.getItemAtPosition(position);
        Geocoder geocoder = new Geocoder(getApplicationContext());
        List<Address> addresses = null;
        try
        {

         //   removeSearchMarker();
            addresses = geocoder.getFromLocationName(str, 3);
            if (addresses != null && !addresses.equals(""))
                search(addresses);

        }
        catch (Exception e) {

        }
    }

    public static ArrayList<String> autocomplete(String input) {
        ArrayList<String> resultList = null;

        HttpURLConnection conn = null;
        StringBuilder jsonResults = new StringBuilder();
        try {
            StringBuilder sb = new StringBuilder(PLACES_API_BASE + TYPE_AUTOCOMPLETE + OUT_JSON);
            sb.append("?key=" + API_KEY);
            sb.append("&language" + "fa");
            sb.append("&components=country:af");
            sb.append("&input=" + URLEncoder.encode(input, "utf8"));

            URL url = new URL(sb.toString());

            System.out.println("URL: "+url);
            conn = (HttpURLConnection) url.openConnection();
            InputStreamReader in = new InputStreamReader(conn.getInputStream());

            int read;
            char[] buff = new char[1024];
            while ((read = in.read(buff)) != -1) {
                jsonResults.append(buff, 0, read);
            }
        } catch (MalformedURLException e) {
            Log.e(LOG_TAG, "Error processing Places API URL", e);
            return resultList;
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error connecting to Places API", e);
            return resultList;
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }

        try {
            JSONObject jsonObj = new JSONObject(jsonResults.toString());
            JSONArray predsJsonArray = jsonObj.getJSONArray("predictions");
            resultList = new ArrayList<String>(predsJsonArray.length());
            for (int i = 0; i < predsJsonArray.length(); i++) {
               System.out.println(predsJsonArray.getJSONObject(i).getString("description"));
                System.out.println("============================================================");
                resultList.add(predsJsonArray.getJSONObject(i).getString("description"));
            }
        } catch (JSONException e) {
            Log.e(LOG_TAG, "Cannot process JSON results", e);
        }

        return resultList;
    }

    class GooglePlacesAutocompleteAdapter extends ArrayAdapter<String> implements Filterable {
        private ArrayList<String> resultList;

        public GooglePlacesAutocompleteAdapter(Context context, int textViewResourceId) {
            super(context, textViewResourceId);
        }

        @Override
        public int getCount() {
            return resultList.size();
        }

        @Override
        public String getItem(int index) {
            return resultList.get(index);
        }

        @Override
        public Filter getFilter() {
            Filter filter = new Filter() {
                @Override
                protected FilterResults performFiltering(CharSequence constraint) {
                    FilterResults filterResults = new FilterResults();
                    if (constraint != null) {
                        resultList = autocomplete(constraint.toString());
                        filterResults.values = resultList;
                        filterResults.count = resultList.size();
                    }
                    return filterResults;
                }

                @Override
                protected void publishResults(CharSequence constraint, FilterResults results) {
                    if (results != null && results.count > 0) {
                        notifyDataSetChanged();
                    } else {
                        notifyDataSetInvalidated();
                    }
                }
            };
            return filter;
        }
    }

   protected void search(List<Address> addresses) {

   Address address = (Address) addresses.get(0);
    LatLng latLng = new LatLng(address.getLatitude(), address.getLongitude());

   // String  addressText = String.format("%s, %s", address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "", address.getCountryName());

    map.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    map.animateCamera(CameraUpdateFactory.zoomTo(14));
    latlongLocation.setText("Latitude:" + address.getLatitude() + ", Longitude:" + address.getLongitude());
   // map.setInfoWindowAdapter(new MyInfoWindowAdapter());
   }

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

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

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

    @Override
    protected void onDestroy() {
        map=null;
        super.onDestroy();
    }


   private void setUpMapIfNeeded() {
       if (map == null) {
           map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                   .getMap();
           if (map != null) {
               setUpMap();
           }
       }
   }

   private void setUpMap() {
       LatLng origin = new LatLng(34.520299, 69.179912);
       CameraUpdate panToOrigin = CameraUpdateFactory.newLatLng(origin);
       map.moveCamera(panToOrigin);
       map.animateCamera(CameraUpdateFactory.zoomTo(13), 400, null);
       map.getUiSettings();
       map.getUiSettings().setZoomControlsEnabled(true);
       map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
       map.setMyLocationEnabled(true);
       map.setInfoWindowAdapter(new MyInfoWindowAdapter());

       new Thread(new Runnable() {
           public void run() {
               try {
                   retrieveLocations();
               } catch (IOException e) {
                   Log.e(LOG_TAG, "Cannot retrive locations", e);
                   return;
               }
           }
       }).start();
   }

   protected void retrieveLocations() throws IOException {
       HttpURLConnection conn = null;
       final StringBuilder json = new StringBuilder();
       try {
           URL url = new URL(SERVICE_URL);
           conn = (HttpURLConnection) url.openConnection();
           InputStreamReader in = new InputStreamReader(conn.getInputStream());

           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();
           }
       }

       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 {

       JSONArray jsonArray = new JSONArray(json);
       for (int i = 0; i < jsonArray.length(); i++) {
           JSONObject jsonObj = jsonArray.getJSONObject(i);
           String address=add.getAddressFromLocation(jsonObj.getDouble("geolat"), jsonObj.getDouble("geolng"), getApplicationContext());

          String date=jsonObj.getString("posted_date");
           SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
           Date testDate=null;
           try{
               testDate=sdf.parse(date);
           }catch (Exception ex){
               ex.printStackTrace();
           }
           sdf=new SimpleDateFormat("EEE, d MMM yyyy  HH:mm aa");
           date=sdf.format(testDate);
           map.addMarker(new MarkerOptions()
                           .title(address.toString()+"@"+date)
                           .position(new LatLng(jsonObj.getDouble("geolat"), jsonObj.getDouble("geolng")
                           ))
                           .icon(BitmapDescriptorFactory.fromResource(R.drawable.icon3))
           );

       }
   }

    public void setTitleFromActivityLabel (int textViewId)
    {
        TextView tv = (TextView) findViewById (textViewId);
        if (tv != null) tv.setText (getTitle ());
    }

}

这些代码可以正常工作以从地图中的json数据中绘制标记,但问题是,当我开始此活动时,显示地图和标记需要花费太多时间,在此期间,所有内容都像冻结一样我可以&#39;回去或回家如果我在任何screan组件上多次点击它会使应用程序崩溃。

创建标记的json记录数量循环创建标记可能就像40-50条记录那样是扩展的可能性。所以我的问题是这个问题的原因是什么,还有其他方法可以快速显示地图中的标记而不会使应用程序崩溃吗?。

我应该提一下,我是Android开发新手,非常感谢任何帮助。提前谢谢你!

1 个答案:

答案 0 :(得分:1)

根据Android guidelines我认为你应该使用AsyncTask代替“retrieveLocations”,而不是自己创建一个线程connect to a network.