-1

I need to use a bitmap image as Marker.icon .

i have 2 AsyncTask class , MyTask and BitmapTask , the first one retrieve a JSONArray with value { double,double,string,string = url of my bitmap icon } and the second one use the last string of JSONArray (in other words the url) as parameter the get the bitmap icon .

Trying to get it this way failed :

MyTask class

      public class MyTask extends AsyncTask<String, String, String> {

    @Override
    protected void onPreExecute() {
    //          updateDisplay("Starting task");

        //tasks.add(this);
    }

    @Override
    protected String doInBackground(String... params) {

        String content = HttpManager.getData(params[0]);
        return content;
    }


  @Override
  protected void onPostExecute(String result) {
       double  JsonLat = 0.0  ;
       double  Jsonlong = 0.0 ;
       String  JsonName = "" ;
       String  JsonIconurl = "" ;
       Bitmap  JsonIcon = null;



        try {

            JSONArray cast = new JSONArray(result);
            BitmapTask icontask = new BitmapTask();
            for (int i=0; i<cast.length(); i++) {

                JSONObject Marker = new JSONObject(cast.get(i).toString());
                stringJsonLat = Marker.getString("latitude");
                stringJsonLng = Marker.getString("longitude");
                Jsonlong = Double.parseDouble(stringJsonLng);
                JsonLat = Double.parseDouble(stringJsonLat);
                JsonName = Marker.get("title").toString();
                JsonIconurl = Marker.get("icone").toString();

                 icontask.execute(JsonIconurl);
                 JsonIcon = icontask.doInBackground();

                if (InArea(JsonLat,Jsonlong)) {
                    mMap.addMarker(new MarkerOptions().position(new LatLng(JsonLat,Jsonlong)).title(JsonName).icon(BitmapDescriptorFactory.fromBitmap(JsonIcon)));

                }

            }

        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

    @Override
    protected void onProgressUpdate(String... values) {
    //          updateDisplay(values[0]);
    }

}

BitmapTask class

 public class BitmapTask extends AsyncTask<String, Void, Bitmap>{
    @Override
    protected Bitmap doInBackground(String... params) {
        Bitmap bmImg = null;
        try {
            URL url = new URL(params[0]);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoInput(true);
            conn.connect();
            InputStream is = conn.getInputStream();
            bmImg = BitmapFactory.decodeStream(is);
        }
        catch (IOException e)
        {
            e.printStackTrace();
            bmImg = null;
        }

        return bmImg;
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        super.onPostExecute(result);
        // TODO: do what you need with resulting bitmap - add marker to map
    }
};

3 Answers3

1

I suggest to make all the download operations in one AsyncTask (downloading the JSON string and the icon).

You need to have a class to wrap the download results:

Wrapper class:

private class JSONMarkerObject {
    double lat = 0.0;
    double lng = 0.0;
    String name = "";
    String iconURL = "";
    Bitmap iconBitmap = null;
}

Helper functions:

private ArrayList<JSONMarkerObject> parseJSON(String content) {

    ArrayList<JSONMarkerObject> markers = new ArrayList<MainActivity.JSONMarkerObject>();
    try {
        JSONArray array = new JSONArray(content);
        for (int i = 0; i < array.length(); i++) {
            JSONObject Marker = array.getJSONObject(i);
            JSONMarkerObject obj = new JSONMarkerObject();

            obj.lat = Double.parseDouble(Marker.getString("latitude"));
            obj.lng = Double.parseDouble(Marker.getString("longitude"));
            obj.name = Marker.getString("title");
            obj.iconURL = Marker.getString("icone");
            obj.iconBitmap = downloadIcon(obj.iconURL);
            markers.add(obj);
        }

    } catch (NumberFormatException e) {
        e.printStackTrace();
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return markers;

}

private Bitmap downloadIcon(String iconURL) {
    Bitmap bmImg = null;
    try {
        URL url = new URL(iconURL);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setDoInput(true);
        conn.connect();
        InputStream is = conn.getInputStream();
        bmImg = BitmapFactory.decodeStream(is);
    } catch (IOException e) {
        e.printStackTrace();
        bmImg = null;
    }

    return bmImg;
}

Download task:

public class MyTask extends AsyncTask<String, String, ArrayList<JSONMarkerObject>> {

    @Override
    protected void onPreExecute() {

    }

    @Override
    protected ArrayList<JSONMarkerObject> doInBackground(String... params) {

        String content = HttpManager.getData(params[0]);
        ArrayList<JSONMarkerObject> markers = parseJSON(content);
        return markers;
    }

    @Override
    protected void onPostExecute(ArrayList<JSONMarkerObject> result) {

        try {

            for (int i = 0; i < result.size(); i++) {

                JSONMarkerObject obj = result.get(i);

                if (InArea(obj.lat, obj.lng)) {
                    mMap.addMarker(new MarkerOptions().position(new LatLng(obj.lat, obj.lng)).title(obj.name)
                            .icon(BitmapDescriptorFactory.fromBitmap(obj.iconBitmap)));

                }
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onProgressUpdate(String... values) {
        // updateDisplay(values[0]);
    }

}

I see no need for downloading the text first in a single task, and then downloading the icons in another single task, because the markers will appear on the map when the icons are downloaded, so there is no problem in downloading everything in one shot.

Edit

The simplest way to add an info window is to set the title() and snippet() methods of the corresponding marker.

mMap.addMarker(new MarkerOptions()
.position(new LatLng(obj.lat, obj.lng))
.title(obj.name)
.icon(BitmapDescriptorFactory.fromBitmap(obj.iconBitmap)))
.setTitle(obj.name)
.snippet(obj.name);
Adham Enaya
  • 780
  • 1
  • 11
  • 29
  • can i use a infowindow for each marker i get this way ? – Ismaili Alaoui smail Apr 24 '15 at 16:13
  • @IsmailiAlaouismail Yes you can – Adham Enaya Apr 26 '15 at 06:59
  • infowindow seems work only on marker object , contrariwise , i need to use it on my JSONMarkerObject – Ismaili Alaoui smail Apr 27 '15 at 08:55
  • You don't got what i want to mean exactly ! My JSONMarkerObject contain additional information than a normal Marker Object ! i already think about using snippet to contain all this information and trying to manipulate the string to get this information ....... – Ismaili Alaoui smail Apr 27 '15 at 10:07
  • @IsmailiAlaouismail If if got you, I think you need to add a new attribute in the class `JSONMarkerObject` and use it exactly like how we used the other variables. – Adham Enaya Apr 27 '15 at 13:44
  • this is what i tough before , but the infowindow works on marker object only , this is why i will put every extra information as string in the snippet and i will parse this string by using a split ;) – Ismaili Alaoui smail Apr 27 '15 at 14:24
  • @IsmailiAlaouismail If you want to have more multiple properties to be displayed in the WinowInfo you can create an instance of you object (that contains your data) in the JSONMarkerObject object. – Adham Enaya Aug 09 '15 at 06:46
0

Run your MyTask AsyncTask, and in onPostExecute of MyTask class run your BitmapTask AsyncTask.

MyTask's onPostExecute

@Override
protected void onPostExecute(String result) {
     new BitmapTask().execute(params);   //params if any
}
Yauraw Gadav
  • 1,706
  • 1
  • 18
  • 39
0

Inside your BitmapTask class, include the following:

public interface BitmapTaskListener{
    public void onResult(Bitmap bmImg);
}

private BitmapTaskListener bitmapListener;

public void setBitmapListener (BitmapTaskListener listener){
    bitmapListener = listener;
}

Of course you don't have to use the same names. Your onPostExecute should be:

@Override
protected void onPostExecute(Bitmap result) {
    if (bitmapListener!=null)
        bitmapListener.onResult(result);
}

And finally, you should use the setBitmapListener to set the listener. You will have to implement the method onResult where you will do whatever it is you want with the Bitmap you got.

Edit: Actually, you are calling the BitmapTask from within MyTask. You can either propagate the listener or I would suggest getting the result from the first task in your UI and initialize from there the second task.

Also, don't this: JsonIcon = icontask.doInBackground();. doInBackground is called internally, after onPreExecute. You should start the task simply by task.execute(params)