转载请标明出处:http://www.cnblogs.com/tangZH/p/8969898.html 

更多文章:http://77blogs.com/?p=253

前言:

有时候我们仅仅是想要获取设备所在的经纬度,那么直接调用Android相关的api就可以了,不需要去接入高德地图或者谷歌地图等等。

一、获取定位服务

  1.  
  1. private LocationManager locationManager;
  1. locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);

二、获取所有可用的位置提供器

  1. //获取所有可用的位置提供器
  2. List<String> providers = locationManager.getProviders(true);

三、判断可用的位置提供器类型,是网络定位,还是GPS定位,若是都没有,那么就跳转至设置界面,提示打开网络和GPS定位服务

这里说一下两种定位的区别:

通过GPS定位,较精确,也比较耗电,而网络定位精度不高,省电。

  1. String locationProvider = null;
  2. if (providers.contains(LocationManager.GPS_PROVIDER)) {
  3. //如果是GPS
  4. locationProvider = LocationManager.GPS_PROVIDER;
  5. } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
  6. //如果是Network
  7. locationProvider = LocationManager.NETWORK_PROVIDER;
  8. } else {
  9. Intent i = new Intent();
  10. i.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
  11. mContext.startActivity(i);
  12. return null;
  13. }

四、获取Location

  1. //获取Location
  2. Location location = locationManager.getLastKnownLocation(locationProvider);

五、监视地理位置变化

这里设置3秒监听一次

  1. //监视地理位置变化
  2. locationManager.requestLocationUpdates(locationProvider, 3000, 1, locationListener);

六、实现地理位置变化接口

  1. public LocationListener locationListener = new LocationListener() {
  2.  
  3. // Provider的状态在可用、暂时不可用和无服务三个状态直接切换时触发此函数
  4. @Override
  5. public void onStatusChanged(String provider, int status, Bundle extras) {
  6.  
  7. }
  8.  
  9. // Provider被enable时触发此函数,比如GPS被打开
  10. @Override
  11. public void onProviderEnabled(String provider) {
  12.  
  13. }
  14.  
  15. // Provider被disable时触发此函数,比如GPS被关闭
  16. @Override
  17. public void onProviderDisabled(String provider) {
  18.  
  19. }
  20.  
  21. //当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
  22. @Override
  23. public void onLocationChanged(Location location) {
  24. }
  25. };

注意:

要在文件清单里面写上

  1. <uses-permission android:name="android.permission.INTERNET"/>
  2. <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  3. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

我为此写了个工具类。

  1. package com.example.chatting.chatting.utils;
  2.  
  3. import android.content.Context;
  4. import android.content.Intent;
  5. import android.location.Location;
  6. import android.location.LocationListener;
  7. import android.location.LocationManager;
  8. import android.os.Bundle;
  9. import android.provider.Settings;
  10.  
  11. import java.util.List;
  12.  
  13. /**
  14. * Created by Administrator on 2018/4/17.
  15. * 获取用户的地理位置
  16. */
  17. public class GPSUtils {
  18.  
  19. private static GPSUtils instance;
  20. private Context mContext;
  21. private LocationManager locationManager;
  22.  
  23. private GPSUtils(Context context) {
  24. this.mContext = context;
  25. }
  26.  
  27. public static GPSUtils getInstance(Context context) {
  28. if (instance == null) {
  29. instance = new GPSUtils(context);
  30. }
  31. return instance;
  32. }
  33.  
  34. /**
  35. * 获取经纬度
  36. *
  37. * @return
  38. */
  39. public String getLngAndLat(OnLocationResultListener onLocationResultListener) {
  40. double latitude = 0.0;
  41. double longitude = 0.0;
  42.  
  43. mOnLocationListener = onLocationResultListener;
  44.  
  45. String locationProvider = null;
  46. locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
  47. //获取所有可用的位置提供器
  48. List<String> providers = locationManager.getProviders(true);
  49.  
  50. if (providers.contains(LocationManager.GPS_PROVIDER)) {
  51. //如果是GPS
  52. locationProvider = LocationManager.GPS_PROVIDER;
  53. } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
  54. //如果是Network
  55. locationProvider = LocationManager.NETWORK_PROVIDER;
  56. } else {
  57. Intent i = new Intent();
  58. i.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
  59. mContext.startActivity(i);
  60. return null;
  61. }
  62.  
  63. //获取Location
  64. Location location = locationManager.getLastKnownLocation(locationProvider);
  65. if (location != null) {
  66. //不为空,显示地理位置经纬度
  67. if (mOnLocationListener != null) {
  68. mOnLocationListener.onLocationResult(location);
  69. }
  70.  
  71. }
  72. //监视地理位置变化
  73. locationManager.requestLocationUpdates(locationProvider, , , locationListener);
  74. return null;
  75. }
  76.  
  77. public LocationListener locationListener = new LocationListener() {
  78.  
  79. // Provider的状态在可用、暂时不可用和无服务三个状态直接切换时触发此函数
  80. @Override
  81. public void onStatusChanged(String provider, int status, Bundle extras) {
  82.  
  83. }
  84.  
  85. // Provider被enable时触发此函数,比如GPS被打开
  86. @Override
  87. public void onProviderEnabled(String provider) {
  88.  
  89. }
  90.  
  91. // Provider被disable时触发此函数,比如GPS被关闭
  92. @Override
  93. public void onProviderDisabled(String provider) {
  94.  
  95. }
  96.  
  97. //当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
  98. @Override
  99. public void onLocationChanged(Location location) {
  100. if (mOnLocationListener != null) {
  101. mOnLocationListener.OnLocationChange(location);
  102. }
  103. }
  104. };
  105.  
  106. public void removeListener() {
  107. locationManager.removeUpdates(locationListener);
  108. }
  109.  
  110. private OnLocationResultListener mOnLocationListener;
  111.  
  112. public interface OnLocationResultListener {
  113. void onLocationResult(Location location);
  114.  
  115. void OnLocationChange(Location location);
  116. }
  117. }

这里边涉及到了另一个问题,获取权限

对于6.0以下的权限及在安装的时候,根据权限声明产生一个权限列表,用户只有在同意之后才能完成app的安装,造成了我们想要使用某个app,就要默默忍受其一些不必要的权限(比如是个app都要访问通讯录、短信等)。而在6.0以后,我们可以直接安装,当app需要我们授予不恰当的权限的时候,我们可以予以拒绝。当然你也可以在设置界面对每个app的权限进行查看,以及对单个权限进行授权或者解除授权。

新的权限机制更好的保护了用户的隐私,Google将权限分为两类,一类是Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、访问网络等;另一类是Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、访问通讯录等。

对于Dangerous Permission,我们需要动态获取权限,那么我们怎么动态定位权限呢?

在activity中(其实我们可以把权限的获取写在一个BaseActivity中)我们可以这么做:

1、判断版本,如果6.0以下,那么便不需要获取权限。

  1. /**
  2. * 是否应该检查权限
  3. * @return
  4. */
  5. public boolean showCheckPermissions() {
  6. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  7. return true;
  8. } else {
  9. return false;
  10. }
  11. }

2、若是6.0以及以上的话,那么便去判断是否已经授权,若是没有授权,那么便会去申请授权。若是已经授权,那么便直接执行我们的操作。

(判断之后若是没有授权,会弹出系统对话框询问是否同意授权,该对话框不可定制。)

  1. //获取权限(如果没有开启权限,会弹出对话框,询问是否开启权限)
  2. if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
  3. || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
  4. //请求权限
  5. ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
  6. Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_CODE);
  7. } else {
  8.  
  9. }

3、授权回调。询问是否同意授权的时候,系统会弹出对话框,我们选择之后,会进行回调。在回调里面进行判断。

  1. @Override
  2. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  3. switch (requestCode) {
  4. case LOCATION_CODE: {
  5. if (grantResults.length > 0
  6. && grantResults[0] == PackageManager.PERMISSION_GRANTED
  7. && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
  8. // 权限被用户同意。
  9. // 执形我们想要的操作
  10. } else {
  11.  
  12. }
  13. }
  14. }
  15. }

若是同意了,那么便可以直接执形我们的操作,若是不同意,那么下次依旧会弹出询问的对话框。不过这个对话框与之前比起来多了一个选项,那就是“不再提醒”(第一次询问没有这个选项)。这就难办了,若是点击了不再提醒,那么以后就不会再弹出对话框了,唉,那我们怎么判断呢?

Google给我们提供了一个方法:

  1. ActivityCompat.shouldShowRequestPermissionRationale

该方法主要是为了给用户提供解释。

这个方法,在没弄明白之前,也是挺烦人。弄明白之后就好办了,那么,我们需要弄明白它的返回值。

(1)、当用户第一次被询问是否授权的时候,该方法返回值为false

(2)、若是用户上一次拒绝授权,但是没有点击“不再提醒“”的时候,这一次返回true。(我们可以根据这个判断,在这一次给用户一个解释,解释为什么该app需要该权限)

(3)、当用户上一次拒绝授权,并且点击了“不再提醒”的时候,那么返回false。

(4)、当用户在设置界面手动关闭了该APP的权限,那么也返回false。

那么,就出现了一个问题,这么多种情况都返回false,那么我们要怎么判断是哪一种情况呢?

比如第一与第三种情况。

若是我们在进行权限判断之前调用这个方法:

  1.  
  1. if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)
  2. || !ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
    .....
  3. }
  1. if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
  2. || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)

若是返回true,说明是第二种情况,需要给用户一个解释(我们可以给出一个对话框,点击确定后再执形检测权限的操作,即下面的的操作)。

若是返回false,那么到底是第一还是第三种情况。我们无法判断。这里我给出一种方法:在授权回调里面去检测,如下。

else可以说明已经拒绝授权。

然后调用shouldShowRequestPermissionRationale方法,若是返回false,说明

1、点击了“不再提醒”。

2、该app本身没有权限,被关闭。

那么我们就可以提醒用户去设置界面手动开启权限。

  1. @Override
  2. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  3. switch (requestCode) {
  4. case LOCATION_CODE: {
  5. if (grantResults.length > 0
  6. && grantResults[0] == PackageManager.PERMISSION_GRANTED
  7. && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
  8. // 权限被用户同意。
  9. // 执形我们想要的操作
  10. } else {
  11. // 权限被用户拒绝了。
  12. //若是点击了拒绝和不再提醒
  13. //关于shouldShowRequestPermissionRationale
  14. // 1、当用户第一次被询问是否同意授权的时候,返回false
  15. // 2、当之前用户被询问是否授权,点击了false,并且点击了不在询问(第一次询问不会出现“不再询问”的选项),
  16. // 之后便会返回false
  17. // 3、当用户被关闭了app的权限,该app不允许授权的时候,返回false
  18. // 4、当用户上一次不同意授权,没有点击“不再询问”的时候,下一次返回true
  19. if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)
  20. || !ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
  21. //提示用户前往设置界面自己打开权限
  22. Toast.makeText(this, "请前往设置界面打开权限", Toast.LENGTH_SHORT).show();
  23. return;
  24. }
  25.  
  26. }
  27. }
  28. }
  29. }

Android获取定位权限,获取设备所在的经纬度的更多相关文章

  1. android开发,权限获取

    转:http://blog.csdn.net/yawinstake/article/details/6748897 访问登记属性 android.permission.ACCESS_CHECKIN_P ...

  2. android基站定位程序获取地理位置

    目录 一.设置界面 二.为按钮绑定事件 三.获取基站信息 四.获取经纬度 五.获取物理位置 六.显示结果 七.运行程序 八.总结 九.程序代码 正文 在Android操作系统下,基站定位其实很简单,先 ...

  3. android开发的权限获取 (转载的)

    访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permiss ...

  4. Android M 动态权限获取

    新的权限获取方式除了要求像之前版本号一样在AndroidManifest文件里静态申请之外,应用还需依据须要请求权限,方式採用向用户显示一个请求权限的对话框. 这些被动态申请的权限能够在系统设置中被手 ...

  5. 标准基座获取定位可以获取address城市,自定义基座获取不到address

    正常的返回应该 { "type": "WGS84", "altitude": 0, "latitude": 31.830 ...

  6. Android应用请求获取Root权限

    应用获取Root权限的原理:让应用的代码执行目录获取最高权限.在Linux中通过chmod 777 [代码执行目录] /** * 应用程序运行命令获取 Root权限,设备必须已破解(获得ROOT权限) ...

  7. Android -- 程序判断手机ROOT状态,获取ROOT权限

    判断手机是否具有ROOT权限                                                            /** * 判断手机是否ROOT */ public ...

  8. android6.0获取通讯录权限

    android6.0中,获取通讯录的权限是    <uses-permission android:name="android.permission.GET_ACCOUNTS" ...

  9. 软件申请获取root权限

      申请root的工具类 //获取root权限 RootManager manager=new RootManager(); manager.upgradeRootPermission(getPack ...

随机推荐

  1. 主流数据库连接池性能比较 hikari druid c3p0 dbcp jdbc

    背景 对现有的数据库连接池做调研对比,综合性能,可靠性,稳定性,扩展性等因素选出推荐出最优的数据库连接池 . NOTE: 本文所有测试均是MySQL库 测试结论 1:性能方面 hikariCP> ...

  2. [Swift]LeetCode225. 用队列实现栈 | Implement Stack using Queues

    Implement the following operations of a stack using queues. push(x) -- Push element x onto stack. po ...

  3. [Swift]LeetCode1012. 至少有 1 位重复的数字 | Numbers With 1 Repeated Digit

    Given a positive integer N, return the number of positive integers less than or equal to N that have ...

  4. Java中异常的处理以及自定义异常,抛出异常到方法调用栈底层

    package com.gezhi; /** * 创建一个自定义异常SpendMoneyException类 *  * @author square 凉 * */@SuppressWarnings(& ...

  5. .NET Core实战项目之CMS 第十章 设计篇-系统开发框架设计

    这两天比较忙,周末也在加班,所以更新的就慢了一点,不过没关系,今天我们就进行千呼万唤的系统开发框架的设计.不知道上篇关于架构设计的文章大家有没有阅读,如果阅读后相信一定对架构设计有了更近一部的理解,如 ...

  6. 获取Ip所在城市名与详细

    //获取ip和地理信息 string url = "http://pv.sohu.com/cityjson"; WebRequest wRequest = WebRequest.C ...

  7. ArrayList循环遍历并删除元素的常见陷阱

    在工作和学习中,经常碰到删除ArrayList里面的某个元素,看似一个很简单的问题,却很容易出bug.不妨把这个问题当做一道面试题目,我想一定能难道不少的人.今天就给大家说一下在ArrayList循环 ...

  8. 【Python3爬虫】第一个Scrapy项目

    Python版本:3.5    IDE:Pycharm 今天跟着网上的教程做了第一个Scrapy项目,遇到了很多问题,花了很多时间终于解决了== 一.Scrapy终端(scrapy shell) Sc ...

  9. 配置最新版LAMP环境

    本篇文章讲解的是在centos7.3下配置 Apache2.4 + MySQL5.7 + PHP7.1.8 (如果是Nginx请跳过Apache流程继续往下看,所有流程本人已临床验证无数遍,绝无问题) ...

  10. C# 反射,通过类名、方法名调用方法

    在 C# 代码中,有些时候只知道方法的名字(string),需要调用该方法,那么就需要用到 C# 的反射机制.下面是一个简单的 demo. using System; using System.Ref ...