0

Im trying to scrape a websites to get the lat, lng using Jsoup to place into gmaps but i get a stack trace of

FATAL EXCEPTION: main
Process: au.com.industryresponsetraining.map, PID: 18842
 java.lang.NumberFormatException: Invalid double: ""

I have read it due to

you are parsing onCreate() value without putting any default value so the exception

except on my onCreate() is where my Jsoup is run. if I add something like

double myDouble;

String myString = ((EditText) findViewById(R.id.editText1)).getText().toString();

if (myString != null && !myString.equals("")) {
    myDouble = Double.valueOf(myString);
} else {
    myDouble = 0;
}

referenced from here my map ends out at sea.

My webpage has a valid lat, lng on it

here is my activity

package au.com.industryresponsetraining.map;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;


public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    String ln = "";
    String lt = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
        new Thread(new Runnable() {

            @Override
            public void run() {
                try {

                    //get the Document object from the site. Enter the link of site you want to fetch
                    Document document = Jsoup.connect("http://www.industryresponsetraining.com.au/mdt/lat.html").get();

                    //Get the title of blog using title tag
                    //title = document.select("p").text().toString();
                    lt = document.select("h6").text().toString();
                    ln = document.select("h7").text().toString();


                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        double lats = Double.valueOf(lt);
        double lngs = Double.valueOf(ln);
        LatLng marker = new LatLng(lats, lngs);
        mMap.addMarker(new MarkerOptions().position(marker).title("my Marker"));
        mMap.moveCamera(CameraUpdateFactory.newLatLng(marker));
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(marker, 15));
    }
}

The actual google map stuff has been referenced from the developers page

Community
  • 1
  • 1
shaggs
  • 600
  • 7
  • 27
  • 1
    Log the value of ln and lt in onMapReady. Also log the values in the thread you will know whats happenning or use a debugger – Raghunandan Mar 16 '16 at 12:56
  • http://stackoverflow.com/questions/18672456/java-lang-numberformatexception-invalid-double – IntelliJ Amiya Mar 16 '16 at 12:58
  • 1
    @IntelliJ Amiya i have read that post and even refernced somthing similar and gave and outcome of. Didnt work – shaggs Mar 16 '16 at 13:07
  • @Raghunandan would i log it as `lt = document.select("h6").text().toString();` and remove that from above ? – shaggs Mar 16 '16 at 13:21

2 Answers2

1

It should be a double value, not string value like empty ("") String

Ansewer: As stated in

actually, 2 lines of code above happen after your onMapReady. So when onMapReady execute, your lt and ln are always "". So you need to determine when your lt and 'ln has been updated with a new value, then create a market before that time.

Edit Working code

package au.com.industryresponsetraining.map;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import java.io.IOException;


public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private static final String TAG = MapsActivity.class.getSimpleName();
    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        new ParseAsyncTask().execute("http://www.industryresponsetraining.com.au/mdt/lat.html");
    }

    class ParseAsyncTask extends AsyncTask<String, Void, String[]> {

        @Override
        protected String[] doInBackground(String... params) {
            String url = params[0];
            try {

                //get the Document object from the site. Enter the link of site you want to fetch
                Document document = Jsoup.connect(url).get();

                //Get the title of blog using title tag
                //title = document.select("p").text().toString();
                String lat = document.select("h6").text().toString();
                Log.d(TAG, lat);

                String lng = document.select("h7").text().toString();
                Log.d(TAG, lng);
                return new String[]{lat, lng};
            } catch (IOException e) {
                e.printStackTrace();
                return new String[]{"0.0", "0.0"};
            }
        }

        @Override
        protected void onPostExecute(String[] result) {
            createMarker(result);
        }
    }

    private void createMarker(String[] result) {
        if (mMap != null) {
            double lats = Double.valueOf(result[0]);
            double lngs = Double.valueOf(result[1]);
            LatLng marker = new LatLng(lats, lngs);
            mMap.addMarker(new MarkerOptions().position(marker).title("my Marker"));
            mMap.moveCamera(CameraUpdateFactory.newLatLng(marker));
            mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(marker, 15));
        }
    }
}
thuongle
  • 537
  • 6
  • 10
  • Oops. So where is your code `String myString = ((EditText) findViewById(R.id.editText1)).getText().toString();` – thuongle Mar 16 '16 at 13:04
  • i had that code as a reference and changed it to `double lats; if (lt != null && !lt.equals("")) { lats = Double.valueOf(lt); } else { lats = 0; }` I also did this for lngs and it placed me out a sea so guessing returned 0, 0 – shaggs Mar 16 '16 at 13:18
  • So your code `lt = document.select("h6").text().toString(); ln = document.select("h7").text().toString();` never happen in runtime. – thuongle Mar 16 '16 at 13:22
  • Thats what i'm guessing. – shaggs Mar 16 '16 at 13:23
  • actually, 2 lines of code above happen after your `onMapReady`. So when `onMapReady` execute, your `lt` and `ln` are always `""`. So you need to determine when your `lt` and '`ln` has been updated with a new value, then create a market before that time. – thuongle Mar 16 '16 at 13:27
  • Would be update in the `Document document = Jsoup.connect("http://www.industryresponsetraining.com.au/mdt/lat.html").get(); //Get the title of blog using title tag //title = document.select("p").text().toString(); lt = document.select("h6").text().toString(); ln = document.select("h7").text().toString();` but this is in the onCreate() – shaggs Mar 16 '16 at 13:34
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/106469/discussion-between-thuongle-and-shaggs). – thuongle Mar 16 '16 at 13:38
  • your code worked that you did in chat so please post here for correct answer – shaggs Mar 17 '16 at 10:33
0

This is just a timing problem caused by the parallel processes finishing in the "wrong" order. ("Wrong" as in opposite to what you expected.)

In onCreate() you start the asynchronous operation to get a Google Map by calling getMapAsync(). That operation will run for some time and once it finishes the onMapReady() method is triggered.

In onCreate() you also start your own thread which runs the jsoup code to fetch the web page and extract the coordinates from it. The jsoup's connect() and get() methods run some time and after they have finished you then extract the coordinates.

If the Google Map code finished earlier then the jsoup code has not yet fetched and extracted the coordinates.

As the Google Map code has a higher priority (You first need the map in order to be able to draw a marker on it) you should just let it finish first.

Then in the onMapReady() method you can start your jsoup code.

The minimal code modifications could be something like:

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    String ln = "";
    String lt = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        new Thread(new Runnable() {

            @Override
            public void run() {
                try {

                    //get the Document object from the site. Enter the link of site you want to fetch
                    Document document = Jsoup.connect("http://www.industryresponsetraining.com.au/mdt/lat.html").get();

                    //Get the title of blog using title tag
                    //title = document.select("p").text().toString();
                    lt = document.select("h6").text().toString();
                    ln = document.select("h7").text().toString();

                    // The UI must be modified from the UI thread.
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            double lats = Double.valueOf(lt);
                            double lngs = Double.valueOf(ln);
                            LatLng marker = new LatLng(lats, lngs);
                            mMap.addMarker(new MarkerOptions().position(marker).title("my Marker"));
                            mMap.moveCamera(CameraUpdateFactory.newLatLng(marker));
                            mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(marker, 15));
                        }
                    });

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

    }
}

The runOnUiThread() is needed because the Google Map is part of the UI and the UI can't be modified from a background thread.

However that (above) is not really the proper Android way to do this. Instead of just creating a standard Java thread for the jsoup code and then using runOnUiThread() inside that thread you should use an AsyncTask like this:

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    String ln = "";
    String lt = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        AsyncTask jsoupTask = new AsyncTask() {

            @Override
            protected Object doInBackground(Object[] params) {
                // This runs in a background thread.

                Document document;

                try {
                    //get the Document object from the site. Enter the link of site you want to fetch
                    document = Jsoup.connect("http://www.industryresponsetraining.com.au/mdt/lat.html").get();
                } catch (Exception e) {
                    e.printStackTrace();
                }

                return document; // Might be null!
            }

            @Override
            protected void onPostExecute(Document document) {
                // This is triggered once the code in doInBackground() has been completed.

                super.onPostExecute(document);

                if (document != null) {
                    try {
                        //Get the title of blog using title tag
                        //title = document.select("p").text().toString();
                        lt = document.select("h6").text().toString();
                        ln = document.select("h7").text().toString();

                        double lats = Double.valueOf(lt);
                        double lngs = Double.valueOf(ln);
                        LatLng marker = new LatLng(lats, lngs);
                        mMap.addMarker(new MarkerOptions().position(marker).title("my Marker"));
                        mMap.moveCamera(CameraUpdateFactory.newLatLng(marker));
                        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(marker, 15));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        jsoupTask.execute();

    }
}
Markus Kauppinen
  • 3,025
  • 4
  • 20
  • 30