Android中如何使用GPS


Android中如何使用GPS获取位置信息?一个小Demo如下

GPS简介

Gobal Positioning System,全球定位系统,是美国在20世纪70年代研制的一种以人造地球卫星为基础的高精度无线电导航的定位系统,它在全球任何地方以及近地空间都能够提供准确的地理位置、车行速度及精确的时间信息;它是具有在海、陆、空进行全方位实时三维导航与定位功能的新一代卫星导航与定位系统。

中国用的定位系统是北斗卫星导航系统Beidou Navigation Satellite System,简称BDS,BDS、GPS、俄罗斯的GLONASS、欧盟的GALILEO是联合国卫星导航委员会已经认定的供应商。

手机的定位功能应用广泛,本章来学习GPS的应用开发。

GPS的常用API

GPS系统有三部分组成,卫星空间部分、地面监控部分和用户设备部分。

对于Android机来说,是用户设备部分,是GPS定位系统的接收机,也就是说GPS定位需要有硬件支持GPS功能。对于Android开发人员来说,通过LocationManager、LocationProvider、Location这三个API的一些方法就能开发出GPS应用。

程序的LocationManger对象不能直接创建,而是要通过Context.getSystemService方法获取

LocationManager locationManager= (LocationManager) getSystemService(Context.LOCATION_SERVICE);
List<String> allProviders = locationManager.getAllProviders();

通过询问chatGPT,整理出了这样的一个表格,LocationManger的方法以及作用如下:

方法名

返回值

作用

getLastKnownLocation(String provider)

Location

获取指定 provider 的最近一次位置信息

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

void

注册位置监听器,以获取 provider 的位置更新。参数 minTime 和 minDistance 分别表示位置更新的最小时间间隔和最小距离间隔

removeUpdates(LocationListener listener)

void

取消位置监听器的注册

isProviderEnabled(String provider)

boolean

判断指定 provider 是否可用

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

void

注册一个“地理围栏”,当设备进入指定半径的圆形区域时触发 intent

removeProximityAlert(PendingIntent intent)

void

取消“地理围栏”的注册

使用 LocationManager 时需要申请适当的权限,比如 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 权限。

还有一个API是LocationProvider,他不是Android中的类,而是 Android 系统中的一个抽象类,定义了位置提供者的标准接口,它的实现类用于提供位置信息。LocationProvider 的实现类可以通过系统服务 LocationManager 来获取。当应用程序请求获取位置信息时,LocationManager 会选择合适的位置提供者来获取位置信息,根据不同的需求选择不同的位置提供者。

方法名

返回值

作用

getName()

String

获取位置提供者(locationProvider)的名称

getAccuracy()

int

获取该位置提供者的精度

getPowerRequirement()

int

获取该位置提供者的电量消耗

hasMonetaryCost()

boolean

判断该位置提供者是否需要支付费用

requiresCell()

boolean

判断该位置提供者是否需要使用移动网络

requiresNetwork()

boolean

判断该位置提供者是否需要使用数据网络

requiresSatellite()

boolean

判断该位置提供者是否需要使用卫星

supportsAltitude()

boolean

判断该位置提供者是否支持海拔信息

supportsBearing()

boolean

判断该位置提供者是否支持方向信息

supportsSpeed()

boolean

判断该位置提供者是否支持速度信息

还有一个API是Location,Location 是 Android 中用于表示位置信息的类,它包含了经度、纬度、海拔、速度、方向等位置信息。Location 对象是由 LocationProvider 提供的,LocationManager 负责获取 LocationProvider 提供的位置信息,并将其封装成 Location 对象,然后提供给应用程序使用。方法如下:

方法名

返回值

作用

getLatitude()

double

获取该位置的纬度

getLongitude()

double

获取该位置的经度

getAltitude()

double

获取该位置的海拔

getAccuracy()

float

获取该位置的精度

getBearing()

float

获取该位置的方向

getSpeed()

float

获取该位置的速度

getTime()

long

获取该位置信息的时间戳

hasAccuracy()

boolean

判断该位置信息是否包含精度信息

hasAltitude()

boolean

判断该位置信息是否包含海拔信息

hasBearing()

boolean

判断该位置信息是否包含方向信息

hasSpeed()

boolean

判断该位置信息是否包含速度信息

需要注意的是,获取 Location 对象时可能会出现空值,因此在使用 Location 对象前需要先进行非空判断。另外,获取位置信息需要申请适当的权限,比如 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 权限。

上面三个API就是Android GPS定位支持的三个核心API。使用步骤如下:

1 获取系统的LocationManger对象。

2 使用LocationManger,通过指定的locationProvider来获取定位信息,定位信息由Location表示。

3 从Location对象中获取定位信息。

locationProvider

写一个简单的demo来获取当前系统所有的locationProvider

public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";private ListView listView;private LocationManager locationManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);listView = findViewById(R.id.list);locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);//获取所有的locationProvider名称List<String> allProviders = locationManager.getAllProviders();ArrayAdapter adapter=new ArrayAdapter(this, android.R.layout.simple_list_item_1,allProviders);listView.setAdapter(adapter);}
}

在真机上运行可以看到该系统上有如下四个LocationProvider

移动端通常通过WIFI、GPS、基站这三种方式来定位设备。

以下这四种provider分别来介绍一下

    public static final String NETWORK_PROVIDER = "network";public static final String GPS_PROVIDER = "gps";public static final String PASSIVE_PROVIDER = "passive";public static final String FUSED_PROVIDER = "fused";

NETWORK_PROVIDER:通过移动网络的基站或者 Wi-Fi 来获取地理位置;优点:只要有网络,就可以快速定位,室内室外都可;缺点:精确度不高;

GPS_PROVIDER:通过 GPS 来获取地理位置的经纬度信息;优点:获取地理位置信息精确度高;缺点:只能在户外使用,获取经纬度信息耗时,耗电;

PASSIVE_PROVIDER:被动接收更新地理位置信息,而不用自己请求地理位置信息。

PASSIVE_PROVIDER 返回的位置是通过其他 providers 产生的,可以查询 getProvider() 方法决定位置更新的由来,需要 ACCESS_FINE_LOCATION 权限,但是如果未启用 GPS,则此 provider 可能只返回粗略位置匹配;

FUSED_PROVIDER:已经被废弃了

通过名称获取指定的locationProvider

LocationProvider provider = locationManager.getProvider(LocationManager.GPS_PROVIDER);

使用GPS获取位置信息

代码如下:

public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";private LocationManager locationManager;private TextView showInfo;@RequiresApi(api = Build.VERSION_CODES.M)@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);showInfo = findViewById(R.id.show_location);requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},0x123);}private void updateView(Location location) {if (location != null) {Log.d(TAG, "updateView: 222");String res = "实时位置:\n" +"经度:" + location.getLongitude() +"\n纬度:" + location.getLatitude() +"\n高度:" + location.getAltitude() +"\n速度:" + location.getSpeed()+ "\n方向:" + location.getBearing();showInfo.setText(res);} else {Log.d(TAG, "updateView: 111");showInfo.setText("");}}@SuppressLint("MissingPermission")@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == 0x123 && grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {//创建locationManger对象locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);//获取最新的定位信息Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);updateView(lastKnownLocation);//每隔三秒获取一次GPS信息locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 8f, new LocationListener() {@Overridepublic void onLocationChanged(@NonNull Location location) {updateView(location);}});}}
}

这里代码也很简单,我布局文件只写了一个textView来展示经纬度信息,首先在onCreate方法里动态申请权限。在Android6.0以上不仅仅要在声明文件里静态注册,还有动态申请,否则会出现安全异常。然后就是一个更新UI的方法,通过传入的location获取经纬度高度等信息。选择完获取权限后,会执行onRequestPermissionsResult回调函数,然后就是获取定位信息更新UI。

最后需要在声明文件里静态注册权限。

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

我获取到的是北京市内某地区的经纬度,把该程序和地图功能结合,就能反映出该经纬度在地图上的具体位置,即可开发出GPS导航系统。

室内WIFI定位

室内WIFI定位主要根据WIFI路由器所在的位置进行定位,主要应用于室内较小的空间的精准定位。

Android 9 添加了WiFi 室内定义功能(RTT),以下内容来自 developer.android.com

Android 9 添加了对 IEEE 802.11mc Wi-Fi 协议(也称为 Wi-Fi Round-Trip-Time (RTT))的平台支持,从而让您的应用可以利用室内定位功能。
在运行 Android 9 且具有硬件支持的设备上,应用可以使用 RTT API 来测量与附近支持 RTT 的 Wi-Fi 接入点 (AP) 的距离。 设备必须已启用位置服务并开启 Wi-Fi 扫描(在 Settings > Location 下),同时您的应用必须具有 ACCESS_FINE_LOCATION 权限。

设备无需连接到接入点即可使用 RTT。 为了保护隐私,只有手机可以确定与接入点的距离;接入点无此信息。

如果您的设备测量与 3 个或更多接入点的距离,您可以使用一个多点定位算法来预估与这些测量值最相符的设备位置。 结果通常精准至 1 至 2 米。

室内WIFI定位的管理器是WifiRttManager,获取方式如下,由于在Android9后才增加该功能,所以需要先判断。

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {WifiRttManager wifiRttManager= (WifiRttManager) getSystemService(Context.WIFI_RTT_RANGING_SERVICE);
}

获取到wifirttmanger对象后,可以用startRanging开始定位,该方法里有三个参数。

startRanging(@NonNull RangingRequest request, @NonNull Executor executor, @NonNull RangingResultCallback callback)

RangingRequest:该参数代表一个定位请求,该参数管理本次定位是基于哪个WIFI节点进行访问的

Executor:创建一个新的线程来执行WIFI定位,避免阻塞UI线程。

RangingResultCallback:定位成功或失败的时候触发该对象内的特定方法

写一个具体的案例来实现室内WIFI定位,代码如下:

public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";WifiRttManager mWifiRttManager;//定义监听WIFI状态改变的BroadcastReceiverpublic class WIfiChangeReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())) {//开始执行wifi定位startWifiLoc();}}}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//定义一个监听网络状态的改变 WIFI状态改变的intentFilterIntentFilter wifiFilter = new IntentFilter();wifiFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);wifiFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);wifiFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);registerReceiver(new WIfiChangeReceiver(), wifiFilter);}@SuppressLint("MissingPermission")private void startWifiLoc() {//获取wifi管理器WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);//判断是否支持室内wifi定位功能boolean hasRtt = getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);Log.d(TAG, "startWifiLoc: 是否具有室内WIFI定位功能:" + hasRtt);//Android版本大于9才能使用if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {//获取室内WiFi定位管理器mWifiRttManager = (WifiRttManager) getSystemService(Context.WIFI_RTT_RANGING_SERVICE);RangingRequest request = new RangingRequest.Builder().addAccessPoints(wifiManager.getScanResults())//添加WiFi扫描结果.build();//创建RangingRequest对象Log.d(TAG, "startWifiLoc: request:"+request);//开始请求执行室内WIFI定位mWifiRttManager.startRanging(request, Executors.newCachedThreadPool(), new RangingResultCallback() {@Overridepublic void onRangingFailure(int i) {//WIFI定位出错执行的方法Log.d(TAG, "onRangingFailure:错误码是: "+i);}@Overridepublic void onRangingResults(@NonNull List<RangingResult> list) {//室内WiFi定位返回结果时触发for (RangingResult rr : list){Log.d(TAG, "onRangingResults:与 "+rr.getMacAddress()+" WIFI的距离是:"+rr.getDistanceMm());}}});}}}

运行后报错了

 查询了一下原因是我设备硬件不支持WIFIRTT功能。

总结WIFI定位的步骤:

1 获取WifiRttManger对象

2 通过RangingRequest.Builder来创建对象,创建之前应该先添加WiFi扫描得到WiFi访问点的信息

3 调用WifiRttManger对象的startRanging方法

近距离警报

之前学习的API方法中有一个函数:

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

代码:

public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";private LocationManager locationManager;@RequiresApi(api = Build.VERSION_CODES.M)@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 0x123);}@SuppressLint("MissingPermission")@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == 0x123 && grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);//定义靠近点的经纬度信息double lon = 116.00;double lat = 46.00;float radius = 500F; //定义半径500MIntent intent = new Intent(this, ProxAlertReciever.class);//将intent封装成pendingIntentPendingIntent pendingIntent = PendingIntent.getBroadcast(this, -1, intent, 0);//添加临近警告locationManager.addProximityAlert(lat, lon, radius, -1, pendingIntent);}}
}

注册一个广播监听变化:

public class ProxAlertReciever extends BroadcastReceiver {private static final String TAG = "ProxAlertReciever";@Overridepublic void onReceive(Context context, Intent intent) {boolean isEnter= intent.getBooleanExtra(LocationManager.KEY_PROXIMITY_ENTERING,false);if (isEnter){//靠近提示Log.d(TAG, "onReceive: 快靠近了!!");}else {Log.d(TAG, "onReceive: 离开了!!");}}
}

至此 Android中的GPS的就讲完了,想开发出具体的导航系统还要结合地图功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/20662.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【万字长文】深度解析 Transformer 和注意力机制(含完整代码实现)

深度解析 Transformer 和注意力机制 在《图解NLP模型发展&#xff1a;从RNN到Transformer》一文中&#xff0c;我介绍了 NLP 模型的发展演化历程&#xff0c;并用直观图解的方式为大家展现了各技术的架构和不足。有读者反馈图解方式虽然直观&#xff0c;但深度不足。考虑到 Tra…

全球首位 AI 律师出庭,花 100 万美元找“传话筒”!网友:头脑正常的人谁会同意?...

整理 | 郑丽媛 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 在 ChatGPT 的热潮下&#xff0c;近来在国内外科技网站上&#xff0c;各类 AI 话题几乎成为了“热搜常驻户”&#xff0c;其中不乏一些看起来极具噱头的新闻&#xff1a; 本周&#xff0c;AI 公司 Do…

Edge浏览器的美化

用了扩展软件后的Edged的界面为 非常方便 &#xff0c;同时它还可以添加一些你需要用用到的app&#xff0c;无需下载。 它侧栏还有程序员选择&#xff0c;我们在这里可以直接进入CSDN。 废话不多说直接上教程&#xff1a; 1.打开Edge找到扩展选项&#xff0c;点击管理扩展。 …

这才是我想要是游览器——打造最强Microsoft edge+ChatGPT

这也许是你的Microsoft edge界面&#xff1a; 而这时我的edge游览器界面&#xff1a; 对比一下&#xff0c;第一个是默认的游览器界面&#xff0c;第二个是升级后的游览器界面。 是不是感觉第一个比较土呢第二个更高大上一些呢 其实相差巨大的主页&#xff0c;其实只是一个插…

TR外汇黑平台资金盘深度揭秘,谨防上当受骗,迟早会跑路

本人是有着13年外汇经验的外汇人&#xff0c;行业的大小事情&#xff0c;各级的产业链也基本都接触过&#xff0c;算是一个很资深的行业人士了&#xff0c;这么多年可以说是从刀光剑影中走过来&#xff0c;想想也很不容易了。本人vx&#xff1a;yunshao886 本篇所讲内容&#…

玩转 ChatGPT,看这条就够了,Prompt 最全中文合集

Prompt 最全中文合集 玩转 ChatGPT&#xff0c;看这条就够了&#xff01; &#x1f680; 简化流程&#xff1a;ChatGPT Shortcut 提供了快捷指令表&#xff0c;可以快速筛选和搜索适用于不同场景的提示词&#xff0c;帮助用户简化使用流程。 &#x1f4bb; 提高生产力&#…

美国探亲签证面签时一定要用英语吗?

签证问题&#xff1a;美国探亲签证面签时一定要用英语吗&#xff1f; 知识人网&#xff1a;申请美国探亲签证&#xff0c;面签时不会说英语也没有关系的。面签时不一定要说英语&#xff0c;您可以用中文面谈。美国签证官都精通英语和中文&#xff0c;您在面签时可以选择用中文…

中外互免签证协定一览表(普通护照与公务普通护照)

普通护照&#xff1a;由公安部出入境管理机构或者公安部委托的县级以上地方人民政府公安机关出入境管理机构以及中华人民共和国驻外使馆、领馆和外交部委托的其他驻外机构签发&#xff0c;主要颁发给出国定居、探亲、访友、继承财产、留学、就业、旅游等因私事出国的中国公民。…

我与 InsCODE AI 创作助手的一次对话

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 我与INDCODE AI 创作助手的一次对话 &#x1f9ca;摘要&#x1f9ca;前言&#x1f9ca;对话内容&#x1f9ca;结束语 &#x1f9ca;摘要 本文介绍了 CSDN 嵌入式INSCODE AI 创作助手…

我与 INDCODE AI 创作助手的一次对话

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 我与INDCODE AI 创作助手的一次对话 &#x1f9ca;摘要&#x1f9ca;前言&#x1f9ca;对话内容&#x1f9ca;结束语 &#x1f9ca;摘要 本文介绍了 CSDN 嵌入式INSCODE AI 创作助手…

聊聊微服务架构中的用户认证方案!

更多内容关注微信公众号&#xff1a;fullstack888 聊聊微服务中一个重要的话题&#xff1a;如何设计微服务架构下的用户认证方案。今天主要涉及三个方面的内容&#xff1a; 传统的用户认证方案&#xff1b;JWT 与 JJWT&#xff1b;基于网关的统一用户认证。 一、传统的用户认证…

chatgpt赋能python:用Python来炒股——更高效、更智能的投资方式

用Python来炒股——更高效、更智能的投资方式 随着科技的发展&#xff0c;越来越多的投资者开始采用自动化投资方式来管理并优化自己的投资组合&#xff0c;Python作为一种高效、可扩展性强的编程语言&#xff0c;逐渐成为了自动化投资的重要工具。本文将介绍如何利用Python来…

chatgpt赋能python:有人用Python炒股吗?探究Python在炒股领域的应用

有人用Python炒股吗&#xff1f;探究Python在炒股领域的应用 Python作为一种高级编程语言&#xff0c;已经被广泛应用于各个领域&#xff0c;包括自然语言处理、数据分析、人工智能等等。那么在炒股领域&#xff0c;Python是否同样有广泛的应用呢&#xff1f;本文将探究Python…

chatgpt赋能python:Python炒股代码:如何实现自动交易?

Python炒股代码&#xff1a;如何实现自动交易&#xff1f; 股票交易从来都不是一件容易的事情。因此&#xff0c;很多股民也会选择依靠程序化交易&#xff0c;也就是自动交易的方式。而Python正是一种极为适合进行自动交易的编程语言。通过Python编写的程序&#xff0c;不仅可…

html修改修改头像业务,修改头像.html

&#xfeff;修改头像 $axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; }; $axure.utils.getOtherPath function() { return resources/Other.html; }; $axure.utils.getReloadPath function() { return resources/reload.html;…

用户上传头像以及BUG修改

持久层 1、sql语句的规划 上传文件的操作其实是&#xff1a;先将用户上传的文件保存到服务器端的某个位置&#xff0c;然后将保存文件的路径记录在数据库中。当后续需要使用该文件时&#xff0c;从数据库中读出文件的路径&#xff0c;即可实现在线访问该文件。 在持久层处理数…

HTML点击头像修改页面,头像修改页.html

&#xfeff;头像修改页 $axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; }; $axure.utils.getOtherPath function() { return resources/Other.html; }; $axure.utils.getReloadPath function() { return resources/reload.htm…

移动端--修改头像

image/*表示选择所有图片格式 使用第三方插件实现头像裁剪 Cropper.jsCropper.js const cropper new Cropper(image, { viewMode: 1, dragMode: move, aspectRatio: 1, autoCropArea: 1, cropBoxMovable: false, cropBoxResizable: false, background: false, movable: true…

奥特曼格斗进化3全人物存档

奥特曼格斗进化3是奥特曼格斗进化系列的第三部作品&#xff0c;随着游戏的一路走来&#xff0c;游戏的可选角色越来越丰富&#xff0c;画面、技能效果、音效等方面也有了长足的进步&#xff0c;但由于角色解锁起来比较复杂&#xff0c;因此小编为大家带来了奥特曼格斗进化3全人…

python:bs4爬取奥特曼,是不是所有奥特曼都长一样

利用pythonbs4爬取奥特曼粉丝联盟的奥特曼图片&#xff0c;难点把其实也没有&#xff0c;就是爬虫不经常搞&#xff0c;容易忘记一些东西。废话不多说&#xff0c;直接上代码 主要引包 import os from pathlib import Path from bs4 import BeautifulSoup from requests impo…