手机重启后Android获取位置为空

Posted

技术标签:

【中文标题】手机重启后Android获取位置为空【英文标题】:Android get location is null after phone reboot 【发布时间】:2015-03-26 05:39:10 【问题描述】:

在我的应用程序中,我通过此功能获取手机的位置,但是当我重新启动手机并启动应用程序时,我从该方法中得到 null。我有什么遗漏或做错了吗?我应该怎么做才能解决这个问题?

这是我使用的函数:

public void getAddress() 
        Log.v("--", "get address 1");
        boolean isGPSProviderEnabled = locationManager
                .isProviderEnabled(LocationManager.GPS_PROVIDER);
        boolean network_enabled = locationManager
                .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        Log.v("--", "get address 31 " + isGPSProviderEnabled + " gps  -  "
                + isConnectedToNetwork());

        if (isGPSProviderEnabled || network_enabled) 
            Log.v("--", "get address 2");
            Criteria c = new Criteria();
            Log.v("--", "provider " + locationManager.getBestProvider(c, true));
            locationManager.requestSingleUpdate(
                    locationManager.getBestProvider(c, true),
                    mLocationListener, Looper.myLooper());
            location = locationManager.getLastKnownLocation(locationManager
                    .getBestProvider(c, true));
            if (location == null) 
                Log.v("--", "get address 6");
                // TODO check if this is working
                locationManager.requestSingleUpdate(
                        locationManager.getBestProvider(c, true),
                        mLocationListener, Looper.myLooper());
                locationManager.requestLocationUpdates(
                        locationManager.getBestProvider(c, true), 0, 0,
                        mLocationListener);
                Location oldLocation = new Location("");
                oldLocation.setLatitude(new Double(prefs.getString(
                        Constants.LATITUDE, "48.51")));
                oldLocation.setLongitude(new Double(prefs.getString(
                        Constants.LONGITUDE, "2.20")));
                populateList(oldLocation);
                // locationManager.requestLocationUpdates(
                // locationManager.getBestProvider(c, true), 1000, 100,
                // mLocationListener);
             else 
                Log.v("--", "get address 3");
                if (isConnectedToNetwork()) 
                    new AsyncTask<Void, Void, Void>() 
                        protected Void doInBackground(Void... params) 
                            try 
                                com.quanticapps.athan.utils.Geocoder geocoder = new com.quanticapps.athan.utils.Geocoder(
                                        Main.this);
                                GeocoderModel geocoderModel = geocoder
                                        .getFromLocation(
                                                location.getLatitude(),
                                                location.getLongitude(), 5);
                                city = geocoderModel.getCity();
                                country = geocoderModel.getCountry();
                                prefs.edit().putString(Constants.CITY, city)
                                        .apply();
                                Log.v("--", "get address 4");
                             catch (IOException e) 
                                Log.v("--", "get address 11");
                                e.printStackTrace();
                             catch (LimitExceededException e) 
                                Log.v("--", "get address 12");
                                e.printStackTrace();
                            
                            return null;
                        ;

                        protected void onPostExecute(Void result) 
                            prefs.edit().putString(Constants.COUNTRY, country)
                                    .apply();
                            prefs.edit().putString(Constants.CITY, city)
                                    .apply();
                            populateList(location);
                        ;
                    .execute();
                 else 
                    city = null;
                    Log.v("--", "get address 33 " + location.getLatitude());
                    populateList(location);
                
            
         else 
            Log.v("--", "get address 5");
            startGpsEnableDialog();
        

    

还有我的位置监听器:

private final LocationListener mLocationListener = new LocationListener() 
        @Override
        public void onLocationChanged(final Location location) 
            // TODO
            Log.v("--", "get address 121");
            if (location != null) 
                Main.this.location = location;
                getAddress();
            
        

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) 
            // TODO Auto-generated method stub

        

        @Override
        public void onProviderEnabled(String provider) 
            // TODO Auto-generated method stub
            Log.v("--", "provider enabled");
        

        @Override
        public void onProviderDisabled(String provider) 
            // TODO Auto-generated method stub
            Log.v("--", "provider disabled");
        
    ;

【问题讨论】:

你在说locationManager.getLastKnownLocation吗? @tyczj yap 其返回 null 好吧,你重启了手机,没有缓存的最后一个位置了 可能还没准备好?您是否尝试在重新启动后等待几分钟?就像 appWidget 在重启后一段时间后更新一样,你知道我的意思吗? 【参考方案1】:

当手机重新启动时,缓存的最后一个位置会丢失,所以如果你没有打开一个使用 GPS 的应用程序,如谷歌地图或其他东西,那么将没有最后一个位置。

永远不必将位置返回给您,您应该始终假设它可能为空

【讨论】:

我怎样才能在代码中实现这一点,你能和我分享一些sn-p吗? 获取位置,这是否意味着我应该使用getLastKnownLocation 而不是locationManager.requestLocationUpdates(...); 是的,如果没有位置,您需要请求位置更新并等待【参考方案2】:

如果fusedLocationClient返回空位置,那么您应该使用requestLocationUpdates自己获取位置

    fusedLocationClient.lastLocation
        .addOnSuccessListener  location: Location? ->
            if (location == null) 
                checkLocationSettingsAndStartLocationUpdates(
                    resolutionForResult
                )
             else 
                showUserCurrentLocation(location)
            
        

首先让我们定义resolutionForResult

private val resolutionForResult =
    registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult())  activityResult ->
        if (activityResult.resultCode == RESULT_OK)
            locationManger.startLocationUpdates(requestPermissionLauncher)
        else 
            showMessage("we can't determine your location")
        
    

那么这个方法

private fun checkLocationSettingsAndStartLocationUpdates(
    resolutionForResult: ActivityResultLauncher<IntentSenderRequest>
) 
    val builder = LocationSettingsRequest.Builder()
        .addLocationRequest(locationRequest)
    val client: SettingsClient = LocationServices.getSettingsClient(requireContext)
    val task: Task<LocationSettingsResponse> = client.checkLocationSettings(builder.build())

    task.addOnSuccessListener  _ ->
        startLocationUpdates()
    

    task.addOnFailureListener  exception ->
        if (exception is ResolvableApiException) 
            // Location settings are not satisfied, but this can be fixed
            // by showing the user a dialog.
            try 
                val intentSenderRequest =
                    IntentSenderRequest.Builder(exception.resolution).build()
                resolutionForResult.launch(intentSenderRequest)
             catch (sendEx: IntentSender.SendIntentException) 
            
        
    

然后是startLocationUpdates 实际位置更新发生的地方

fun startLocationUpdates(
    ) 
        if (ActivityCompat.checkSelfPermission(
                requireContext,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                requireContext,
                Manifest.permission.ACCESS_COARSE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) 
            requestPermissionLauncher.launch(
                Manifest.permission.ACCESS_FINE_LOCATION
            )
            return
        
        fusedLocationClient.requestLocationUpdates(
            locationRequest,
            locationCallback,
            Looper.getMainLooper()
        )
    

这里也是locationRequestlocationCallback的声明

private val locationRequest: LocationRequest by lazy 
    LocationRequest.create().apply 
        interval = 10000
        fastestInterval = 5000
        priority = LocationRequest.PRIORITY_HIGH_ACCURACY
    

private var locationCallback: LocationCallback = object : LocationCallback() 
    override fun onLocationResult(locationResult: LocationResult?) 
        locationResult ?: return
        for (location in locationResult.locations) 
            if (location != null) 
                //showUserCurrentLocation(location)
                stopLocationUpdates(this)//if you only need the location once then stop the updates
                break
            
        
    

这里是stopLocationUpdates方法

fun stopLocationUpdates(locationCallback: LocationCallback) 
    fusedLocationClient.removeLocationUpdates(locationCallback)

fusedLocationClient 也是在用户授予权限或检查权限后定义的,

这是检查是否保证权限的方法

fun locationPermissionGranted(): Boolean 
    return when (PackageManager.PERMISSION_GRANTED) 
        ContextCompat.checkSelfPermission(
            requireContext,
            Manifest.permission.ACCESS_FINE_LOCATION
        ) -> 
            fusedLocationClient =
                LocationServices.getFusedLocationProviderClient(requireContext)
            true
        
        else -> 
            false
        
    

如果是假的,那么你需要请求许可

 requestPermission(requestPermissionLauncher: ActivityResultLauncher<String>) 
        requestPermissionLauncher.launch(
            Manifest.permission.ACCESS_FINE_LOCATION
        )
    

这是requestPermissionLauncher的定义

private val requestPermissionLauncher = registerForActivityResult(
    ActivityResultContracts.RequestPermission()
)  isGranted: Boolean ->
    if (isGranted) 
        fusedLocationClient =
                LocationServices.getFusedLocationProviderClient(requireContext())
     else 
        showMessage(
            "the application can't show your " +
                    "current location on the map, because you denied the location permission"
        )
    

【讨论】:

以上是关于手机重启后Android获取位置为空的主要内容,如果未能解决你的问题,请参考以下文章

在 GPS 芯片长时间处于活动状态后,Android 设备需要重启/重启才能获取 GPS 位置

在 android 中获取更新位置和禁用 GPS 后如何获取?

无法在 Android 手机上获取位置

获取手机信号塔位置 - Android

Android 怎么使用 最简单 的方法来获取手机当前的位置(获取手机当前的经,纬度),求详细

Android:如果手机通过 WiFi 连接,则无法从网络获取地理位置