Question

So first I'll explain what I'm trying to do with my Android App. The app allows the user to enter their vehicle information and an origin and destination. The user will then click the "Plan my Road Trip" button which will send them to page two that has a Google Map on it. While on the second page, the app will then take the origin and destination, put them into a Google Directions URL i.e

http://maps.googleapis.com/maps/api/directions/json?origin=90210&destination=02115&sensor=false&units=imperial

and then parse the "overview_polyline" JSONObject into a LatLng ArrayList. That ArrayList will be used to draw the path between the origin and destination using a Polyline.

As you can see below in the screen shot, the user has 4 spinners to select from which is irrelevant to this question. The user also has an Origin EditText box and a Destination EditText box that I mentioned above.

enter image description here

My question is as follows. When I click the button that takes me to page two, the app crashes. It doesn't even get past setContentView(R.layout.page2);. I've tested the JSON parsing in another project and there is nothing wrong with the parsing code, but for some reason it is not working in this situation. I am using an AsyncTask class as well. Is this the way to go? If not, would it be possible to show an example of the right way to do this? Also, as you will see in the code, If I manually add points to the ArrayList instead of having it be filled dynamically, the map loads and the Polylines work.

Here is the code...

Page2Activity.java

 public class Page2Activity extends FragmentActivity {

GoogleMap map;
//Non Dynamic ArrayList
//ArrayList<LatLng> points = new ArrayList<LatLng>();

//Dynamic ArrayList
ArrayList<LatLng> poly = new ArrayList<LatLng>();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.page2);

    //Async Task here
    new populatePolys().execute();


    //This works if I manually add the points. Non Dynamic. But obviously this is not what I want.

//      SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
//      map = fm.getMap();
//       
//      points.add(new LatLng(51.5, -0.1));
//      points.add(new LatLng(40.7, -74.0));
//      points.add(new LatLng(30.2, -80.1));
//      Polyline line = map.addPolyline(new PolylineOptions()
//      .addAll(points)
//      .width(5)
//      .color(Color.RED));
}

 class populatePolys extends AsyncTask<Void, Void, ArrayList<LatLng>> {
    protected ArrayList<LatLng> doInBackground(Void... params) {

        //Creating a new instance of the Activity for the first page
        //The first page holds the user's input for the Origin EditText box and Destination EditText box.
        MainActivity mA = new MainActivity();
        String pointA = "";
        String pointB = "";
        try {
            //Grabbing the user input from the main page.
            pointA = URLEncoder.encode(mA.originEditText.getText().toString(), "UTF-8");
            pointB = URLEncoder.encode(mA.destinationEditText.getText().toString(), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        JSONObject jsonObject = null;
        String status = "INVALID_REQUEST";

        try {
            jsonObject = readJsonFromUrl("http://maps.googleapis.com/maps/api/directions/json?origin=" + pointA + "&destination=" + pointB + "&sensor=false&units=imperial");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }

        if(status.equals("OK")){
            //Directions entered are correct.
            JSONObject polyArray;
            JSONArray routesArray;
            try {
                //Grabbing the Polyline points String. This does pull the correct value.
                //Parsing is correct.
                routesArray = jsonObject.getJSONArray("routes");
                JSONObject route = routesArray.getJSONObject(0);
                polyArray = route.getJSONObject("overview_polyline");
                String polyPoints = polyArray.getString("points");

                //Passing the Polyline points from the JSON file I get from the Google Directions URL into a decoder.
                decodePoly(polyPoints);
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return poly;
    }

    protected void onPostExecute(NodeList makeList) {

        //Adding the Dynamic ArrayList "poly" into Polylines.

        SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        map = fm.getMap();

        Polyline line = map.addPolyline(new PolylineOptions()
        .addAll(poly)
        .width(5)
        .color(Color.RED));

    }


}


/*
 * LatLng Decoder for polyline
 */

private List<LatLng> decodePoly(String encoded) {

    int index = 0, len = encoded.length();
    int lat = 0, lng = 0;

    while (index < len) {
        int b, shift = 0, result = 0;
        do {
            b = encoded.charAt(index++) - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
        lat += dlat;

        shift = 0;
        result = 0;
        do {
            b = encoded.charAt(index++) - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
        lng += dlng;

        LatLng p = new LatLng((int) (((double) lat / 1E5) * 1E6),
             (int) (((double) lng / 1E5) * 1E6));
        poly.add(p);
    }

    return poly;
}

/*
 * Methods to parse the JSON when grabbing from Google Directions API
 */

private static String readAll(Reader rd) throws IOException {
    StringBuilder sb = new StringBuilder();
    int cp;
    while ((cp = rd.read()) != -1) {
      sb.append((char) cp);
    }
    return sb.toString();
}

public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {

      InputStream is = new URL(url).openStream();
        try {
          BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
          String jsonText = readAll(rd);
          JSONObject jsonObject = new JSONObject(jsonText);
          return jsonObject;
        } finally {
          is.close();
        }   
  }



}

Code for page2.xml.... UPDATED (see edits for older code)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
    <fragment
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.google.android.gms.maps.SupportMapFragment"/>
</LinearLayout>

Updated LogCat...

07-10 11:33:09.193: E/AndroidRuntime(8130): FATAL EXCEPTION: AsyncTask #5
07-10 11:33:09.193: E/AndroidRuntime(8130): java.lang.RuntimeException: An error occured while executing doInBackground()
07-10 11:33:09.193: E/AndroidRuntime(8130):     at android.os.AsyncTask$3.done(AsyncTask.java:299)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at java.lang.Thread.run(Thread.java:856)
07-10 11:33:09.193: E/AndroidRuntime(8130): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
07-10 11:33:09.193: E/AndroidRuntime(8130):     at android.os.Handler.<init>(Handler.java:121)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at android.app.Activity.<init>(Activity.java:763)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at com.example.roadtripplanner.MainActivity.<init>(MainActivity.java:51)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at com.example.roadtripplanner.Page2Activity$populatePolys.doInBackground(Page2Activity.java:74)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at com.example.roadtripplanner.Page2Activity$populatePolys.doInBackground(Page2Activity.java:1)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at android.os.AsyncTask$2.call(AsyncTask.java:287)
07-10 11:33:09.193: E/AndroidRuntime(8130):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
07-10 11:33:09.193: E/AndroidRuntime(8130):     ... 5 more

To see the old logcat, see edits

Please ask if you need any more code.

Was it helpful?

Solution

well look at what the error says Caused by: java.lang.ClassCastException: com.google.android.gms.maps.MapFragment cannot be cast to android.support.v4.app.Fragment

I believe you are using the wrong class in your xml

android:name="com.google.android.gms.maps.MapFragment"

should be

android:name="com.google.android.gms.maps.SupportMapFragment"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top