java 在不同的方法中组织方法完成的顺序Android Studio

z4bn682m  于 2023-05-12  发布在  Java
关注(0)|答案(1)|浏览(103)

我的应用程序有一个问题,崩溃是因为它调用了方法的其余部分之前,第一个方法完成。下面是错误发生的地方:

@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;
    }
}
k10s72fa

k10s72fa1#

就像你说的,在你启动权限请求之后,你的代码的其余部分就会被执行。通过调用onRequestPermissionsResult,权限请求的实际结果 * 稍后 * 才出现。应用程序不能暂停执行以等待结果,用户做出决定等-它只是一个冻结的应用程序,这就是为什么它会异步发生。
这意味着你也需要编写异步工作的应用程序。你不能只调用onCreate中依赖于被授予权限的东西,因为如果用户还没有被询问,你必须等到处理好。你必须推迟这个任务,直到你准备好执行它。
最简单的方法是将它插入一个函数中,然后在准备好的时候调用它:

protected void initialiseMap() {
    currentLocation = getLastKnownLocation();
    suppMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.maps);
    suppMapFragment.getMapAsync(this);
}

(实际上我不知道哪些行需要延迟,哪些可以在onCreate中安全地调用--您可以解决这个问题!)
现在,您可以在合适的时候调用该函数。一种可能性是在权限检查期间执行此操作-如果您检查了它并且一切正常(例如:你可以立即调用函数并完成。实际上,您已经在fetchLastLocation()中执行了类似的操作-您的OnSuccessListener包含与onCreate中相同的代码。我不知道你的任务是如何工作的,但是如果它很快就调用了那个代码,它不需要在onCreate中,对吗?现在你可以直接调用initialiseMap函数。
您还需要处理未授予权限的情况,该权限将在以后获得。您也可以这样做--当请求成功时,onRequestPermissionsResult调用fetchLastLocation。由于这应该立即传递给调用initialiseMap的任务,因此它应该可以正常工作。(因为你要再次调用这个函数,所以在任何情况下都是在这里进行初始化,也许你根本不需要单独的initialiseMap函数)。
但是不要忘记,您还需要处理未授予权限的情况。你必须决定它应该是什么样子,当你等待的时候,事情应该是什么样子(例如:在fetchLastLocation中,如果您要输入权限请求,则可能需要调用一个显示某些“挂起”状态的函数)。以及如果许可被主动拒绝,事情应该如何看待(例如在onRequestPermissionsResult中,调用显示警告、空Map视图等的函数)。
这是很多话要说 “你几乎已经得到了它,你正在有条件地处理初始化,只是不要在onCreate中调用初始化的东西,它将总是运行” -但希望它有助于使流程更清晰,以及根据发生的情况通过代码的不同路线。你只需要确保初始化只发生在代码中正确的位置,而且这样做绝对安全!

相关问题