Arpit Arpit - 4 months ago 19
Android Question

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...

Answer

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
 }
...
Comments