我的应用程序有一个问题,崩溃是因为它调用了方法的其余部分之前,第一个方法完成。下面是错误发生的地方:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
client = LocationServices.getFusedLocationProviderClient(this);
fetchLastLocation();
LManager = (LocationManager) getSystemService(LOCATION_SERVICE);
currentLocation = getLastKnownLocation();
suppMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.maps);
suppMapFragment.getMapAsync(this);
}
@Override
public void onMapReady(@NonNull GoogleMap googleMap) {
this.mMap = googleMap;
CheckGps();
LatLng latLng = null;
if(currentLocation == null)
{
currentLocation = getLastKnownLocation();
latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
}
else{
latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
}
MarkerOptions markerOptions = new MarkerOptions().position(latLng).title("You are here!");
googleMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 12));
googleMap.addMarker(markerOptions);
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
return;
}
googleMap.setMyLocationEnabled(true);
}
在OnCreate
方法中,它运行一个名为fetchLastLocaiton()
的方法,该方法要求手机允许使用该位置,但在调用fetchLastLocaiton()
并给出响应之前,OnMapReadyCallback()
使应用程序崩溃,从而导致应用程序在您第一次启动应用程序时崩溃。并导致崩溃,每次你运行应用程序没有位置被打开你的手机(其中CheckGps()
方法检查)。
AsyncTask或方法中的新Thread是否有帮助?还是我代码中的其他地方有错误?如果是这样,下面是代码的其余部分:
package com.example.ilovemilfs;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.TextureView;
import android.view.View;
import android.widget.Toast;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;
import java.util.jar.Attributes;
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
GoogleMap mMap;
SupportMapFragment suppMapFragment;
Location currentLocation;
FusedLocationProviderClient client;
private static final int REQUEST_CODE = 101;
LocationRequest locationRequest;
private LocationManager LManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
client = LocationServices.getFusedLocationProviderClient(this);
fetchLastLocation();
LManager = (LocationManager) getSystemService(LOCATION_SERVICE);
currentLocation = getLastKnownLocation();
suppMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.maps);
suppMapFragment.getMapAsync(this);
}
private void fetchLastLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE);
CheckGps();
return;
}
Task<Location> task = client.getLastLocation();
task.addOnSuccessListener(new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if (location != null) {
currentLocation = location;
suppMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.maps);
suppMapFragment.getMapAsync(MainActivity.this);
}
}
});
}
@Override
public void onMapReady(@NonNull GoogleMap googleMap) {
this.mMap = googleMap;
CheckGps();
LatLng latLng = null;
if(currentLocation == null)
{
currentLocation = getLastKnownLocation();
latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
}
else{
latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
}
MarkerOptions markerOptions = new MarkerOptions().position(latLng).title("You are here!");
googleMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 12));
googleMap.addMarker(markerOptions);
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
return;
}
googleMap.setMyLocationEnabled(true);
}
private void CheckGps() {
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(5000);
locationRequest.setFastestInterval(3000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest).setAlwaysShow(true);
Task<LocationSettingsResponse> locationSettingsResponseTask = LocationServices.getSettingsClient(getApplicationContext()).checkLocationSettings(builder.build());
locationSettingsResponseTask.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
@Override
public void onComplete(@NonNull Task<LocationSettingsResponse> task) {
try {
LocationSettingsResponse response = task.getResult(ApiException.class);
Toast.makeText(MainActivity.this, "Gps is already enabled", Toast.LENGTH_SHORT).show();
} catch (ApiException e) {
if (e.getStatusCode() == LocationSettingsStatusCodes.RESOLUTION_REQUIRED) {
ResolvableApiException resolvableApiException = (ResolvableApiException) e;
try {
resolvableApiException.startResolutionForResult(MainActivity.this, 101);
} catch (IntentSender.SendIntentException ex) {
throw new RuntimeException(ex);
}
}
if (e.getStatusCode() == LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE) {
Toast.makeText(MainActivity.this, "Setting not available", Toast.LENGTH_SHORT).show();
}
}
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
fetchLastLocation();
}
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 101) {
if (resultCode == RESULT_OK) {
Toast.makeText(this, "GPS is enabled", Toast.LENGTH_SHORT).show();
}
if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Denied GPS permission", Toast.LENGTH_SHORT).show();
}
}
}
public void ibLokacija(View view) {
CheckGps();
}
public void ibRefreshRef(View view) {
Intent intent = getIntent();
finish();
startActivity(intent);
}
public void ibHospital(View view) {
NearbyHospitals();
}
public void NearbyHospitals() {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Handler handler = new Handler(Looper.getMainLooper());
Location l = this.currentLocation;
executorService.execute(new Runnable() {
@Override
public void run() {
try{
String uri = "https://overpass-api.de/api/interpreter?data=[out:json][timeout:25];(node%5B%22amenity%22%3D%22hospital%22%5D(around%3A10000%2C%20"
+ String.valueOf(l.getLatitude()) + "%2C%20"
+ String.valueOf(l.getLongitude()) + ");)%3Bout%20body;";
URL url = new URL(uri);
HttpURLConnection huc = (HttpURLConnection) url.openConnection();
InputStream inputStream = (InputStream) huc.getContent();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
StringBuilder stringBuilder = new StringBuilder();
String line = null;
while((line = bufferedReader.readLine()) != null){
stringBuilder.append(line + "\n");
}
inputStream.close();
String string = stringBuilder.toString();
handler.post(new Runnable() {
@Override
public void run() {
Hospitals(string);
}
});
}
catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void Hospitals(String s) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Handler handler = new Handler(Looper.getMainLooper());
GoogleMap googleMap = this.mMap;
executorService.execute(new Runnable() {
@Override
public void run() {
try {
JSONObject jsonObject = new JSONObject(s);
JSONArray jsonArray = jsonObject.getJSONArray("elements");
Integer integer = jsonArray.length();
String s1 = integer.toString();
for(int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
JSONObject locationJSON1 = jsonObject1.getJSONObject("tags");
String name = null;
if(locationJSON1.isNull("name")){
name = "Hospital";
}
else{
name = locationJSON1.getString("name");
}
String lat_street = jsonArray.getJSONObject(i).getString("lat");
String lon_housenumber = jsonArray.getJSONObject(i).getString("lon");
LatLng latLng = null;
if(lat_street != null && lon_housenumber != null){
latLng = new LatLng(Double.parseDouble(lat_street), Double.parseDouble(lon_housenumber));
}
else if(jsonArray.getJSONObject(i).isNull("lat") && jsonArray.getJSONObject(i).isNull("lon") && locationJSON1.isNull("addr:street") && locationJSON1.isNull("addr:housenumber")){
latLng = getLocationFromName(MainActivity.this, name);
}
else{
lat_street = locationJSON1.getString("addr:street");
lon_housenumber = locationJSON1.getString("addr:housenumber");
latLng = getLocationFromAddress(MainActivity.this, lat_street + lon_housenumber);
}
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.title(name);
markerOptions.position(latLng);
handler.post(new Runnable() {
@Override
public void run() {
googleMap.addMarker(markerOptions);
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public LatLng getLocationFromAddress(Context context, String strAddress){
Geocoder geocoder = new Geocoder(context);
List<Address> addresses;
LatLng latLng = null;
try{
addresses = geocoder.getFromLocationName(strAddress, 10);
if(addresses == null){
return null;
}
Address location = addresses.get(0);
location.getLatitude();
location.getLongitude();
latLng = new LatLng(location.getLatitude(), location.getLongitude());
} catch (Exception e) {
e.printStackTrace();
}
return latLng;
}
public LatLng getLocationFromName(Context context, String name){
Geocoder geocoder = new Geocoder(context);
List<Address> addresses = null;
LatLng latLng = null;
try{
addresses = geocoder.getFromLocationName(name, 10);
Address address = addresses.get(0);
address.getLatitude();
address.getLongitude();
latLng = new LatLng(address.getLatitude(), address.getLongitude());
} catch (Exception e) {
e.printStackTrace();
}
return latLng;
}
private Location getLastKnownLocation(){
Location l = null;
LocationManager locationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);
List<String> providers = locationManager.getProviders(true);
Location betterLocation = null;
for(String provider : providers){
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){
l = locationManager.getLastKnownLocation(provider);
}
if(l == null){
continue;
}
if(betterLocation == null || l.getAccuracy() < betterLocation.getAccuracy()){
betterLocation = l;
}
}
return betterLocation;
}
}
1条答案
按热度按时间k10s72fa1#
就像你说的,在你启动权限请求之后,你的代码的其余部分就会被执行。通过调用
onRequestPermissionsResult
,权限请求的实际结果 * 稍后 * 才出现。应用程序不能暂停执行以等待结果,用户做出决定等-它只是一个冻结的应用程序,这就是为什么它会异步发生。这意味着你也需要编写异步工作的应用程序。你不能只调用
onCreate
中依赖于被授予权限的东西,因为如果用户还没有被询问,你必须等到处理好。你必须推迟这个任务,直到你准备好执行它。最简单的方法是将它插入一个函数中,然后在准备好的时候调用它:
(实际上我不知道哪些行需要延迟,哪些可以在
onCreate
中安全地调用--您可以解决这个问题!)现在,您可以在合适的时候调用该函数。一种可能性是在权限检查期间执行此操作-如果您检查了它并且一切正常(例如:你可以立即调用函数并完成。实际上,您已经在
fetchLastLocation()
中执行了类似的操作-您的OnSuccessListener
包含与onCreate
中相同的代码。我不知道你的任务是如何工作的,但是如果它很快就调用了那个代码,它不需要在onCreate
中,对吗?现在你可以直接调用initialiseMap
函数。您还需要处理未授予权限的情况,该权限将在以后获得。您也可以这样做--当请求成功时,
onRequestPermissionsResult
调用fetchLastLocation
。由于这应该立即传递给调用initialiseMap
的任务,因此它应该可以正常工作。(因为你要再次调用这个函数,所以在任何情况下都是在这里进行初始化,也许你根本不需要单独的initialiseMap
函数)。但是不要忘记,您还需要处理未授予权限的情况。你必须决定它应该是什么样子,当你等待的时候,事情应该是什么样子(例如:在
fetchLastLocation
中,如果您要输入权限请求,则可能需要调用一个显示某些“挂起”状态的函数)。以及如果许可被主动拒绝,事情应该如何看待(例如在onRequestPermissionsResult
中,调用显示警告、空Map视图等的函数)。这是很多话要说 “你几乎已经得到了它,你正在有条件地处理初始化,只是不要在
onCreate
中调用初始化的东西,它将总是运行” -但希望它有助于使流程更清晰,以及根据发生的情况通过代码的不同路线。你只需要确保初始化只发生在代码中正确的位置,而且这样做绝对安全!