首页 > 其他分享 >Android手机定位

Android手机定位

时间:2024-03-14 13:58:30浏览次数:17  
标签:定位 提供者 bundle location 监听器 Criteria 手机 Android

目录

一、定位功能准备

1.申请权限

2.开启定位所需功能

(1)定位

(2)WiFi

(3)移动数据连接(基站)

二、获取定位信息

1.定位条件器 Criteria

2.定位管理器 LocationManager

3.定位监听器 LocationListener

三、解析定位信息 Location

四、案例代码一览


Android的手机定位一般由卫星定位WiFi定位基站定位实现。卫星定位由几个全球卫星导航系统提供,主要包括美国GPS、俄罗斯格洛纳斯、中国北斗。WiFi定位一般通过接入公共WiFi,通过WiFi的MAC地址与电信网络宽带的网络IP,查询WiFi位置获取接入该WiFi的大致位置。基站定位是监测手机SIM卡能搜索到周围的哪些基站,手机必然处于它们信号的重叠位置。

一、定位功能准备

定位需要手机开启对应的功能;定位、无线网络(WiFi)、数据连接。

1.申请权限

定位操作需要获取权限;部分权限涉及用户隐私,需要动态申请。

<!--定位-->
<!--精准定位,一般通过卫星定位,需要动态申请权限-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--粗略定位,一般通过基站定位或WiFi定位,需要动态申请权限-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>


<!--查看网络状态-->
<!--数据网络状态,无需动态申请-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--WiFi网络状态,无需动态申请-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>


<!--查看手机状态,需要动态申请-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

2.开启定位所需功能

(1)定位

使用LocationManager(定位管理器)获取定位功能状态。

//获取定位功能状态
public static boolean getGPSState(Context context){
    //获取定位管理器
    LocationManager locationManager= (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
    
//确认定位功能是否开启,未开启则跳转至定位功能设置界面
public static void checkGPSIsOpen(Context context){
    //未开启定位功能
    if(!getGPSState(context)){
        //跳转至定位功能设置界面
        Intent intent=new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        context.startActivity(intent);
    }
}

(2)WiFi

使用WiFiManager(WiFi管理器)获取WiFi状态及设置WiFi状态。

//获取WiFi状态
public static boolean getWiFiState(Context context){
    WifiManager wifiManager= (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    return wifiManager.isWifiEnabled();
}
    
//设置WiFi状态
public static void setWiFiState(Context context,boolean state){
    WifiManager wifiManager= (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    wifiManager.setWifiEnabled(state);
}

(3)移动数据连接(基站)

使用ConnectivityManager(连接管理器)获取移动数据连接状态及设置连接状态;请注意因为是隐藏方法,需要通过反射调用。

//获取移动数据连接开关的状态
public static boolean getMobileDataState(Context context){
    //获取连接管理器
    ConnectivityManager connectivityManager= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    boolean isOpen=false;
    try {
        //该方法为隐藏方法,需要通过反射调用
        String methodName="getMobileDataEnable";
        Method method=connectivityManager.getClass().getMethod(methodName);
        isOpen= (boolean) method.invoke(connectivityManager);
    }catch (Exception e){
        e.printStackTrace();
    }
        return isOpen;
}

//设置移动数据连接开关的状态
public static void setMobileDataState(Context context,boolean state){
    //获取连接管理器
    ConnectivityManager connectivityManager= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    try{
        //该方法为隐藏方法,需要通过反射调用
        String methodName="setMobileDataEnable";
        Method method=connectivityManager.getClass().getMethod(methodName);
        method.invoke(connectivityManager,state);
    }catch (Exception e){
        e.printStackTrace();
    }
}

二、获取定位信息

开启定位相关功能只是将定位的前提条件准备好,若想获得手机当前所处的位置信息,还要依靠一系列定位工具。与定位信息获取有关的工具有定位条件器Criteria定位管理器LocationManager定位监听器LocationListener

简单来说就是,通过设置好条件的定位条件器(Criteria)获取到最佳的定位信息提供者(String型数据),再向定位管理器添加定位监听器(LocationListener)及定位信息提供者。

下面对这3个工具分别进行介绍。

1.定位条件器 Criteria

定位条件器用于设置定位的前提条件,比如精度、速度、海拔、方位等信息。

有以下6个常用方法:

setAccuracy:设置定位精确度。有两个取值:

  • Criteria.ACCURACY_FINE 表示精度高。
  • Criteria.ACCURACY_COARSE表示精度低。

setSpeedAccuracy:设置速度精确度。速度精确度的取值如下:

  • ACCURACY_HIGH 精度高,误差小于100米
  • ACCURACY_MEDIUM 精度中等,误差在100米到500米之间
  • ACCURACY_LOW 精度低,误差大于500米

setAltitudeRequired:设置是否需要海拔信息。取值true表示需要,false表示不需要。

setBearingRequired:设置是否需要方位信息。取值true表示需要,false表示不需要。

setCostAllowed:设置是否允许运营商收费。取值true表示允许,false表示不允许。

setPowerRequirement:设置对电源的需求。有3个取值:

  • Criteria.POWER_LOW 耗电低
  • Criteria.POWER_MEDIUM 耗电中等
  • Criteria.POWER_HIGH 耗电高

2.定位管理器 LocationManager

定位管理器用于获取定位信息的提供者、设置监听器,并获取最近一次的位置信息。定位管理器的对象从系统服务LOCATION_SERVICE获取。常用方法有以下7个:

getBestProvider:获取最佳的定位提供者(String型数据)。第一个参数为定位条件器Criteria的实例,第二个参数取值true表示只要可用的;在第二参数取true时,无有效定位提供者将返回null。建议第二参数参数false与监听器的onProviderDisabled和onProviderEnabled方法配合使用。定位提供者的取值(名称)说明如下:

  • gps 卫星定位,开启GPS功能
  • network 网络定位,开启数据连接或WLAN功能
  • passive 无法定位,未开启定位相关功能
  • fused 自动选择最佳定位方法

isProviderEnabled:判断指定的定位提供者是否可用。

getLastKnownLocation:获取最近一次的定位地点,返回值为Location对象,如无有效定位信息将返回null

requestLocationUpdates:设置定位监听器。其中,第一个参数为定位提供者(String型),第二个参数为位置更新的最小间隔时间,第三个参数为位置更新的最小距离,第四个参数为定位监听器实例。

removeUpdates:移除定位监听器。

addGpsStatusListener:添加定位状态的监听器。该监听器需实现GpsStatus.Listener 接口的onGpsStatusChanged方法

removeGpsStatusListener:移除定位状态的监听器。

3.定位监听器 LocationListener

定位监听器用于监听定位信息的变化事件,如定位提供者的开关、位置信息发生变化等。该监听器可使用以下4种方法。
onLocationChanged:在位置地点发生变化时调用。在此可获取最新的位置信息。
onProviderDisabled:在定位提供者被用户关闭时调用。

onProviderEnabled:在定位提供者被用户开启时调用。
onStatusChanged:在定位提供者的状态变化时调用。定位提供者的状态取值如下:

  • OUT_OF_SERVICE 在服务范围外
  • TEMPORARILY_UNAVAILABLE 暂时不可用
  • AVAILABLE 可用状态
//获取权限
int i=ActivityCompat.checkSelfPermission(MainActivity.this,"android.permission.ACCESS_FINE_LOCATION");
if(i!= PackageManager.PERMISSION_GRANTED){
    //无权限,请求权限
    requestPermissions(new String[]{"android.permission.ACCESS_FINE_LOCATION"},1234);
}

//创建定位条件器
Criteria criteria=new Criteria();
//设置精度,Criteria.ACCURACY_FINE表示精确,Criteria.ACCURACY_COARSE表示粗略
criteria.setAccuracy(Criteria.ACCURACY_FINE);
//设置是否需要海拔信息
criteria.setAltitudeRequired(true);
//设置是否需要方位信息
criteria.setBearingRequired(true);
//设置是否允许运营商扣费
criteria.setCostAllowed(true);
//设置对电源的需求
criteria.setPowerRequirement(Criteria.POWER_LOW);

//获取定位管理者
LocationManager locationManager= (LocationManager) getSystemService(LOCATION_SERVICE);
//获取最佳定位提供者;第二个参数表示是否只取可用的内容提供者
String locationProvider=locationManager.getBestProvider(criteria,true);

//判断定位提供者是否有效
if(locationProvider!=null){

    //设置定位监听器;第一个参数为定位提供者,第二个参数为最小更新时间,第三个参数为最小更新距离,第四个参数为定位监听器
    locationManager.requestLocationUpdates(locationProvider, 300, 0, new LocationListener() {
        //定位发生变化时触发
        public void onLocationChanged(@NonNull Location location) {
            //解析Location对象中的数据
        }

        //定位提供者不可用时触发
        public void onProviderDisabled(@NonNull String provider) {}

        //定位提供者可用时触发
        public void onProviderEnabled(@NonNull String provider) {}
                
        //状态变更时触发
        public void onStatusChanged(String provider, int status, Bundle extras) {}
    });

    //获取最后的位置
    Location location=locationManager.getLastKnownLocation(locationProvider);

}
else{
    //无有效定位提供者
}

三、解析定位信息 Location

通过LoactionManager对象使用getLastKnownLocation方法以及定位变化监听器可获取到Location型数据。

Location对象可使用以下方法解析数据:

  • getLatitude(): 返回位置的纬度。
  • getLongitude(): 返回位置的经度。
  • getAltitude(): 返回位置的海拔高度,如果没有海拔信息,则返回 0。
  • getAccuracy(): 返回位置的精确度。
  • getProvider(): 返回提供位置信息的服务的名称。
  • getTime(): 返回位置信息的时间戳。
  • hasAltitude(): 检查位置是否包含海拔信息。
  • hasSpeed(): 检查位置是否包含速度信息。
  • hasBearing(): 检查位置是否包含方向信息。
  • hasAccuracy(): 检查位置是否包含精确度信息。
  • distanceTo(Location dest): 计算当前位置到目标位置之间的距离。
  • bearingTo(Location dest): 计算当前位置到目标位置的方向。
  • setLatitude(double latitude): 设置位置的纬度。
  • setLongitude(double longitude): 设置位置的经度。
  • setAltitude(double altitude): 设置位置的海拔高度。
textView.setText("经度:"+location.getLongitude()+"纬度:"+location.getLatitude());

四、案例代码一览

public class MainActivity extends AppCompatActivity {
    private TextView textView = null;
    private Handler handler = null;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取控件
        textView = findViewById(R.id.textView);
        handler = new Handler(new Handler.Callback() {
            @SuppressLint("SetTextI18n")
            public boolean handleMessage(@NonNull Message message) {
                if (message.what == 123) {
                    Bundle bundle = (Bundle) message.obj;
                    //textView.setText("经度:" + bundle.getDouble("a1") + "纬度:" + bundle.getDouble("a2"));

                    textView.setText("经度:"+bundle.getDouble("a1")+"\n纬度:"+bundle.getDouble("a2")+
                            "\n海拔:"+bundle.getDouble("a3")+"\n方向:"+bundle.getFloat("a4")+"\nfrom: "+bundle.getString("a5")+
                            "\n"+bundle.getLong("a6")+"\n"+bundle.getString("a7"));
                    return true;
                }
                return false;
            }
        });
        //确认权限
        int i1 = ActivityCompat.checkSelfPermission(MainActivity.this, "android.permission.ACCESS_FINE_LOCATION");
        if (i1 != PackageManager.PERMISSION_GRANTED) {
            //无权限,申请权限
            requestPermissions(new String[]{"android.permission.ACCESS_FINE_LOCATION"}, 1);
        } else {
            //有权限
            beginLocation(MainActivity.this);
        }


    }


    @SuppressLint("SetTextI18n")
    public void beginLocation(Context context) {
        //准备定位条件器
        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE);//高精度
        criteria.setPowerRequirement(Criteria.POWER_HIGH);
        criteria.setCostAllowed(true);
        criteria.setAltitudeRequired(true);//海拔
        criteria.setBearingRequired(true);//方向
        //获取定位管理器
        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        //获取最佳定位提供者
        String provider = locationManager.getBestProvider(criteria, true);
        if (provider != null) {
            //添加监听器
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            Log.d("OK","定位提供者为"+provider);
            locationManager.requestLocationUpdates(provider, 300, 0, new LocationListener() {
                Location oldLocation=null;
                public void onLocationChanged(@NonNull Location location) {
                    if (location != null) {
                        oldLocation=location;
                        Message message = new Message();
                        message.what = 123;
                        Bundle bundle = new Bundle();
                        bundle.putDouble("a1", location.getLongitude());
                        bundle.putDouble("a2", location.getLatitude());
                        bundle.putDouble("a3",location.getAltitude());
                        bundle.putFloat("a4",location.getBearing());
                        bundle.putString("a5",location.getProvider());
                        bundle.putLong("a6",location.getTime());
                        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        String date=f.format(location.getTime());
                        bundle.putString("a7",date);
                        message.obj = bundle;
                        handler.sendMessage(message);
                    }
                }

                public void onProviderDisabled(@NonNull String provider) {
                    textView.setText("定位关停 - "+provider);
                }

                @Override
                public void onProviderEnabled(@NonNull String provider) {
                    textView.setText("定位启动 - "+provider);
                    onLocationChanged(oldLocation);
                }
            });
            //获取最后结果
            Location location=locationManager.getLastKnownLocation(provider);
            if(location!=null){
                SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String date=f.format(location.getTime());
                textView.setText("经度:"+location.getLongitude()+"\n纬度:"+location.getLatitude()+
                        "\n海拔:"+location.getAltitude()+"\n方向:"+location.getBearing()+"\nfrom: "+location.getProvider()+
                        "\n"+date);
            }
            else{
                textView.setText("无定位信息");
            }
        }
        else {
            textView.setText("定位功能未开启");
        }
    }

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestCode==1){
            for(int i=0;i<permissions.length;i++){
                if(grantResults[i]!=PackageManager.PERMISSION_GRANTED){
                    requestPermissions(new String[]{"android.permission.ACCESS_FINE_LOCATION"},1);
                    return;
                }
            }
            beginLocation(MainActivity.this);
        }
    }
}

tag:定位;Location;基站定位;WiFi定位

标签:定位,提供者,bundle,location,监听器,Criteria,手机,Android
From: https://blog.csdn.net/m0_57150356/article/details/136501104

相关文章

  • java毕设安卓基于Android的志愿者服务系统(开题+源码)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、研究背景在当今信息化社会,移动互联网技术的迅猛发展正深刻改变着人们的生活方式。特别是在社会公益领域,志愿者服务作为社会文明进步的重要标志,其组织与管......
  • 想用手机做ai短视频的ai短视频伙伴快看看,这款app可以让你的图片唱歌,说话,对口型最好的a
    经常看到很多ai短视频伙伴过来问,你这里有没有手机可以用的ai短视频工具,说实话到目前为止,手机能够使用的ai工具真的非常少,高粱seo记得仅仅有一款做水流瀑布流动类的app,之前很多人在直播间搞培训用的,因为涉及到ai方面的工具,一般来说消耗资源比较大,一般电脑用起来都费劲,更别说手......
  • Android14音频进阶:生产者与消费者模型(六十二)
    简介:CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!优质专栏:Audio工程师进阶系列【原创干货持续更新中……】......
  • 定位
    相对定位:relative相对于自己原来的位置,不会脱离文档流,不会对相邻元素位置产生影响,也不会改变元素原有的显示模式,可以与浮动一起设置。绝对定位:absolute相对于第一个定位的祖先元素的内边距来定位(从父元素开始网上找),如果没有定位的祖先元素,则相对于整个页面定位。绝对定位的特......
  • 深入理解Android启动流程:从按下电源键到Launcher的呈现
    引言Android系统的启动过程是一个复杂而精巧的机制,涉及到硬件初始化、内核引导、系统服务加载等多个环节。本文将对Android设备从按下电源键到启动完成并显示Launcher界面这一整个启动流程进行详细的剖析。一、硬件初始化与BootLoader阶段硬件初始化:当用户按下电源键后,......
  • java毕设安卓基于Android的校园二手交易平台(开题+源码)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着移动互联网技术的飞速发展,智能手机已成为大学生生活中不可或缺的一部分。特别是在数字化校园建设的推动下,各类移动应用纷纷涌现,极大地便利了师生......
  • js-正负数保留小数点特定位数
    functionround(num,iCount){//iCount保留几位小数letchangeNum=numletzs=true//判断是否是负数if(changeNum<0){changeNum=Math.abs(changeNum)z......
  • Android View 绘制原理
    在Android中,视图绘制原理是指系统如何创建、管理和更新用户界面上显示的各种视图(Views)的过程。以下是Android视图绘制的基本原理概述:1.**视图层次结构**:  -AndroidUI是由一系列嵌套的视图构成的层次结构,顶层通常是`DecorView`,它包裹着`ContentView`(即Activity的根视图......
  • Android Studio开发学习(一)———下载安装
    AndroidStudio版本:android-studio-2023.2.1.23-windows安装AndroidStudio官网下载   androidstudio官网安装AndroidStudio在安装目标盘创建文件夹,不要有中文文件夹,文件夹名称不要带空格。本次安装在VMware虚拟机中安装,只有一个C盘,无其他盘,所以自定义安装目录都在C......
  • Android开发window安装Ubuntu虚拟机编译aosp安卓12源代码
    Window安装Ubuntu虚拟机编译aosp安卓12源代码1.安装VMWare虚拟机,以及安装Ubuntu1.1下载安装VMWare虚拟机下载地址和密钥,请见:https://www.cnblogs.com/yongfengnice/p/17413934.html1.2下载安装Ubuntuubuntu下载地址:https://ubuntu.com/download/alternative-dow......