简体   繁体   中英

App crashing when internet connection is not available

We are facing a peculiar problem with our app when the app is running and connection goes off it works fine. However when we try to search for a particular place it crashes. Please refer to the code below we are using Google Maps API -

 public class MainActivity extends AppCompatActivity implements     OnMapReadyCallback,
    GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener,
    LocationListener, AdapterView.OnItemClickListener {

private GoogleMap mMap;
    GoogleApiClient mGoogleApiClient;
    Location mLastLocation;
    Marker mCurrLocationMarker,FindMarker;
    LocationRequest mLocationRequest;
    AutoCompleteTextView atvPlaces;
    DownloadTask placesDownloadTask;
    DownloadTask placeDetailsDownloadTask;
    ParserTask placesParserTask;
    ParserTask placeDetailsParserTask;
    LatLng latLng;
    final int PLACES = 0;
    final int PLACES_DETAILS = 1;
    ListView lv;
    ImageButton remove;
    private boolean exit = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    // setSupportActionBar(toolbar);



    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    checkLocationPermission();
    }

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View view) {
    onLocationChanged(mLastLocation);
    }
    });

    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
    .findFragmentById(R.id.map);
     mapFragment.getMapAsync(this);


    AdView adView = (AdView)findViewById(R.id.addview);
    AdRequest adRequest = new AdRequest.Builder().build();

    adView.loadAd(adRequest);

    remove = (ImageButton)findViewById(R.id.place_autocomplete_clear_button);

    // Getting a reference to the AutoCompleteTextView
    atvPlaces = (AutoCompleteTextView) findViewById(R.id.id_search_EditText);
    atvPlaces.setThreshold(1);

    // Adding textchange listener
    atvPlaces.addTextChangedListener(new TextWatcher() {

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    // Creating a DownloadTask to download Google Places matching "s"
    placesDownloadTask = new DownloadTask(PLACES);

    // Getting url to the Google Places Autocomplete api
         String url = getAutoCompleteUrl(s.toString());

    // Start downloading Google Places
    // This causes to execute doInBackground() of DownloadTask class

        placesDownloadTask.execute(url);


        if (!atvPlaces.getText().toString().equals("")){
            lv.setVisibility(View.VISIBLE);
            remove.setVisibility(View.VISIBLE);
        }else  {
            lv.setVisibility(View.GONE);
            remove.setVisibility(View.GONE);
        }


    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
    int after) {
    // TODO Auto-generated method stub
    }

    @Override
    public void afterTextChanged(Editable s) {
    // TODO Auto-generated method stub
    }
    });


    lv=(ListView)findViewById(R.id.list);

    lv.setOnItemClickListener(this);

    // for enter button search hide key board and search using by enter button..
    atvPlaces.setOnEditorActionListener(new AutoCompleteTextView.OnEditorActionListener() {

    public boolean onEditorAction(TextView v, int actionId,
                                  KeyEvent event) {
        if (actionId == EditorInfo.IME_ACTION_SEARCH) {

            String location = atvPlaces.getText().toString();
            if (location != null && !location.equals("")) {
                new GeocoderTask().execute(location);

            }
            lv.setVisibility(View.GONE);
            InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            im.hideSoftInputFromWindow(atvPlaces.getWindowToken(), 0);
            return true;
        }
        return false;
    }
});


   setListenerOnWidget();
   checkLocation();
}

// location access allow or not
private void checkLocation() {

    LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    LocationManager locationManager = null;
    boolean location_enabled = false;
    boolean network_enabled = false;

    try {
        location_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    } catch (Exception ex){}


    try {
        network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    } catch(Exception ex) {}

    if ( !location_enabled && !network_enabled){
        AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
        dialog.setMessage("Location Not Enabled");
        dialog.setTitle("Check Location Access");
        dialog.setCancelable(false);
        dialog.setPositiveButton("Allow", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                //this will navigate user to the device location settings screen
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivity(intent);
            }
        });
        AlertDialog alert = dialog.create();
        alert.show();
    }
}

private void setListenerOnWidget() {
    View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
        atvPlaces.setText("");
        }
    };
    remove.setOnClickListener(listener);
}

@Override
public void onBackPressed() {
    if(exit){
        finish();
    }else {
        Toast.makeText(this, "Tap Back again to Exit.",
                Toast.LENGTH_SHORT).show();
        exit = true;
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                exit = false;
            }
        }, 3 * 1000);

    }
    }


@Override
public void onItemClick (AdapterView < ? > adapterView, View view,int i, long l){
    //ListView lv = (ListView) adapterView;
    SimpleAdapter adapter = (SimpleAdapter) adapterView.getAdapter();

    HashMap<String, String> hm = (HashMap<String, String>) adapter.getItem(i);

    // Creating a DownloadTask to download Places details of the selected place
    placeDetailsDownloadTask = new DownloadTask(PLACES_DETAILS);

    // Getting url to the Google Places details api
    String url = getPlaceDetailsUrl(hm.get("reference"));

    // Start downloading Google Place Details
    // This causes to execute doInBackground() of DownloadTask class
    placeDetailsDownloadTask.execute(url);

    InputMethodManager inputManager = (InputMethodManager)
            getSystemService(Context.INPUT_METHOD_SERVICE);

    inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),
            InputMethodManager.HIDE_NOT_ALWAYS);

    String str = ((TextView) view.findViewById(R.id.place_name)).getText().toString();
    Toast.makeText(this,str, Toast.LENGTH_SHORT).show();
    //atvPlaces.setText(str.replace(' ',','));
    atvPlaces.setText(str);

    lv.setVisibility(view.GONE);


}



private String getPlaceDetailsUrl(String ref) {
    // Obtain browser key from https://code.google.com/apis/console
    String key = "key=*******************************************";

    // reference of place
    String reference = "reference=" + ref;

    // Sensor enabled
    String sensor = "sensor=false";

    // Building the parameters to the web service
    String parameters = reference + "&" + sensor + "&" + key;

    // Output format
    String output = "json";

    // Building the url to the web service
    String url = "https://maps.googleapis.com/maps/api/place/details/" + output + "?" + parameters;

    return url;
    }

private String getAutoCompleteUrl(String place) {
    // Obtain browser key from https://code.google.com/apis/console
    String key = "key=**********************************";

    // place to be be searched
    String input = "input=" + place;

    // place type to be searched
    String types = "types=geocode";

    // Sensor enabled
    String sensor = "sensor=false";

    // Building the parameters to the web service
    String parameters = input + "&" + types + "&" + sensor + "&" + key;

    // Output format
    String output = "json";

    // Building the url to the web service
    String url = "https://maps.googleapis.com/maps/api/place/autocomplete/" + output + "?" + parameters;

    url = url.replaceAll(" ", "%20");
    return url;
    }


private String downloadUrl(String strUrl) throws IOException {
    String data = "";
    InputStream iStream = null;
    HttpURLConnection urlConnection = null;
    try {
    URL url = new URL(strUrl);

    // Creating an http connection to communicate with url
    urlConnection = (HttpURLConnection) url.openConnection();

    // Connecting to url
    urlConnection.connect();

    // Reading data from url
    iStream = urlConnection.getInputStream();

    BufferedReader br = new BufferedReader(new InputStreamReader(iStream));

    StringBuffer sb = new StringBuffer();

    String line = "";
    while ((line = br.readLine()) != null) {
    sb.append(line);
    }

    data = sb.toString();

    br.close();

    } catch (Exception e) {
    Log.d("Exception while downloading url", e.toString());
    } finally {
    iStream.close();
    urlConnection.disconnect();
    }
    return data;
    }

  public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;

 public boolean checkLocationPermission() {
    if (ContextCompat.checkSelfPermission(this,
    Manifest.permission.ACCESS_FINE_LOCATION)
    != PackageManager.PERMISSION_GRANTED) {

    if (ActivityCompat.shouldShowRequestPermissionRationale(this,
    Manifest.permission.ACCESS_FINE_LOCATION)) {

    ActivityCompat.requestPermissions(this,
    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
    MY_PERMISSIONS_REQUEST_LOCATION);
    } else {
    ActivityCompat.requestPermissions(this,
    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
    MY_PERMISSIONS_REQUEST_LOCATION);
    }
    return false;
    } else {
    return true;
    }

    }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
    }

   @Override
   public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
    return true;
    }

    return super.onOptionsItemSelected(item);
    }

   @Override
   public void onConnected(@Nullable Bundle bundle) {
    mLocationRequest = new LocationRequest();
    //mLocationRequest.setInterval(1000);
    //mLocationRequest.setFastestInterval(1000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

    if (ContextCompat.checkSelfPermission(this,
    Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }
    }

   @Override
   public void onConnectionSuspended(int i) {

    }

   @Override
   public void onLocationChanged(Location location) {
mLastLocation = location;
if(mCurrLocationMarker != null){
    mCurrLocationMarker.remove();
}

LatLng latLng = new LatLng(location.getLatitude(),location.getLongitude());
MarkerOptions markerOption = new MarkerOptions();
markerOption.position(latLng);
markerOption.title("Current Position");
 markerOption.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mMap.addMarker(markerOption);
Toast.makeText(this,"Location changed",Toast.LENGTH_SHORT).show();
CameraPosition cameraPosition = new CameraPosition.Builder().target(latLng).zoom(13).build();
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

if(mGoogleApiClient != null){
    LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this);
}

    loadNearByPlaces(location.getLatitude(), location.getLongitude());
    }

  @Override
  public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

    }

  @Override
  public void onMapReady(GoogleMap googleMap) {

    mMap = googleMap;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (ContextCompat.checkSelfPermission(this,
    android.Manifest.permission.ACCESS_FINE_LOCATION)
    == PackageManager.PERMISSION_GRANTED) {
    buildGoogleApiClient();
    mMap.setMyLocationEnabled(true);

    }
    } else {
    buildGoogleApiClient();
    mMap.setMyLocationEnabled(true);
    }

    }

  protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
    .addConnectionCallbacks(this)
    .addOnConnectionFailedListener(this)
    .addApi(LocationServices.API)
    .build();
    mGoogleApiClient.connect();
    }

   @Override
   public void onRequestPermissionsResult(int requestCode,
    String permissions[], int[] grantResult) {
    switch (requestCode) {
    case MY_PERMISSIONS_REQUEST_LOCATION: {

    if (grantResult.length > 0
    && grantResult[0] == PackageManager.PERMISSION_GRANTED) {
    if (ContextCompat.checkSelfPermission(this,
    Manifest.permission.ACCESS_FINE_LOCATION)
    == PackageManager.PERMISSION_GRANTED) {
    if (mGoogleApiClient == null) {
    buildGoogleApiClient();
    }
    mMap.setMyLocationEnabled(true);
    }

    } else {
    Toast.makeText(this, "permisison denied", Toast.LENGTH_LONG).show();
    }
    return;
    }

    }
    }

  private void loadNearByPlaces(double latitude, double longitude) {
  //YOU Can change this type at your own will, e.g hospital, cafe, restaurant.... and see how it all works
    String type = "atm";
    StringBuilder googlePlacesUrl =
    new StringBuilder("https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
    googlePlacesUrl.append("location=").append(latitude).append(",").append(longitude);
    googlePlacesUrl.append("&radius=").append(PROXIMITY_RADIUS);
    googlePlacesUrl.append("&types=").append(type);
    googlePlacesUrl.append("&sensor=true");
    googlePlacesUrl.append("&key=" + GOOGLE_BROWSER_API_KEY);

    JsonObjectRequest request = new JsonObjectRequest(googlePlacesUrl.toString(),
    new Response.Listener<JSONObject>() {
  @Override
  public void onResponse(JSONObject result) {

    Log.i(TAG, "onResponse: Result= " + result.toString());
    parseLocationResult(result);
    }
    },
    new Response.ErrorListener() {
  @Override
  public void onErrorResponse(VolleyError error) {
    Log.e(TAG, "onErrorResponse: Error= " + error);
    Log.e(TAG, "onErrorResponse: Error= " + error.getMessage());
    }
    });

    AppController.getInstance().addToRequestQueue(request);
    }

   private void parseLocationResult(JSONObject result) {

    String id, place_id, placeName = null, reference, icon, vicinity = null;
    double latitude, longitude;

    try {
    JSONArray jsonArray = result.getJSONArray("results");

    if (result.getString(STATUS).equalsIgnoreCase(OK)) {

    //mMap.clear();

    for (int i = 0; i < jsonArray.length(); i++) {
    JSONObject place = jsonArray.getJSONObject(i);

    id = place.getString(ATM_ID);
    place_id = place.getString(PLACE_ID);
    if (!place.isNull(NAME)) {
    placeName = place.getString(NAME);
    }
    if (!place.isNull(VICINITY)) {
    vicinity = place.getString(VICINITY);
    }
    latitude = place.getJSONObject(GEOMETRY).getJSONObject(LOCATION)
    .getDouble(LATITUDE);
    longitude = place.getJSONObject(GEOMETRY).getJSONObject(LOCATION)
    .getDouble(LONGITUDE);
    reference = place.getString(REFERENCE);
    icon = place.getString(ICON);

    MarkerOptions markerOptions = new MarkerOptions();
    LatLng latLng = new LatLng(latitude, longitude);
    markerOptions.position(latLng);
    markerOptions.title(placeName);
        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE));
        markerOptions.snippet(vicinity);
    mMap.addMarker(markerOptions);

        mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {

            @Override
            public View getInfoWindow(Marker arg0) {

                return null;
            }

            @Override
            public View getInfoContents(Marker marker) {
                View myContentsView = getLayoutInflater().inflate(R.layout.marker, null);
                TextView tvTitle = ((TextView)myContentsView.findViewById(R.id.title));
                tvTitle.setText(marker.getTitle());
                TextView tvSnippet = ((TextView)myContentsView.findViewById(R.id.snippet));
                tvSnippet.setText(marker.getSnippet());
                return myContentsView;
            }
        });

    }

    Toast.makeText(getBaseContext(), jsonArray.length() + " ATM_FOUND!",
    Toast.LENGTH_SHORT).show();
    } else if (result.getString(STATUS).equalsIgnoreCase(ZERO_RESULTS)) {
    Toast.makeText(getBaseContext(), "No ATM found in 5KM radius!!!",
    Toast.LENGTH_LONG).show();
    }

    } catch (JSONException e) {

    e.printStackTrace();
    Log.e(TAG, "parseLocationResult: Error=" + e.getMessage());
    }
    }

 private class DownloadTask extends AsyncTask<String, Void, String> {
private int downloadType = 0;

// Constructor
public DownloadTask(int type) {
    this.downloadType = type;
}

@Override
protected String doInBackground(String... url) {
    // For storing data from web service
    String data = "";

    try {
        // Fetching the data from web service
        data = downloadUrl(url[0]);
    } catch (Exception e) {
        Log.d("Background Task", e.toString());
    }
    return data;
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);

    switch (downloadType) {
        case PLACES:
            // Creating ParserTask for parsing Google Places
            placesParserTask = new ParserTask(PLACES);

            // Start parsing google places json data
            // This causes to execute doInBackground() of ParserTask class
            placesParserTask.execute(result);

            break;

        case PLACES_DETAILS:
            // Creating ParserTask for parsing Google Places
            placeDetailsParserTask = new ParserTask(PLACES_DETAILS);

            // Starting Parsing the JSON string
            // This causes to execute doInBackground() of ParserTask class
            placeDetailsParserTask.execute(result);
    }
  }
 }

  private class ParserTask extends AsyncTask<String, Integer, List<HashMap<String, String>>> {

int parserType = 0;

public ParserTask(int type) {
    this.parserType = type;
}

@Override
protected List<HashMap<String, String>> doInBackground(String... jsonData) {

    JSONObject jObject;
    List<HashMap<String, String>> list = null;

    try {
        jObject = new JSONObject(jsonData[0]);

        switch (parserType) {
            case PLACES:
                PlaceJSONParser placeJsonParser = new PlaceJSONParser();
                // Getting the parsed data as a List construct
                list = placeJsonParser.parse(jObject);
                break;
            case PLACES_DETAILS:
                PlaceDetailsJSONParser placeDetailsJsonParser = new PlaceDetailsJSONParser();
                // Getting the parsed data as a List construct
                list = placeDetailsJsonParser.parse(jObject);
        }

    } catch (Exception e) {
        Log.d("Exception", e.toString());
    }
    return list;
}

@Override
protected void onPostExecute(List<HashMap<String, String>> result) {

    switch (parserType) {
        case PLACES:
            String[] from = new String[]{"description"};
            int[] to = new int[]{R.id.place_name};

            // Creating a SimpleAdapter for the AutoCompleteTextView
            //SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), result, android.R.layout.simple_list_item_1, from, to);

            // Setting the adapter
            //atvPlaces.setAdapter(adapter);

            ListAdapter adapter = new SimpleAdapter(MainActivity.this, result,R.layout.row,from,to);
            // Adding data into listview
            lv.setAdapter(adapter);
            break;
        case PLACES_DETAILS:
            String location = atvPlaces.getText().toString();
            if (location != null && !location.equals("")) {
                new GeocoderTask().execute(location);


            }

            break;
    }
}
 }

 private class GeocoderTask extends AsyncTask<String, Void, List<Address>> {

@Override
protected List<Address> doInBackground(String... locationName) {
    // TODO Auto-generated method stub

    Geocoder geocoder = new Geocoder(getBaseContext());
    List<Address> addresses = null;

    try {
        // Getting a maximum of 3 Address that matches the input text
        addresses = geocoder.getFromLocationName(locationName[0], 3);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return addresses;
}

protected void onPostExecute(List<Address> addresses) {
    if(addresses==null || addresses.size()==0){
        Toast.makeText(getBaseContext(), "No Location found", Toast.LENGTH_SHORT).show();
    }
    for(int i=0;i<addresses.size();i++){
        Address address =  (Address)addresses.get(i);
        latLng = new LatLng(address.getLatitude(), address.getLongitude());
        String addressText = String.format("%s, %s",
                address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "",
                address.getCountryName());
        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(latLng);
        markerOptions.title("Find Location");
        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
        FindMarker = mMap.addMarker(markerOptions);

        CameraPosition cameraPosition = new CameraPosition.Builder().target(latLng).zoom(13).build();
        mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

        loadNearByPlaces(address.getLatitude(), address.getLongitude());


    }

}

}

}

Thanks...

Within

 protected void onPostExecute(List<Address> addresses) {
      if(addresses==null || addresses.size()==0){
    Toast.makeText(getBaseContext(), "No Location found", Toast.LENGTH_SHORT).show();
return; // ADD RETURN HERE
// Your code will go beyond toast and NPE
 }
...

May be google map's api search is returning null that is why you are getting null exception, so just check your api keys and google map permissions and try. Otherwise attach a screenshot of your error logcat for more convenience.

protected void onPostExecute(List<Address> addresses) {
    if(addresses==null || addresses.size()==0){
         Toast.makeText(getBaseContext(), "No Location found", Toast.LENGTH_SHORT).show();
    }
    (...)
}

here (line 845) in the if statement add

return;

to make it:

if(addresses==null || addresses.size()==0){
    Toast.makeText(getBaseContext(), "No Location found", Toast.LENGTH_SHORT).show();
    return;
}

or

if(addresses==null || addresses.size()==0){
    Toast.makeText(getBaseContext(), "No Location found", Toast.LENGTH_SHORT).show();
} else for(...) {...}

There NullPointerException is thrown because once you've checked if the addresses is null you don't break the process and even if its null it goes further to the line

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

where addresses.size() (or null.method()) is throwing the exception

from you log, the problem is here:

try {
    // Getting a maximum of 3 Address that matches the input text
    addresses = geocoder.getFromLocationName(locationName[0], 3);
} catch (IOException e) {
    e.printStackTrace();
}

as addresses equals null , so you have to check the Exception catched by the IOException in doInBackground() method, and see why it can't execute getFromLocationName() method.

Then, at you onPostExecute() method make sure to check if addresses is null or not before looping through it in order to make sure it won't cause your app to crash, and this can happen by returning from your if-condition in the beginning of the method:

if(addresses==null || addresses.size()==0){
    Toast.makeText(getBaseContext(), "No Location found", Toast.LENGTH_SHORT).show();
    return;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM