Android 基础定位学习

一、开启定位功能。

手机定位类别。

手机定位类别                                         原理
卫星定位服务根据多个卫星与芯片的通讯结果得到手机与卫星的距离
手机定位服务基站定位:根据铁塔对应的信息进行定位
WIFI定位:查询WIFI路由器信息定位

获取定位权限。

首先需要先申请手机的定位权限,并且查询网络状态以及手机状态,于是在AndroidMainfest.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.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <!--查询手机状态-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

获取定位、数据连接、WLAN功能开关状态的判定以及系统界面的跳转。

首先我们获取定位功能的开关状态,构造getLocationstatus方法,用于获取定位开关状态:

  • 从系统服务中获取定位管理器 LocationManager
    LocationManager locationManager = (LocationManager) 
    context.getSystemService(Context.LOCATION_MANAGER);
  • 用isProviderEnable返回开关开启结果
    public static boolean getLocationStatus(Context context){
            LocationManager locationmanager = (LocationManager) 
    context.getSystemService(Context.LOCATION_SERVICE);
            return locationmanager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        }

获取数据连接的开关状态,构造 getMobileDataStatus 方法 

  • 从系统服务器中获取电话管理器 TelephonyManager
  • 通过反射引用隐藏方法 getDataEnable
    public static boolean getMobileDataStatus(Context context){
            TelephonyManager telephonyManager = (TelephonyManager) 
    context.getSystemService(Context.TELEPHONY_SERVICE);
            boolean isOpen = false;
            try {
                String methodName = "getDataEnable";
                Method method = telephonyManager.getClass().getMethod(methodName);
                isOpen = (boolean) method.invoke(telephonyManager);
            } catch (Exception e){
                e.printStackTrace();
            }
            return isOpen;
        }

获取无线网络的开关状态,构造 getWifiStatus 方法 

  • 从服务器管理器中获取无线网络管理器 WifiManager
  • 通过 isWiFiEnable 方法返回结果
    public static boolean getWifiStatus(Context context){
            WifiManager wifiManager = (WifiManager) 
    context.getSystemService(Context.WIFI_SERVICE);
            return wifiManager.isWifiEnabled();
        }

最后我们再通过检验开关状态来向用户申请权限,跳入到相关界面要求用户打开权限

定位设置界面Settings.ACTION_LOCATION_SOURCE_SETTINGS
移动数据界面Settings.ACTION_WIFI_SETTINGS
wifi界面Settings.ACTION_DATA_ROAMING_SETTINGS
  • 创建一个Activity以及相关布局来实现功能
    public class LocationGPS extends AppCompatActivity {
    
        @SuppressLint("MissingInflatedId")
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            EdgeToEdge.enable(this);
            setContentView(R.layout.activity_location_gps);
            findViewById(R.id.location_one).setOnClickListener(v -> {
                if(!LocationUnit.getLocationStatus(this)) startActivity(new 
    Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                if(!LocationUnit.getWifiStatus(this)) startActivity(new 
    Intent(Settings.ACTION_WIFI_SETTINGS));
                if(!LocationUnit.getMobileDataStatus(this)) startActivity(new 
    Intent(Settings.ACTION_DATA_ROAMING_SETTINGS));
            });
        }
    }

 二、获取定位信息

实现获取定位信息需要用到三类工具,定位条件器 Criteria、定位管理器 LoactionManager、定位监听器 LocationListener

定位条件器 Criteria

定位条件器 Criteria 设定关于定位的前提条件

  • setAccuracy: 设置定位精度
    Criteria.ACCURACY_FINE高精度
    Critrtia.ACCURACY_COARSE低精度
  • setSpeedAccuracy: 设置速度精确度
    ACCURACY_HIGH高精度,误差小于100米
    ACCURACY_MEDIUM中等精度,误差100~500米
    ACCURACY_LOW低精度,误差大于500米
  • setAltitudeRequired: 设置是否需要海拔信息
  • setBearingRequired: 设置是否需要方位信息
  • setCostAllowed:设置是否允许运营商收费
  • setPowerRequirement: 设置对电源的需求
    Criteria.POWER_LOW高耗电
    Criteria.POWER_MIEDIUM中耗电
    Criteria.POWER_LOW低耗电

        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE); //定位精确度
        criteria.setAltitudeRequired(true); //海拔信息
        criteria.setBearingRequired(true); //方位信息
        criteria.setPowerRequirement(Criteria.POWER_LOW); // 对电源需求
        criteria.setCostAllowed(false); // 是否允许运营商收费

 定位管理器 LocationManager

LocationManager 主要用于获取定位信息的提供者、设置监听器、获取最后一次的位置信息等,从系统服务LOCATION_SERVICE获取。

  • getBestProvider:获取最佳的定位提供者
    String bestProvider = locationManager.getBestProvider(criteria, true);

    第一个参数时是定位条件器,第二个参数是只选取可用的,其中bestProvider有三个对应返回值gps、network、passive

    gps 卫星定位
    network网络定位
    passive无法定位

  • isProviderEnable:判断指定的定位提供者是否可用
  • getLastKnownLocation:获取最后一次定位的位置信息
  • requestLocationUpdates:设置定位监听器,其中参数,一是提供商,二是位置更新的最小更新时间,三是位置更新的最小更新距离,四是定义好的定位监听器
    locationManager.requestLocationUpdates(provider, 300, 0, locationListener);
  • removeUpdates: 移除位置监听器
  • addGpsStatusListener:添加定位状态的监听器
  • removeGpsStatusListener:删除定位状态的监听器
  • registerGnssStatusCallback:注册全球导航卫星系统的状态监听器
  • unregisterGnssStatusCallback:注销全球导航卫星系统的状态监听器

 定位监听器 LocationLisenter

监听定位信息的变化事件,可重写以下方法

  • onLocationChange:位置发生改变时调用,可以用来更新位置信息
  • onProviderDisabled:在定位提供者被用户禁止时调用
  • onProviderDisabled:在定位提供者被用户开启时调用
  • onStatusChanged:定位提供者的状态变化时调用
    OUT_OF_SERVICE在服务器范围外
    TEMPORARILY_UNAVAILABLE

    暂时不可用

    AVAILABLE可用状态

开始定位 

初始化定位服务

即获取定位器设置相关规则,并且获取到最佳的定位提供者

private void initLocation(){
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE); //定位精确度
        criteria.setAltitudeRequired(true); //海拔信息
        criteria.setBearingRequired(true); //方位信息
        criteria.setPowerRequirement(Criteria.POWER_LOW); // 对电源需求
        criteria.setCostAllowed(false); // 是否允许运营商收费
        String bestProvider = locationManager.getBestProvider(criteria, true);
    }
开始定位

开始定位前,我们需要检测是否开启了定位服务,如果没有开启,我们需要提示用户开启。

if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != 
PackageManager.PERMISSION_GRANTED) {
            permissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
            ActivityCompat.requestPermissions(this, permissions, 458);
        }

 然后我们需要定义一个位置变更监听器 LocationLisenter,但是在此之前我们需要先创造一个locationShow方法来表示出监听器所收集到的定位信息

private void locationShow(Location location){
        String desc = String.format("获取位置时间为%是%s\n 精度为%f,纬度为%f \n高度为%d,精度
为%d米",location.getTime(),location.getLongitude(), 
location.getLatitude(),Math.round(location.getAltitude()), 
Math.round(location.getAccuracy()));
        display = (TextView) findViewById(R.id.location_display);
        display.setText(desc);
    }

其中Location即表示包含的位置信息以及常用的获取方法如下

location.getTime

获取时间信息

location.getLongitude获取经度信息
location.getLatitude

获取纬度信息

location.getAltitude获取海拔信息
location.getAccuracy获取精度信息

 定义位置监听器 LocationLisenter

private final LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(@NonNull Location location) {
            locationShow(location);
        }

    };

将位置监听器设置到定位管理器中

locationManager.requestLocationUpdates(provider, 300, 0, locationListener);

我们再添加一个功能,用于得到上一次的位置信息

Location location = locationManager.getLastKnownLocation(provider);

于是我们便可以初步的获取位置信息,总览如下

private void startLocation(String provider){
        if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            permissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
            ActivityCompat.requestPermissions(this, permissions, 458);
        }
        // 设置位置变更监听器
        locationManager.requestLocationUpdates(provider, 300, 0, locationListener);
        Location location = locationManager.getLastKnownLocation(provider);
    }
    // 定义一个位置变更监听器
    private final LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(@NonNull Location location) {
            locationShow(location);
        }

    };
    @SuppressLint("DefaultLocale")
    private void locationShow(Location location){
        String desc = String.format("获取位置时间为%是%s\n 精度为%f,纬度为%f \n高度为%d,精度为%d米",
                location.getTime(),location.getLongitude(), location.getLatitude(),
                Math.round(location.getAltitude()), Math.round(location.getAccuracy())
        );
        display = (TextView) findViewById(R.id.location_display);
        display.setText(desc);
    }

于是我们得到了100毫秒刷新一次的位置信息

 虽然这可以让我们较为精准地获得到位置信息,但对我们实际获得地理信息并不是很直观,需要我们另外将纬度信息到他处进行转换。这里我是决定用了高德地图地开发平台,流程和这里差不多,但可以更直接地获取到地理信息。

  • 20
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值