目录
前言
问题重现
1.无法获取到位置信息的内容提供者
1.1解决方法
2.获取到的位置信息一直为空
2.1解决方法
3.拿到经纬度后使用安卓自带的地理编码器解析报错
3.1解决方法
3.2补充,已解决
尾声
前言
我在使用原生安卓获取当前位置的时候,遇到的一些问题,如果您使用的也是原生安卓的话,这篇文章可能会对您有所帮助。
我的安卓版本是Android12。
真机是小米10S。
问题重现
1.无法获取到位置信息的内容提供者
首先先在AndroidManifest.xml清单文件中添加权限
<!--详细位置权限-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--粗略位置权限-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!--访问网络权限-->
<uses-permission android:name="android.permission.INTERNET"/>
这里申请位置信息可以申请两种权限,我就申请详细的了
package com.example.blogstudy.activity.address;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.example.blogstudy.R;
import java.util.List;
public class AddressJavaActivity extends AppCompatActivity {
private static final String TAG = "AddressJavaActivity";
private Context mContext;
private Activity mActivity;
private final static int GET_ADDRESS = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_address_java);
mContext = AddressJavaActivity.this;
mActivity = AddressJavaActivity.this;
}
@Override
protected void onStart() {
getMyAddress();
super.onStart();
}
private void getMyAddress() {
//位置信息管理对象
LocationManager locationManager = (LocationManager) mActivity.getSystemService(LOCATION_SERVICE);
//获取内容提供者
List<String> providers = locationManager.getProviders(true);
Log.d(TAG, "providers: " + providers);
//providers不会为空,没有的话会返回一共空列表
String provider = null;
if (providers.size() != 0) {
if (providers.contains(LocationManager.NETWORK_PROVIDER)) {//判断列表中有没有网络提供者
//使用网络定位
provider = LocationManager.NETWORK_PROVIDER;
} else if (providers.contains(LocationManager.GPS_PROVIDER)) {//判断列表中有没有GPS
//使用GPS定位
provider = LocationManager.GPS_PROVIDER;
} else if (providers.contains(LocationManager.PASSIVE_PROVIDER)) {//被动提供者
//是一种被动定位方式,它自己不能获取定位信息,而是利用被系统保存的其他程序所更新的定位信息
provider = LocationManager.PASSIVE_PROVIDER;
}
} else {
Toast.makeText(mContext, "没有位置信息内容提供者", Toast.LENGTH_SHORT).show();
}
if (provider != null) {
checkPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION, GET_ADDRESS);
}
}
/**
* 调用完requestPermission() 方法之后,无论是哪一种结果,最终都回调到 onRequestPermissionsResult() 方法中
* 然后对授权结果 grantResults 进行判断
*
* @param requestCode 我们请求权限时自己定义的请求码
* @param permissions 权限列表
* @param grantResults 已经授予的权限列表
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//权限申请成功,判断一下申请的是哪个权限
switch (requestCode){
case GET_ADDRESS:
//对应的操作
break;
default:
Toast.makeText(mContext, "请注意,未知的权限被打开了", Toast.LENGTH_SHORT).show();
}
}else {
//说明权限申请失败,给予对应的提示信息
switch (requestCode){
case GET_ADDRESS:
Toast.makeText(mContext, "定位相关的权限可能没有打开", Toast.LENGTH_SHORT).show();
break;
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
/**
* 检查权限
* @param context 上下文
* @param permission 需要申请的权限
* @param requestCode 请求码
*/
private void checkPermission(Context context, String permission, int requestCode) {
//判断有没有权限
if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
//说明当前没有权限,需要去申请
ActivityCompat.requestPermissions(mActivity, new String[]{permission}, requestCode);
}else {
//说明有有权限,进行对应的操作
switch (requestCode){
case GET_ADDRESS:
//对应的操作
break;
}
}
}
}
我的思路其实很简单,获取到位置信息的内容提供者,然后再去获取权限
然后就一直返回空列表,怎么都获取不到
1.1解决方法
经过我多次的尝试,解决了,怎么说呢,找出解放方法的时候,我觉得我挺傻的
方法就是,先获取权限,再去获取内容提供者。
package com.example.blogstudy.activity.address;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.example.blogstudy.R;
import java.util.List;
public class AddressJavaActivity extends AppCompatActivity {
private static final String TAG = "AddressJavaActivity";
private Context mContext;
private Activity mActivity;
private final static int GET_ADDRESS = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_address_java);
mContext = AddressJavaActivity.this;
mActivity = AddressJavaActivity.this;
}
@Override
protected void onStart() {
checkPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION, GET_ADDRESS);
super.onStart();
}
private void getMyAddress() {
//位置信息管理对象
LocationManager locationManager = (LocationManager) mActivity.getSystemService(LOCATION_SERVICE);
//获取内容提供者
List<String> providers = locationManager.getProviders(true);
Log.d(TAG, "providers: " + providers);
//providers不会为空,没有的话会返回一共空列表
String provider = null;
if (providers.size() != 0) {
if (providers.contains(LocationManager.NETWORK_PROVIDER)) {//判断列表中有没有网络提供者
//使用网络定位
provider = LocationManager.NETWORK_PROVIDER;
} else if (providers.contains(LocationManager.GPS_PROVIDER)) {//判断列表中有没有GPS
//使用GPS定位
provider = LocationManager.GPS_PROVIDER;
} else if (providers.contains(LocationManager.PASSIVE_PROVIDER)) {//被动提供者
//是一种被动定位方式,它自己不能获取定位信息,而是利用被系统保存的其他程序所更新的定位信息
provider = LocationManager.PASSIVE_PROVIDER;
}
} else {
Toast.makeText(mContext, "没有位置信息内容提供者", Toast.LENGTH_SHORT).show();
}
if (provider != null) {
//获取位置信息
}
}
/**
* 调用完requestPermission() 方法之后,无论是哪一种结果,最终都回调到 onRequestPermissionsResult() 方法中
* 然后对授权结果 grantResults 进行判断
*
* @param requestCode 我们请求权限时自己定义的请求码
* @param permissions 权限列表
* @param grantResults 已经授予的权限列表
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//权限申请成功,判断一下申请的是哪个权限
switch (requestCode){
case GET_ADDRESS:
//对应的操作
getMyAddress();
break;
default:
Toast.makeText(mContext, "请注意,未知的权限被打开了", Toast.LENGTH_SHORT).show();
}
}else {
//说明权限申请失败,给予对应的提示信息
switch (requestCode){
case GET_ADDRESS:
Toast.makeText(mContext, "定位相关的权限可能没有打开", Toast.LENGTH_SHORT).show();
break;
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
/**
* 检查权限
* @param context 上下文
* @param permission 需要申请的权限
* @param requestCode 请求码
*/
private void checkPermission(Context context, String permission, int requestCode) {
//判断有没有权限
if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
//说明当前没有权限,需要去申请
ActivityCompat.requestPermissions(mActivity, new String[]{permission}, requestCode);
}else {
//说明有有权限,进行对应的操作
switch (requestCode){
case GET_ADDRESS:
//对应的操作
getMyAddress();
break;
}
}
}
}
这就拿到了!
2.获取到的位置信息一直为空
if (provider != null) {
//获取位置信息
@SuppressLint("MissingPermission") Location location = locationManager.getLastKnownLocation(provider);
Log.d(TAG, "location: " + location);
}
2.1解决方法
上面的写法中,我使用到的内容提供者其实只有一个,换一种写法,不指定内容提供者了,循环那个列表,谁有我就用谁的,如果都没有那就没办法了。
private void getMyAddress() {
//位置信息管理对象
LocationManager locationManager = (LocationManager) mActivity.getSystemService(LOCATION_SERVICE);
//获取内容提供者
List<String> providers = locationManager.getProviders(true);
Log.d(TAG, "providers: " + providers);
//providers不会为空,没有的话会返回一共空列表
if (providers.size() != 0) {
//哪个位置提供者有位置信息,就用哪一个
for (String provider :
providers) {
@SuppressLint("MissingPermission") Location location = locationManager.getLastKnownLocation(provider);
if (location != null){
Log.d(TAG, "location: " + location);
//获取到位置信息后的操作
break;
}
}
} else {
Toast.makeText(mContext, "没有位置信息内容提供者", Toast.LENGTH_SHORT).show();
}
}
结果不尽人意
都没有打印信息,说明三个都是空的,绝了。
然后我检查了一下,我的GPS是打开的,网络是通畅的(我弄了个应用宝进去,可以看见软件信息)
然后,我在模拟机里面下载了一个地图软件,然后使用地图软件定位后,在跑一遍,就有了。
这个其实很明显了,我使用的是LocationManager.PASSIVE_PROVIDER,至于为什么会这样我也不太懂,安卓学的不深,献丑了。
经过测试,Android Sduio的模拟机在关机后,再跑就获取不到信息了。
最后,我在真机上跑了一下,没有问题,可以正常拿到位置信息,真机上多了一个内容提供者
3.拿到经纬度后使用安卓自带的地理编码器解析报错
private void getMyAddress() {
//位置信息管理对象
LocationManager locationManager = (LocationManager) mActivity.getSystemService(LOCATION_SERVICE);
//获取内容提供者
List<String> providers = locationManager.getProviders(true);
Log.d(TAG, "providers: " + providers);
//providers不会为空,没有的话会返回一共空列表
if (providers.size() != 0) {
//哪个位置提供者有位置信息,就用哪一个
for (String provider :
providers) {
@SuppressLint("MissingPermission") Location location = locationManager.getLastKnownLocation(provider);
if (location != null){
Log.d(TAG, "location: " + location);
//获取到位置信息后的操作
getLocationInfo(location);
break;
}
}
} else {
Toast.makeText(mContext, "没有位置信息内容提供者", Toast.LENGTH_SHORT).show();
}
}
/**
* 获取经纬度
* @param location
*/
private void getLocationInfo(Location location) {
//经度
double longitude = location.getLongitude();
//纬度
double latitude = location.getLatitude();
getCityName(latitude, longitude);
}
/**
* 获取城市名
* @param latitude 纬度
* @param longitude 经度
*/
private void getCityName(double latitude, double longitude) {
// 定义位置解析
Geocoder geocoder = new Geocoder(mActivity, Locale.getDefault());
// getFromLocation(纬度, 经度, 最多获取的位置数量)
try {
List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
Address address;
String city = null;
if (addresses.size() != 0) {
// 得到第一个经纬度位置解析信息
address = addresses.get(0);
// 获取到当前城市
city = address.getLocality();
}
if (city != null){
Log.d(TAG, "city: " + city);
}
} catch (IOException e) {
e.printStackTrace();
}
}
3.1解决方法
不知道,经过多次尝试,解决不了。
不过真机上跑没有问题
不过会有一个警告,说运行缓慢
只需要在使用地理编码器逆向解析的时候放在一个新的线程中就可以消除这个警告了
/**
* 获取经纬度
* @param location
*/
private void getLocationInfo(Location location) {
//经度
double longitude = location.getLongitude();
//纬度
double latitude = location.getLatitude();
new Thread(new Runnable() {
@Override
public void run() {
getCityName(latitude, longitude);
}
}).start();
}
3.2补充,已解决
解决方式就是翻墙,我在模拟机上挂了个梯子,然后就没有问题了
不过这个定位很诡异,在美国Mountain View是位于美国加利福尼亚州的城市,翻译过来叫山景城
尾声
我对这篇文章并不满意,因为它并没有解决问题。
如果这篇文章能帮助到您,那么这篇文章就有意义!
感谢您的观看!