2

I am trying to create markers on google maps, based on if the plane has departed yet. I have checked and everything works okay until it tries to create the planes.

Here is the code:

    package com.fly.plane;

import java.sql.Time;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

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

import com.fly.plane.R;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.Projection;
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 android.R.array;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.graphics.Point;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v4.app.FragmentActivity;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.TextView;

public class MyMapActivity extends ListActivity {

    private ProgressDialog pDialog;

    // URL to get data JSON
    private static String url = "http://edmundgentle.com/snippets/flights/api.php";

    // JSON Node speeds
    private static final String TAG_data = "data";
    private static final String TAG_BEARING = "bearing";
    private static final String TAG_SPEED = "speed";
    private static final String TAG_ARR = "arr";
    private static final String TAG_ARR_TIME = "time";
    private static final String TAG_ARR_LAT = "lat";
    private static final String TAG_ARR_LON = "lon";
    private static final String TAG_DEP = "dep";
    private static final String TAG_DEP_TIME = "time";
    private static final String TAG_DEP_LAT = "lat";
    private static final String TAG_DEP_LON = "lon";

    // data JSONArray
    JSONArray data = null;

    // Hashmap for ListView
    ArrayList<HashMap<String, Double>> contactList;

    // Hashmap for ListView
    ArrayList<Double> ct;

    List<Marker> markers = new ArrayList<Marker>();

    //final Handler handler;
    private GoogleMap mMap; 
    public static final LatLng dest(String alt,String aln, int i){
        final double latitude = Double.parseDouble(alt);
        final double longitude = Double.parseDouble(aln);
        return new LatLng(latitude, longitude);
    }
    public double latt = -15.48169437461;
    public double lng = -15.48169437461;
    public ArrayList<Integer> dLat;

    public String[] markerList;

    public String dlat;
    public String dlon;
    public String alat;
    public String alon;

    private int count;

    public boolean wait = true;

    //private Button startB;
    public TextView text;

    Timer timing;
    double time = 600;
    double timm = 1;

    long timer = 18000000;
    long newTime;
    TextView tv, test;
    Thread t;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_map);

        contactList = new ArrayList<HashMap<String, Double>>();

        ct = new ArrayList<Double>();

        //ListView lv = getListView();

      //create markers  
        new Getdata().execute();
        // timer showing time of day in fast time
        t = new Thread() {

              @Override
              public void run() {
                try {
                  while (!isInterrupted()) {
                    Thread.sleep(600);
                    runOnUiThread(new Runnable() {
                      @Override
                      public void run() {
                          timer = timer +60000;
                          if (timer >= 64000000) timer = 18000000;
                          newTime = timer;
                        // update TextView here!
                         //String time = "HH:mm:ss";
                         //tv.setText(DateFormat.format(time , timer));
                         tv.setText(Double.toString(time));
                         test.setText(Double.toString(timm));
                         //tv.setText(Double.toString(contactList.get(20).get("time")));
                         //Timer();
                      }
                    });
                  }
                } catch (InterruptedException e) {
                }
              }
            };

            tv = new TextView(this); 
            test = new TextView(this); 
            tv=(TextView)findViewById(R.id.timer); 
            test=(TextView)findViewById(R.id.test); 
         // run the mUpdateUITimerTask's run() method in 10 seconds from now
    }    


    // animate each plane
    public void animateMarker(final Marker marker , final LatLng toPosition,
            final boolean hideMarker, final double spd) {

        float speed = (float) spd;// Float.parseFloat(spd);
        final Handler handler = new Handler();
        final long start = SystemClock.uptimeMillis();
        Projection proj = mMap.getProjection();
        Point startPoint = proj.toScreenLocation(marker.getPosition());
        final LatLng startLatLng = proj.fromScreenLocation(startPoint);
        final float duration = 10 * speed;
        final Interpolator interpolator = new LinearInterpolator();
        handler.post(new Runnable() {
            @Override
            public void run() {
                long elapsed = SystemClock.uptimeMillis() - start;
                float t = interpolator.getInterpolation((float) ((float) elapsed
                        / duration));
                double lng = t * toPosition.longitude + (1 - t)
                        * startLatLng.longitude;
                double lat = t * toPosition.latitude + (1 - t)
                        * startLatLng.latitude;
                marker.setPosition(new LatLng(lat, lng));
                if (t < 1.0) {
                    // Post again 16ms later.
                    handler.postDelayed(this, 16);
                } else {
                    handler.postDelayed(this, 16);
                    if (hideMarker) {
                        marker.setVisible(false);
                    } else {
                        marker.setVisible(true);
                    }
                }
            }
        });
    }

    public void Timer(){
        //TimerTask tasknew = new TimerTask();
        timing = new Timer();
        timing.schedule(new CreateMarker(), 1000, 1000);
    }

    public void DrawMarker(){
        mMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
                //animateMarker(markers.get(i), dest(alt,aln,i) , true, spd);
            /*Marker marker =  mMap.addMarker(new MarkerOptions()
            .position(new LatLng(0, 0))
            .title("Hello world")
            .icon(BitmapDescriptorFactory.fromResource(R.drawable.planemarker)));
            //markers.add(marker);          
            //animateMarker(markers.get(i), dest(alt,aln,i) , true, spd);*/
    }


    public String calcCurPos(double curlat, double curlon, double deslat, double deslon, double avgSpd, double bearing){

        double distance = avgSpd * 0.0167;

        // check if degrees or radians
        //deslat = distance * Math.cosh(bearing);

        bearing = bearing * Math.PI / 180;

        int radius = 6371;

        double nextLat = Math.asin(Math.sin(curlat)* Math.cos(distance/radius)
                + Math.cos(curlat)*Math.sin(distance/radius)*Math.cos(bearing));

        double nextLon = curlon + Math.atan2(Math.sin(bearing)* Math.sin(distance/ radius)
                * Math.cos(curlat), Math.cos(distance/radius)-Math.sin(curlat) * Math.sin(nextLat));

        nextLat = (nextLat * 180) / Math.PI;
        nextLon = (nextLon * 180) / Math.PI;


        /**
         * Warning might want to convert them to string prior to return.
         */
        return nextLat + ";" + nextLon;
    }

public class CreateMarker extends TimerTask{

    @Override
    public void run() {
        // TODO Auto-generated method stub

        if (time >= 2400){
            time=0;
        }

        time += 500;
        //mMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();

        for (int i =0; i < 100;i++){
            // get data from array list
            double depLat = contactList.get(i).get("dlat");
            double depLon =  contactList.get(i).get("dlon");
            double arLat = contactList.get(i).get("alat");
            double arLon =  contactList.get(i).get("alon");
            double spd = contactList.get(i).get("speed");
            double dTime = contactList.get(i).get("time");
            double curLat = contactList.get(i).get("clat");
            double curLon = contactList.get(i).get("clon");
            double bearing = contactList.get(i).get("bearing");

            //int dTime = Integer.parseInt(dtime);

            double oldLat = curLat;

            if (time >= dTime)
            {
                if (curLat > arLat || curLat < 0){
                    String latlng = calcCurPos(curLat, curLon, arLat, arLon ,spd, bearing );

                    String[] values = latlng.split(";");

                    curLat = Double.parseDouble(values[0]);
                    curLon = Double.parseDouble(values[1]);

                    final LatLng position = new LatLng(curLat,curLon);

                        //DrawMarker();

                    //animateMarker(markers.get(i), position , true, spd);
                    try{
                    if (markers != null || markers.get(i) == null){
                        //timm += 1;
                        timm += 1;
                        final Marker marker =  mMap.addMarker(new MarkerOptions()
                        .position(new LatLng(0, 0))
                        .title("Hello world")
                        .icon(BitmapDescriptorFactory.fromResource(R.drawable.planemarker)));
                        markers.add(marker);
                        //DrawMarker();
                        //Marker marker =  mMap.addMarker(mo);

                        //animateMarker(markers.get(i), dest(alt,aln,i) , true, spd);

                    }
                    else{

                        //Marker marker = markers.get(i);

                        //marker.setPosition(position);
                        //animateMarker(markers.get(i), position , true, spd);
                    }
                    }
                    catch(NullPointerException npe)
                    {
                        //do something else
                    }

                }
            }

            HashMap<String, String> contact = new HashMap<String, String>();

            contact.put("bearing", bearing);
            contact.put("speed", spd);
            contact.put("time", dtime);
            contact.put("alat", alt);
            contact.put("alon", aln);
            contact.put("dlat", dlat);
            contact.put("dlon", dlon);    
            contact.put("clat", dlat);
            contact.put("clon", dlon);

            contactList.add(contact);*/

        }


        //return null;

    }
    }


    /**
     * Async task class to get json by making HTTP call
     * */
    private class Getdata extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            // Showing progress dialog
            pDialog = new ProgressDialog(MyMapActivity.this);
            pDialog.setMessage("Please wait...");
            pDialog.setCancelable(false);
            pDialog.show();

        }

        @Override
        protected Void doInBackground(Void... arg0) {
            // Creating service handler class instance
            HTTPHandler sh = new HTTPHandler();

            // Making a request to url and getting response
            String jsonStr = sh.makeServiceCall(url, HTTPHandler.GET);

            Log.d("Response: ", "> " + jsonStr);
            boolean limit = false;
            if (jsonStr != null  ||  limit == false) {
                try {
                    JSONObject jsonObj = new JSONObject(jsonStr);

                    // Getting JSON Array node
                    data = jsonObj.getJSONArray(TAG_data);

                    // looping through All data
                    for (int i = 0; i < data.length(); i++) {
                        JSONObject c = data.getJSONObject(i);

                        String bearing = c.getString(TAG_BEARING);
                        String spd = c.getString(TAG_SPEED);
                        // departure node is JSON Object
                        JSONObject dep = c.getJSONObject(TAG_DEP);
                        String dtime = dep.getString(TAG_DEP_TIME);
                        //String dlat = dep.getString(TAG_DEP_LAT);
                        //String dlon = dep.getString(TAG_DEP_LON);
                        dlat = dep.getString(TAG_DEP_LAT);
                        dlon = dep.getString(TAG_DEP_LON);


                        // replace : and last 2 0's from departure time
                        dtime = dtime.replaceAll(":","");
                        //dtime.replaceAll(";","");
                        dtime = dtime.substring(0,dtime.length()-2);

                        // arrival node is JSON Object
                        JSONObject arr = c.getJSONObject(TAG_ARR);

                        String alt = arr.getString(TAG_ARR_LAT);
                        String aln = arr.getString(TAG_ARR_LON);

                        // convert data positions to doubles for Google Maps + stuff

                        double brng = Double.parseDouble(bearing);
                        brng = brng * Math.PI / 180;

                        double speed = Double.parseDouble(spd);
                        //double brng = Double.parseDouble(bearing);
                        double dLatitude = Double.parseDouble(dlat);
                        double dLongitude = Double.parseDouble(dlon);
                        double aLatitude = Double.parseDouble(alt);
                        double aLongitude = Double.parseDouble(aln);
                        double cLatitude = Double.parseDouble(dlat);
                        double cLongitude = Double.parseDouble(dlon);
                        double dtme = Double.parseDouble(dtime);

                        // tmp hashmap for single contact
                        HashMap<String, Double> contact = new HashMap<String, Double>();

                        contact.put("bearing", brng);
                        contact.put("speed", speed);
                        contact.put("time", dtme);
                        contact.put("alat", aLatitude);
                        contact.put("alon", aLongitude);
                        contact.put("dlat", dLatitude);
                        contact.put("dlon", dLongitude);    
                        contact.put("clat", cLatitude);
                        contact.put("clon", cLongitude);

                        // adding contact to contact list
                        contactList.add(contact);

                        if (i== data.length()){
                            wait = false;
                        }
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            } else {
                Log.e("ServiceHandler", "Couldn't get any data from the url");
            }

            return null;
        }
        // spawns planes when json loaded
        @Override
        protected void onPostExecute(Void result) {
            Timer();
            t.start();
            super.onPostExecute(result);
            // Dismiss the progress dialog
            if (pDialog.isShowing())
                pDialog.dismiss();            
            // use plane api for latlon
            mMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();

        }}


    }

Here is the error codes:

02-26 18:51:21.747: W/dalvikvm(17225): threadid=21: thread exiting with uncaught exception (group=0x41930898)
02-26 18:51:21.757: E/AndroidRuntime(17225): FATAL EXCEPTION: Timer-0
02-26 18:51:21.757: E/AndroidRuntime(17225): java.lang.IllegalStateException: Not on the main thread
02-26 18:51:21.757: E/AndroidRuntime(17225):    at maps.k.o.b(Unknown Source)
02-26 18:51:21.757: E/AndroidRuntime(17225):    at maps.i.g.b(Unknown Source)
02-26 18:51:21.757: E/AndroidRuntime(17225):    at maps.e.al.a(Unknown Source)
02-26 18:51:21.757: E/AndroidRuntime(17225):    at eif.onTransact(SourceFile:167)
02-26 18:51:21.757: E/AndroidRuntime(17225):    at android.os.Binder.transact(Binder.java:347)
02-26 18:51:21.757: E/AndroidRuntime(17225):    at com.google.android.gms.maps.internal.IGoogleMapDelegate$a$a.addMarker(Unknown Source)
02-26 18:51:21.757: E/AndroidRuntime(17225):    at com.google.android.gms.maps.GoogleMap.addMarker(Unknown Source)
02-26 18:51:21.757: E/AndroidRuntime(17225):    at com.fly.plane.MyMapActivity$CreateMarker.run(MyMapActivity.java:298)
02-26 18:51:21.757: E/AndroidRuntime(17225):    at java.util.Timer$TimerImpl.run(Timer.java:284)

The CreateMarker class handles the checks for gathering and comparing the data from the API, and should spawn planes if their departure time is the same as the time of day (just a counter).

The error seems to point towards it not liking the marker being created in the class, but i have tried creating a method in the main class to spawn the marker, and just running that method from the CreateMarker class when a plane should be drawn, but i get errors in that.

Any help would be appreciated.

Phil

n1k1ch
  • 2,594
  • 3
  • 31
  • 35
Phil
  • 83
  • 1
  • 2
  • 15

1 Answers1

4

Wrap

final Marker marker =  mMap.addMarker(new MarkerOptions()
            .position(new LatLng(0, 0))
            .title("Hello world")
            .icon(BitmapDescriptorFactory.fromResource(R.drawable.planemarker)));
markers.add(marker);

In runOnUiThread:

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        final Marker marker =  mMap.addMarker(new MarkerOptions()
            .position(new LatLng(0, 0))
            .title("Hello world")
            .icon(BitmapDescriptorFactory.fromResource(R.drawable.planemarker)));
        markers.add(marker);
    }
});
n1k1ch
  • 2,594
  • 3
  • 31
  • 35
  • Thanks, that works for allowing me to add markers! however, there are a few hacks i put in because i got stuck at other parts. the if (markers != null || markers.get(i) == null){} part is meant to be iff the markers[i] is null create a new marker, but just putting markers.get(i) causes it to crash. its meant to either add a new plane if it doesnt exist, or update its position if it does exist – Phil Feb 26 '14 at 20:51
  • 1
    Please, ask separate question and don't chameleonize current (but as an short answer -Your [`markers.get()`](http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#get(int)) probably throws `IndexOutOfBoundsException`. You'd better to use `Set markers = new HashSet()` instead of `List` and change logic accordingly.) – n1k1ch Feb 26 '14 at 21:14
  • Okay, didn't want to make another thread as it seems like spam, but if that's procedure then ill remember it! thanks for help! – Phil Feb 26 '14 at 21:19
  • I am happy to help by extending this answer in case you next question(s) is closely related to the original problem. But in my opinion, you now faced problem different from `IllegalStateException` :) and it deserves a new question about *collection which stores unique elements* – n1k1ch Feb 26 '14 at 21:29