当前位置:

首页 > 系统应用 > 10.14 Android GPS初涉

10.14 Android GPS初涉

本文目录

    本节引言: 说到GPS这个名词,相信大家都不陌生,GPS全球定位技术嘛,嗯,Android中定位的方式 一般有这四种:GPS定位,WIFI定准,基站定位,AGPS定位(基站+GPS); 这套系列教程聚焦的,是 GPS 定位最基础、也最常用的那部分能力。说白了,GPS 依靠的是设备与卫星之间的信号交互

    本节引言:

    说到GPS这个名词,相信大家都不陌生,GPS全球定位技术嘛,嗯,Android中定位的方式 一般有这四种:GPS定位,WIFI定准,基站定位,AGPS定位(基站+GPS);

    这套系列教程聚焦的,是 GPS 定位最基础、也最常用的那部分能力。说白了,GPS 依靠的是设备与卫星之间的信号交互,来确定当前所处的经纬度,整体定位精度通常不错。不过它也不是没有短板,最明显的一点就是:室内几乎无法使用。原因也不复杂,想让 GPS 保持较为准确的定位,通常需要同时接收到 4 颗及以上卫星的信号。反过来说,如果人处在室外,而且网络不可用,GPS 依然照样能发挥作用。

    本节我们就来探讨下Android中的GPS的基本用法~

    1.定位相关的一些API

    1)LocationManager

    官方API文档:LocationManager

    这玩意是系统服务来的,不能直接new,需要:

    LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

    另外用GPS定位别忘了加权限:

    好的,获得了LocationManager对象后,我们可以调用下面这些常用的方法:

    • addGpsStatusListener(GpsStatus.Listener listener):添加一个GPS状态监听器
    • addProximityAlert(double latitude, double longitude, float radius, long expiration, PendingIntent intent): 添加一个临界警告
    • getAllProviders():获取所有的LocationProvider列表
    • getBestProvider(Criteria criteria, boolean enabledOnly):根据指定条件返回最优LocationProvider
    • getGpsStatus(GpsStatus status):获取GPS状态
    • getLastKnownLocation(String provider):根据LocationProvider获得最近一次已知的Location
    • getProvider(String name):根据名称来获得LocationProvider
    • getProviders(boolean enabledOnly):获取所有可用的LocationProvider
    • getProviders(Criteria criteria, boolean enabledOnly):根据指定条件获取满足条件的所有LocationProvider
    • isProviderEnabled(String provider):判断指定名称的LocationProvider是否可用
    • removeGpsStatusListener(GpsStatus.Listener listener):删除GPS状态监听器
    • removeProximityAlert(PendingIntent intent):删除一个临近警告
    • requestLocationUpdates(long minTime, float minDistance, Criteria criteria, PendingIntent intent): 通过制定的LocationProvider周期性地获取定位信息,并通过Intent启动相应的组件
    • requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener): 通过制定的LocationProvider周期性地获取定位信息,并触发listener所对应的触发器

    2)LocationProvider(定位提供者)

    官方API文档:LocationProvider

    这比是GPS定位组件的抽象表示,调用下述方法可以获取该定位组件的相关信息!

    常用的方法如下:

    • getAccuracy():返回LocationProvider精度
    • getName():返回LocationProvider名称
    • getPowerRequirement():获取LocationProvider的电源需求
    • hasMonetaryCost():返回该LocationProvider是收费还是免费的
    • meetsCriteria(Criteria criteria):判断LocationProvider是否满足Criteria条件
    • requiresCell():判断LocationProvider是否需要访问网络基站
    • requiresNetwork():判断LocationProvider是否需要访问网络数据
    • requiresSatellite():判断LocationProvider是否需要访问基于卫星的定位系统
    • supportsAltitude():判断LocationProvider是否支持高度信息
    • supportsBearing():判断LocationProvider是否支持方向信息
    • supportsSpeed():判断是LocationProvider否支持速度信息

    3)Location(位置信息)

    官方API文档:Location

    位置信息的抽象类,我们可以调用下述方法获取相关的定位信息!

    常用方法如下:

    • float getAccuracy():获得定位信息的精度
    • double getAltitude():获得定位信息的高度
    • float getBearing():获得定位信息的方向
    • double getLatitude():获得定位信息的纬度
    • double getLongitude():获得定位信息的精度
    • String getProvider():获得提供该定位信息的LocationProvider
    • float getSpeed():获得定位信息的速度
    • boolean hasAccuracy():判断该定位信息是否含有精度信息

    4)Criteria(过滤条件)

    官方API文档:Criteria

    获取LocationProvider时,可以设置过滤条件,就是通过这个类来设置相关条件的~

    常用方法如下:

    • setAccuracy(int accuracy):设置对的精度要求
    • setAltitudeRequired(boolean altitudeRequired):设置是否要求LocationProvider能提供高度的信息
    • setBearingRequired(boolean bearingRequired):设置是否要LocationProvider求能提供方向信息
    • setCostAllowed(boolean costAllowed):设置是否要求LocationProvider能提供方向信息
    • setPowerRequirement(int level):设置要求LocationProvider的耗电量
    • setSpeedRequired(boolean speedRequired):设置是否要求LocationProvider能提供速度信息

    2.获取LocationProvider的例子

    运行效果图:

    由图可以看到,当前可用的LocationProvider有三个,分别是:

    • passive:被动提供,由其他程序提供
    • gps:通过GPS获取定位信息
    • network:通过网络获取定位信息

    实现代码:

    布局文件:activity_main.xml:

    
    

    MainActivity.ja va:

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btn_one;
        private Button btn_two;
        private Button btn_three;
        private TextView tv_result;
        private LocationManager lm;
        private List pNames = new ArrayList(); // 存放LocationProvider名称的集合
    @Override
        protected void onCreate(Bundle sa vedInstanceState) {
            super.onCreate(sa vedInstanceState);
            setContentView(R.layout.activity_main);
            lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            bindViews();
        }
    private void bindViews() {
            btn_one = (Button) findViewById(R.id.btn_one);
            btn_two = (Button) findViewById(R.id.btn_two);
            btn_three = (Button) findViewById(R.id.btn_three);
            tv_result = (TextView) findViewById(R.id.tv_result);
    btn_one.setOnClickListener(this);
            btn_two.setOnClickListener(this);
            btn_three.setOnClickListener(this);
        }
    @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn_one:
                    pNames.clear();
                    pNames = lm.getAllProviders();
                    tv_result.setText(getProvider());
                    break;
                case R.id.btn_two:
                    pNames.clear();
                    Criteria criteria = new Criteria();
                    criteria.setCostAllowed(false);   //免费
                    criteria.setAltitudeRequired(true);  //能够提供高度信息
                    criteria.setBearingRequired(true);   //能够提供方向信息
                    pNames = lm.getProviders(criteria, true);
                    tv_result.setText(getProvider());
                    break;
                case R.id.btn_three:
                    pNames.clear();
                    pNames.add(lm.getProvider(LocationManager.GPS_PROVIDER).getName()); //指定名称
                    tv_result.setText(getProvider());
                    break;
            }
        }
    //遍历数组返回字符串的方法
        private String getProvider(){
            StringBuilder sb = new StringBuilder();
            for (String s : pNames) {
                sb.append(s + "n");
            }
            return sb.toString();
        }
    }

    3.判断GPS是否打开以及打开GPS的两种方式

    在我们使用GPS定位前的第一件事应该是去判断GPS是否已经打开或可用,没打开的话我们需要去 打开GPS才能完成定位!这里不考虑AGPS的情况~

    1)判断GPS是否可用

    private boolean isGpsAble(LocationManager lm){
        return lm.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)?true:false;
    }

    2)检测到GPS未打开,打开GPS

    方法一:强制打开GPS,Android 5.0后无用....

    //强制帮用户打开GPS 5.0以前可用
    private void openGPS(Context context){
        Intent gpsIntent = new Intent();
        gpsIntent.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider");
        gpsIntent.addCategory("android.intent.category.ALTERNATIVE");
        gpsIntent.setData(Uri.parse("custom:3"));
        try {
            PendingIntent.getBroadcast(LocationActivity.this, 0, gpsIntent, 0).send();
        } catch (PendingIntent.CanceledException e) {
            e.printStackTrace();
        }
    }

    方法二:打开GPS位置信息设置页面,让用户自行打开

    //打开位置信息设置页面让用户自己设置
    private void openGPS2(){
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        startActivityForResult(intent,0);
    }

    4.动态获取位置信息

    这个非常简单,调用requestLocationUpdates方法设置一个LocationListener定时检测位置而已!

    示例代码如下:

    布局:activity_location.xml:

    
    
    
    

    LocationActivity.ja va:

    /**
     * Created by Jay on 2015/11/20 0020.
     */
    public class LocationActivity extends AppCompatActivity {
    private LocationManager lm;
        private TextView tv_show;
    @Override
        public void onCreate(Bundle sa vedInstanceState) {
            super.onCreate(sa vedInstanceState);
            setContentView(R.layout.activity_location);
            tv_show = (TextView) findViewById(R.id.tv_show);
            lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            if (!isGpsAble(lm)) {
                Toast.makeText(LocationActivity.this, "请打开GPS~", Toast.LENGTH_SHORT).show();
                openGPS2();
            }
            //从GPS获取最近的定位信息
            Location lc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            updateShow(lc);
            //设置间隔两秒获得一次GPS定位信息
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 8, new LocationListener() {
                @Override
                public void onLocationChanged(Location location) {
                    // 当GPS定位信息发生改变时,更新定位
                    updateShow(location);
                }
    @Override
                public void onStatusChanged(String provider, int status, Bundle extras) {
    }
    @Override
                public void onProviderEnabled(String provider) {
                    // 当GPS LocationProvider可用时,更新定位
                    updateShow(lm.getLastKnownLocation(provider));
                }
    @Override
                public void onProviderDisabled(String provider) {
                    updateShow(null);
                }
            });
        }
    //定义一个更新显示的方法
        private void updateShow(Location location) {
            if (location != null) {
                StringBuilder sb = new StringBuilder();
                sb.append("当前的位置信息:n");
                sb.append("精度:" + location.getLongitude() + "n");
                sb.append("纬度:" + location.getLatitude() + "n");
                sb.append("高度:" + location.getAltitude() + "n");
                sb.append("速度:" + location.getSpeed() + "n");
                sb.append("方向:" + location.getBearing() + "n");
                sb.append("定位精度:" + location.getAccuracy() + "n");
                tv_show.setText(sb.toString());
            } else tv_show.setText("");
        }
    private boolean isGpsAble(LocationManager lm) {
            return lm.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER) ? true : false;
        }
    //打开设置页面让用户自己设置
        private void openGPS2() {
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivityForResult(intent, 0);
        }
    }

    好的,非常简单,因为gps需要在室外才能用,于是趁着这个机会小跑出去便利店买了杯奶茶, 顺道截下图~

    requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener)

    一旦时间间隔超过 minTime(单位:毫秒),或者位置变化超过 minDistance(单位:米),系统就会触发 listener 中的方法来更新 GPS 信息。通常更建议把 minTime 设为不小于 60000,也就是 1 分钟,这样整体会更高效,同时也更省电。当然,如果业务场景确实要求尽可能实时地刷新 GPS 数据,那么也可以直接把 minTime 和 minDistance 都设置为 0。

    对了,别忘了,你还需要一枚权限:

    5.临近警告(地理围栏)

    嗯,就是固定一个点,当手机与该点的距离少于指定范围时,可以触发对应的处理! 有点像地理围栏...我们可以调用LocationManager的addProximityAlert方法添加临近警告! 完整方法如下:

    addProximityAlert(double latitude,double longitude,float radius,long expiration,PendingIntent intent)

    属性说明:

    • latitude:指定固定点的经度
    • longitude:指定固定点的纬度
    • radius:指定半径长度
    • expiration:指定经过多少毫秒后该临近警告就会过期失效,-1表示永不过期
    • intent:该参数指定临近该固定点时触发该intent对应的组件

    示例代码如下:

    ProximityActivity.ja va:

    /**
     * Created by Jay on 2015/11/21 0021.
     */
    public class ProximityActivity extends AppCompatActivity {
        private LocationManager lm;
        @Override
        public void onCreate(Bundle sa vedInstanceState) {
            super.onCreate(sa vedInstanceState);
            setContentView(R.layout.activity_proximity);
            lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            //定义固定点的经纬度
            double longitude = 113.56843;
            double latitude = 22.374937;
            float radius = 10;     //定义半径,米
            Intent intent = new Intent(this, ProximityReceiver.class);
            PendingIntent pi = PendingIntent.getBroadcast(this, -1, intent, 0);
            lm.addProximityAlert(latitude, longitude, radius, -1, pi);
        }
    }

    还需要注册一个广播接收者:ProximityReceiver.ja va:

    /**
     * Created by Jay on 2015/11/21 0021.
     */
    public class ProximityReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            boolean isEnter = intent.getBooleanExtra( LocationManager.KEY_PROXIMITY_ENTERING, false);
            if(isEnter) Toast.makeText(context, "你已到达南软B1栋附近", Toast.LENGTH_LONG).show();
            else Toast.makeText(context, "你已离开南软B1栋附近", Toast.LENGTH_LONG).show();
        }
    }

    别忘了注册:

    运行效果图:

    PS:好吧,设置了10m,结果我从B1走到D1那边,不止10m了吧...还刚好下雨

    6.本节示例代码下载

    GPSDemo.zip

    本节小结:

    好的,本节给大家介绍了Android中GPS定位的一些基本用法,非常简单,内容部分参考的 李刚老师的《Android疯狂讲义》,只是对例子进行了一些修改以及进行了可用性的测试! 本节就到这里,谢谢~

    本文内容来源于网友投稿,如有侵权请联系删除。
    作者最新文章
    系统应用 Android
    相关文章 更多
    docker容器自动重启怎么解决 排查原因与修复方法
    docker容器自动重启怎么解决 排查原因与修复方法

    遇到Docker容器频繁自动重启?本文提供从查看容器日志、解读退出代码到配置Restart Policy的完整排查与修复方案,确保服务稳定性。

    Linux设置静态路由命令与永久生效教程
    Linux设置静态路由命令与永久生效教程

    学习如何在Linux中使用命令行添加临时静态路由,并通过修改网络配置文件实现重启后依然有效的永久静态路由设置,涵盖CentOS和Ubuntu的不同配置方法。

    摄像头连接电脑后怎么打开查看实时画面教程
    摄像头连接电脑后怎么打开查看实时画面教程

    摄像头连接电脑后不知如何查看画面?本教程演示如何使用Windows自带的“相机”应用快速调取实时视频流,无需下载额外软件,步骤简单直观,适用于大多数USB及内置摄像头。

    如何在 windows 11 关闭自动关机
    如何在 windows 11 关闭自动关机

    针对 Windows 11 电脑在无人操作时自动关机或重启的问题,本文详解如何通过任务计划程序禁用更新重启任务,并调整电源睡眠策略,从根源解决非预期的自动关机现象。

    android页面跳转屏幕方向改变变量如何解决
    android页面跳转屏幕方向改变变量如何解决

    详解Android应用中处理屏幕旋转导致Activity重建时的变量保存方法,包括使用onSaveInstanceState捆绑包和Jetpack ViewModel架构组件的最佳实践。

    电脑摄像头怎么测试人脸识别功能及效果判断方法
    电脑摄像头怎么测试人脸识别功能及效果判断方法

    详细讲解在Windows电脑上测试摄像头人脸识别功能的步骤,包括开启Windows Hello、录入面部数据、不同环境下的效果验证及常见问题排查,帮助用户确认设备兼容性与识别准确率。

    docker 容器无法启动的配置检查命令及排查方法
    docker 容器无法启动的配置检查命令及排查方法

    当 Docker 容器启动后立即退出时,不要盲目重启。本文详解如何通过 docker logs 查看标准输出错误,利用 docker inspect 检查挂载与网络配置,并修正入口点脚本权限问题,提供一套高效的因果排查流程。

    安卓手机投屏到电脑win10怎么设置教程
    安卓手机投屏到电脑win10怎么设置教程

    详解如何利用Windows 10自带功能将安卓手机画面投射至电脑屏幕,涵盖开启步骤、连接技巧及延迟分析,适合临时演示与多屏协作场景。

    移动硬盘解除加密怎么操作?详细步骤教程
    移动硬盘解除加密怎么操作?详细步骤教程

    详细介绍如何在Windows系统中为移动硬盘解除BitLocker加密,包括解锁驱动器、关闭加密功能及监控解密进度的完整操作流程,帮助用户安全移除数据保护。

    android下载文件夹在哪里打开及查找方法
    android下载文件夹在哪里打开及查找方法

    想知道Android手机的下载文件夹在哪里?本文提供多种简单方法,教你如何通过系统文件管理器、第三方应用或电脑连接,快速定位并打开Download文件夹,轻松管理下载的文件。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    macOS软件
    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    Mac软件 更多
    Blender
    Blender
    Windows、macOS 和 Linux

    Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

    灵活计算器
    灵活计算器
    macOS/iOS/Android

    灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

    赤友清理大师
    赤友清理大师
    macOS

    赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

    WINDOWS 更多
    Blender
    Blender
    Windows、macOS 和 Linux

    Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

    Windows 10
    Windows 10
    Windows

    Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

    极度公式
    极度公式
    Windows/macOS/Linux

    极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。