繁体   English   中英

无法连接互联网时应用崩溃

[英]App crashing when internet connection is not available

当应用程序运行且连接断开时,我们面临着一个特殊的问题,它可以正常工作。 但是,当我们尝试搜索特定位置时,它会崩溃。 请参考下面的代码,我们正在使用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());


    }

}

}

}

谢谢...

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

可能是Google Map的api搜索返回null,这就是为什么您会得到null异常的原因,所以只需检查您的api键和google map权限,然后尝试。 否则,请附上错误日志的屏幕截图,以获取更多便利。

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

这里(第845行)在if语句中添加

return;

使它:

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

要么

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

抛出NullPointerException,是因为一旦检查了地址是否为null,您就不会中断该过程,即使其为null,它也将进一步处理

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

其中addresses.size()(或null.method())引发异常

从您的日志中,问题出在这里:

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

因为addresses等于null ,所以您必须在doInBackground()方法中检查IOException doInBackground()的异常,并查看为什么它不能执行getFromLocationName()方法。

然后,在你onPostExecute()方法一定要检查,如果addresses为空或不通过它,以便循环,以确保它不会造成您的应用程序崩溃,并且可能发生这种情况从你返回之前if-condition在方法的开始:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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