我在我的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开发新手,非常感谢任何帮助。提前谢谢你!
答案 0 :(得分:1)
根据Android guidelines我认为你应该使用AsyncTask代替“retrieveLocations”,而不是自己创建一个线程connect to a network.。