Reputation: 33
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...
Upvotes: 0
Views: 125
Reputation: 1567
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
Upvotes: 0
Reputation: 9103
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;
}
Upvotes: 0
Reputation: 10083
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
}
...
Upvotes: 1
Reputation: 62
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.
Upvotes: 0