CS 436 Lecture 23 – Maps
November 18, 2014 by Chris Johnson. Filed under cs436, fall 2014, lectures.
Code
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<fragment
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.MapFragment"/>
<ProgressBar
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progressBar"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:visibility="gone"/>
</RelativeLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.twodee.donde">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name="org.twodee.donde.MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="YOUR-API-KEY"/>
</application>
</manifest>
Utilities.java
package org.twodee.donde;
import org.json.JSONException;
import java.io.IOException;
import java.io.InputStream;
public class Utilities {
public static String slurp(InputStream is) throws IOException, JSONException {
StringBuilder sb = new StringBuilder();
byte[] bytes = new byte[1024];
int nBytes;
while ((nBytes = is.read(bytes)) > 0) {
sb.append(new String(bytes, 0, nBytes));
}
return sb.toString();
}
}
Placemark.java
package org.twodee.donde;
import com.google.android.gms.maps.model.LatLng;
import java.util.ArrayList;
public class Placemark {
private ArrayList<String> names;
private String placeName;
private LatLng location;
public Placemark(String placeName) {
this.names = new ArrayList<String>();
this.placeName = placeName;
}
public ArrayList<String> getNames() {
return names;
}
public void addName(String name) {
names.add(name);
}
public String getPlaceName() {
return placeName;
}
public LatLng getLocation() {
return location;
}
public void setLocation(LatLng location) {
this.location = location;
}
public String toString() {
return String.format("%s|%s|%s", names.toString(), placeName, location);
}
}
MainActivity.java
package org.twodee.donde;
import android.app.Activity;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
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.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
public class MainActivity extends Activity {
private GoogleMap map;
private ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
MapFragment mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
map = mapFragment.getMap();
map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
new PlacemarkLoader().execute();
}
class PlacemarkLoader extends AsyncTask<Void, Placemark, ArrayList<Placemark>> {
@Override
protected ArrayList<Placemark> doInBackground(Void... params) {
try {
HashMap<String, Placemark> placeToPlacemarks = new HashMap<String, Placemark>();
File csv = new File(Environment.getExternalStorageDirectory(), "donde.csv");
loadPlacemarks(csv, placeToPlacemarks);
ArrayList<Placemark> placemarks = new ArrayList<Placemark>(placeToPlacemarks.values());
locatePlacemarks(placemarks);
return placemarks;
} catch (Exception e) {
Log.e("FOO", e.getMessage());
}
return null;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
}
@Override
protected void onPostExecute(ArrayList<Placemark> placemarks) {
super.onPostExecute(placemarks);
progressBar.setVisibility(View.GONE);
}
@Override
protected void onProgressUpdate(Placemark... values) {
super.onProgressUpdate(values);
Placemark placemark = values[0];
Log.d("FOO", placemark.toString());
if (placemark.getLocation() != null) {
MarkerOptions marker = new MarkerOptions();
marker.position(placemark.getLocation());
marker.title(placemark.getPlaceName());
marker.snippet(placemark.getNames().toString());
map.addMarker(marker);
}
}
private void loadPlacemarks(File csv,
HashMap<String, Placemark> placeToPlacemarks) throws FileNotFoundException {
Scanner in = new Scanner(csv);
while (in.hasNextLine()) {
String[] fields = in.nextLine().split("\\|");
String name = fields[0];
String place = fields[1];
Placemark placemark = placeToPlacemarks.get(place);
if (placemark == null) {
placemark = new Placemark(place);
placeToPlacemarks.put(place, placemark);
}
placemark.addName(name);
}
in.close();
Log.d("FOO", "LOAD: " + placeToPlacemarks.toString());
}
private void locatePlacemarks(ArrayList<Placemark> placemarks) throws IOException, JSONException, InterruptedException {
Log.d("FOO", "LOCATE: " + placemarks.toString());
for (Placemark placemark : placemarks) {
Uri.Builder builder = new Uri.Builder();
builder.scheme("https");
builder.authority("maps.googleapis.com");
builder.appendEncodedPath("maps/api/geocode/json");
builder.appendQueryParameter("address", placemark.getPlaceName());
String urlString = builder.build().toString();
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
InputStream is = connection.getInputStream();
String body = Utilities.slurp(is);
JSONObject json = new JSONObject(body);
JSONArray results = json.getJSONArray("results");
JSONObject result = results.getJSONObject(0);
JSONObject geometry = result.getJSONObject("geometry");
JSONObject location = geometry.getJSONObject("location");
double latitude = location.getDouble("lat");
double longitude = location.getDouble("lng");
LatLng ll = new LatLng(latitude, longitude);
placemark.setLocation(ll);
publishProgress(placemark);
Thread.sleep(300);
}
}
}
}