0

i have two AsyncTask which works with Current user location data, the first goes well without any problem, but the second, stop the app works and app will crash.

notice that, just in real device the first task will works but in virtual devices even the first didn't work :|

code of mainActivity:

public class MainActivity extends AppCompatActivity {
Button btnShowLocation;
public static TextView txtTemperature;
public static TextView txtWindSpeed;
public static TextView txtHumidity;
public static TextView txtSummary;
public static TextView txtCityName;
GpsTracker gps;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btnShowLocation = (Button)findViewById(R.id.btnupdate);
    txtTemperature = (TextView) findViewById(R.id.txtTemperature);
    txtWindSpeed = (TextView) findViewById(R.id.txtWindSpeed);
    txtHumidity = (TextView) findViewById(R.id.txthumidity);
    txtSummary = (TextView) findViewById(R.id.txtSummary);
    txtSummary = (TextView) findViewById(R.id.txtCityName);
    //find geoLocation
    btnShowLocation.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            gps = new GpsTracker(MainActivity.this);

            if(gps.canGetLocation()){
                Double lat = gps.getLatitude();
                Double lng = gps.getLongtitude();
                Toast.makeText(getApplicationContext(),
                        "Your location is -\nLat:"+lat+"\nLng:"+lng,
                        Toast.LENGTH_LONG).show();
                String url = "https://api.forecast.io/forecast/KEY/"+lat+","+lng+"?units=ca";
                JsonTask task = new JsonTask(getApplicationContext());
                task.execute(url);
                String url2 = "http://maps.googleapis.com/maps/api/geocode/json?latlng="+lat+","+lng;
                CityNameTask city = new CityNameTask(getApplicationContext());
                city.execute(url2);
            }
            else {
                gps.showSettingsAlert();
            }
        }
    });
}
}

the First AsyncTask which work fine:

class JsonTask extends AsyncTask<String, String, String> {
private Context mContext;
public JsonTask (Context context){
    mContext = context;
}
protected void onPreExecute() {
    super.onPreExecute();
}
protected String doInBackground(String... params) {
    HttpURLConnection connection = null;
    BufferedReader reader = null;
    try {
        URL url = new URL(params[0]);
        connection = (HttpURLConnection) url.openConnection();
        connection.connect();
        InputStream stream = connection.getInputStream();
        reader = new BufferedReader(new InputStreamReader(stream));
        StringBuffer buffer = new StringBuffer();
        String line = "";
        String data = "";
        while ((line = reader.readLine()) != null) {
            buffer.append(line+"\n");
            //Log.d("Response: ", "> " + line);   //here u ll get whole response...... :-)
            try{
                JSONObject jsonObject= new JSONObject(line).getJSONObject("currently");
                data=
                        jsonObject.getString("temperature")+","+
                        jsonObject.getString("windSpeed")+","+
                        jsonObject.getString("humidity")+","+
                        jsonObject.getString("summary");

            }
            catch(JSONException e)
            {
            }
        }
        return data.toString();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (connection != null) {
            connection.disconnect();
        }
        try {
            if (reader != null) {
                reader.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return null;
}
@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);

    String string = result;
    String[] parts = string.split(",");
    String temperature = parts[0];
    String windSpeed = parts[1];
    String humidity = parts[2];
    String summary = parts[3];
    MainActivity.txtTemperature.setText(temperature);
    MainActivity.txtWindSpeed.setText(windSpeed);
    MainActivity.txtHumidity.setText(humidity);
    MainActivity.txtSummary.setText(summary);
}
}

the second Task which fails:

class CityNameTask extends AsyncTask<String, String, String> {
private Context mContext;
public CityNameTask (Context context){
    mContext = context;
}
protected void onPreExecute() {
    super.onPreExecute();
}
protected String doInBackground(String... params) {
    HttpURLConnection connection = null;
    BufferedReader reader = null;
    try {
        URL url = new URL(params[0]);
        connection = (HttpURLConnection) url.openConnection();
        connection.connect();
        InputStream stream = connection.getInputStream();
        reader = new BufferedReader(new InputStreamReader(stream));
        StringBuffer buffer = new StringBuffer();
        String line = "";
        String data = "";
        while ((line = reader.readLine()) != null) {
            buffer.append(line+"\n");
        }
        Log.d("Response: ", "> " + line);
        try {
            JSONObject  jsonRootObject = new JSONObject(line);

            JSONArray jsonArray = jsonRootObject.optJSONArray("results");
            for(int i=0; i < jsonArray.length(); i++){
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                data = jsonObject.getString("formatted_address");

            }

        } catch (JSONException e) {e.printStackTrace();}
        return data.toString();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (connection != null) {
            connection.disconnect();
        }
        try {
            if (reader != null) {
                reader.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return null;
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    MainActivity.txtCityName.setText(result);
}
}

-- edited: logcat:

06-03 22:00:07.998 2804-2804/com.mortezaaghili.havamoon E/AndroidRuntime: FATAL EXCEPTION: main
                                                                          Process: com.mortezaaghili.havamoon, PID: 2804
                                                                          java.lang.NullPointerException: Attempt to invoke virtual method 'double android.location.Location.getLatitude()' on a null object reference
                                                                              at com.mortezaaghili.havamoon.GpsTracker.getLatitude(GpsTracker.java:131)
                                                                              at com.mortezaaghili.havamoon.MainActivity$1.onClick(MainActivity.java:54)
                                                                              at android.view.View.performClick(View.java:5198)
                                                                              at android.view.View$PerformClick.run(View.java:21147)
                                                                              at android.os.Handler.handleCallback(Handler.java:739)
                                                                              at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                              at android.os.Looper.loop(Looper.java:148)
                                                                              at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                              at java.lang.reflect.Method.invoke(Native Method)
                                                                              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

edited again: this is GPSTracker class:

public class GpsTracker extends Service implements LocationListener {
    private final Context context;
    boolean isGPSEnabled = false;
    boolean isNetworkEnabled = false;
    boolean canGetLocation = false;
    Location location;
    Double latitude;
    Double longtitude;
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10;
    private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1;
    protected LocationManager locationManager;
    public GpsTracker(Context context){
        this.context = context;
        getLocation();
    }
    public Location getLocation(){
        try {
            locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
            isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
            if (!isGPSEnabled && !isNetworkEnabled){}
            else{
                this.canGetLocation = true;
                if(isNetworkEnabled){
                    try {
                        locationManager.requestLocationUpdates(
                                LocationManager.NETWORK_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES,
                                this);

                        if (locationManager != null){
                            location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                            if(location != null){
                                latitude = location.getLatitude();
                                longtitude = location.getLongitude();

                            }
                        }
                    }
                    catch (SecurityException e)
                    {

                    }
                }
                if(isGPSEnabled){
                    if (location == null){
                        try {
                            locationManager.requestLocationUpdates(
                                    LocationManager.GPS_PROVIDER,
                                    MIN_TIME_BW_UPDATES,
                                    MIN_DISTANCE_CHANGE_FOR_UPDATES,
                                    this);

                            if (locationManager != null){
                                location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

                                if(location != null){
                                    latitude = location.getLatitude();
                                    longtitude = location.getLongitude();

                                }
                            }
                        }
                        catch (SecurityException e)
                        {
                        }
                    }
                }
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    return location;
    }
    public void stopUsingGPS(){
        if (locationManager != null){
            try{
                locationManager.removeUpdates(GpsTracker.this);
            }
            catch(SecurityException e){
            }
        }
    }
    public double getLatitude(){
        if (locationManager != null){
            latitude = location.getLatitude();
        }
        return latitude;
    }
    public double getLongtitude(){
        if (locationManager != null) {
            longtitude = location.getLongitude();
        }
        return longtitude;

    }
    public boolean canGetLocation(){
        return this.canGetLocation;
    }
    public void showSettingsAlert(){
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);

        alertDialog.setTitle("GPS is setting");
        alertDialog.setMessage("GPS is not enabled. do you want go to settings?");
        alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                context.startActivity(intent);
            }
        });
        alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });

        alertDialog.show();
    }
    @Override
    public void onLocationChanged(Location location) {
    }
    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }
    @Override
    public void onProviderEnabled(String provider) {
    }
    @Override
    public void onProviderDisabled(String provider) {
    }
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    }
Mort
  • 1,411
  • 5
  • 19
  • 51
  • post here exception details you get – Stepan Maksymov Jun 03 '16 at 17:30
  • @VasilyKabunov i edited the question – Mort Jun 03 '16 at 17:32
  • @Stepan Maksymov Edited – Mort Jun 03 '16 at 17:32
  • 1
    The variable exception says your `gps` is null. But from the code you supplied, that should be impossible. There must be some other code you did not include that is disposing of that same object instance in another thread. – Jon Adams Jun 03 '16 at 17:35
  • unrelated to your problem, but when you have 2 tasks consider using the [`THREAD_POOL_EXECUTOR`](http://stackoverflow.com/questions/12159403/executing-multiple-asynctasks-parallely) because they run otherwise after each other. – zapl Jun 03 '16 at 17:41
  • @JonAdams yes, but why the second task work fine ? – Mort Jun 03 '16 at 17:43
  • @zapl yes, I'm new in android development but i heard about this way, Thank you – Mort Jun 03 '16 at 17:44
  • 1
    @MortezaAghili RE the 2nd task: Your exception stack trace given is during your onClick event—not during the task execution. So either you have multiple exceptions and you provided the other one to us, or the tasks are either not completing or not throwing exceptions. – Jon Adams Jun 03 '16 at 17:47
  • @JonAdams Can you take a look at edited question, I added the GPSTracker class – Mort Jun 03 '16 at 17:57

4 Answers4

1

What it seems like is that your location variable is not initialized from the GpsTracker class. Therefore when you are extending Service class and implementing LocationListener you would have overridden a method called getLocation(), which should return Location object, but in your case is returning null.

If you could just post the code for that file, or debug it on your own.

Hemal Shah
  • 58
  • 6
  • : I Added the GPStracker class. – Mort Jun 03 '16 at 17:56
  • Looking at your GpsTracker class, you should do the following 1. In the constructor do: `this.location = getLocation();` 2. In the getLocation() method, introduce a new local variable of the type `Location`, then initialize that variable and return it from the function. Also I would recomment putting up various logs in your method to justify the value of `Location` variable at different moments. – Hemal Shah Jun 03 '16 at 18:20
0

probably your GpsTracker class must include something like:

public double getLatitude() {
    if(location != null) { // here must be checked if location is available and it's not null, coz now you probably get crash coz this has not been checked
        latitude = location.getLatitude();
    }
    return latitude;
}
Stepan Maksymov
  • 2,618
  • 19
  • 31
  • yes, it will be checked and as i said, one of them works with user location but the second ... – Mort Jun 03 '16 at 17:43
0

In order to avoid getting Null Locations you need to use google play locations API which is recommended by google.

Also Try

    String line = ""; 
    String data = "";
    while ((line = reader.readLine()) != null) {
        buffer.append(line+"\n");
    } 

At the end of this loop the line object is null So save a copy of the last line element in some variable and Then apply the following code on that.

    Log.d("Response: ", "> " + line);
    try { 
        JSONObject  jsonRootObject = new JSONObject(line);

        JSONArray jsonArray = jsonRootObject.optJSONArray("results");
        for(int i=0; i < jsonArray.length(); i++){
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            data = jsonObject.getString("formatted_address");

        } 
Muddassir Ahmed
  • 518
  • 4
  • 19
  • Thanks, Ow!! why value 'line' is always 'null' ? and if after the while its will be null how i could save this data in another variable ? – Mort Jun 03 '16 at 18:13
  • ` while(reader.readline()!=null){line=reader.realine();buffer.append(line+"\n"); }` **Just Move the code for assigning the value to the line variable inside the while loop** then when the while loop finishes the line variable will contain the last value read from the reader – Muddassir Ahmed Jun 03 '16 at 18:45
  • Moreover the gps.canGetLocation() won't guarantee that the location you get is not NULL, you need to return the location variable from the GPS tracker class and apply a check on it whether it is null or not! – Muddassir Ahmed Jun 03 '16 at 19:05
  • thank you for replay, but now the app dont crash but the return data from json will be empty. could you please see this question ? http://stackoverflow.com/questions/37617246/how-to-just-read-wanted-data-from-json-in-java-android – Mort Jun 03 '16 at 19:09
  • Use the a JsonArray and add the data string into it. – Muddassir Ahmed Jun 04 '16 at 09:24
  • Use the a **JsonArray** and add the data string into it. ` JsonArray jArray= new JsonArray(data); ` Then you can assign the **nth** value from that array into a **JsonObject** ` JsonObject jObject = jArray.getJsonObject(n); ` then to get the value of **"long_name"** use ` String long_name = jObject.getString("long_name"); ` – Muddassir Ahmed Jun 04 '16 at 09:31
0

The relavent part of the stack trace is:

java.lang.NullPointerException: Attempt to invoke virtual method 'double android.location.Location.getLatitude()' on a null object
reference at com.mortezaaghili.havamoon.GpsTracker.getLatitude(GpsTracker.java:131)

Broken code mentioned:

public double getLatitude(){
        if (locationManager != null){
            latitude = location.getLatitude();
        }
        return latitude;
    }

You're checking for a null locationManager but then calling a method on location which may have been null from the big try/catch swallowing in the getLocation() setup method called during the GPSTracker constructor.

Check for location null instead:

public double getLatitude(){
        if (location != null){
            latitude = location.getLatitude();
        }
        return latitude;
    }
Jon Adams
  • 24,464
  • 18
  • 82
  • 120