转自http://www.learningandroid.net/blog/advance/programmable-toggle-gps/

手机应用中最酷的可能就是位置服务相关的了,如何读取GPS信息,在官方文档上有相当详细的说明,后面如果有机会,我也会专门写例子来介绍(教程已完成,请参见:教程:实现Android的不同精度的定位(基于网络和GPS))。但今天,我们先来看下如何以编程的方式来开启或关闭GPS。
官方的API中,android.provider.Settings.Secure类有2个静态方法:
public static final void setLocationProviderEnabled (ContentResolver cr, String provider, boolean enabled)

public static final boolean isLocationProviderEnabled (ContentResolver cr, String provider)
不过遗憾的是,这2个方法都注明了从API Level 8(即Android 2.2)才开始提供,那么在2.2之前又该如何编程实现GPS的开关呢?

山重水复疑无路

首先,我们要知道,Android系统的设置画面中就可以进行GPS的开关,那么它是如何实现的呢?
由于我的机器上的android source是2.3版本的,所以直接启动了一个2.1的模拟器,用adb pull将Settings.apk抓下来,反编译之后,在SecuritySettings类中找到如下代码:
package,com.android.settings.SecuritySettings.java

1
2
3
4
5
6
7
8
      CheckBoxPreference localCheckBoxPreference3 = this.mGps;if (paramPreference == localCheckBoxPreference3){ContentResolver localContentResolver3 = getContentResolver();boolean bool6 = this.mGps.isChecked();Settings.Secure.setLocationProviderEnabled(localContentResolver3, "gps", bool6);continue;}

可以看到2.1系统中已经存在有Settings.Secure.setLocationProviderEnabled方法了,只是该方法没有开放而已,事实上读过Android源码的人都对/*hide*/很反感吧,看得到,摸不到!

既然Setting画面中的用法,我们不能使用,那么再换1种方法,我们去看一下Settings.Secure.setLocationProviderEnabled的写法,然后直接套用。
这次,我们直接去看Android 2.3的源码,找到Setting.java之后,找到相关的方法,代码如下:
core, android.provider.Setting.java

1
2
3
4
5
6
7
8
9
10
11
12
        public static final void setLocationProviderEnabled(ContentResolver cr,String provider, boolean enabled) {// to ensure thread safety, we write the provider name with a '+' or '-'// and let the SettingsProvider handle it rather than reading and modifying// the list of enabled providers.if (enabled) {provider = "+" + provider;} else {provider = "-" + provider;}putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider);}

原来这个方法只是1个包装,事实上调用的还是Settings.Secure中的putString方法,我们直接借用过来:
在自己的onClick事件中写上
Settings.Secure.putString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, “network,gps”);
然后执行,WOW,发生了什么,需要android.permission.WRITE_SETTINGS权限?在Manifest文件中加上,再运行,还是出错,不过这次需要的是android.permission.WRITE_SECURE_SETTINGS,再次加上。
满怀希望的再次运行,结果还是一样的问题:
java.lang.SecurityException: Permission denial: writing to secure settings requires android.permission.WRITE_SECURE_SETTINGS
看来,Google封死了直接调用Settings的路了,事实上我又试着使用反射来直接调用setLocationProviderEnabled方法,结果也是一样的告诉我需要权限。

柳暗花明又一村

难道没有别的办法了吗?那些2.1中可以运行的App Widget是如何做到的呢?
再次检视2.1的Settings.apk中的代码,发现有1个widget包,里面有1个类叫SettingsAppWidgetProvider,这就是用来提供App Widget的类,继续研究这里的代码,发现构造RemoteView的代码中用到如下方法:

1
2
3
4
5
6
7
8
9
  private static PendingIntent getLaunchPendingIntent(Context paramContext, int paramInt1, int paramInt2){Intent localIntent1 = new Intent();Intent localIntent2 = localIntent1.setClass(paramContext, SettingsAppWidgetProvider.class);Intent localIntent3 = localIntent1.addCategory("android.intent.category.ALTERNATIVE");Uri localUri = Uri.parse("custom:" + paramInt2);Intent localIntent4 = localIntent1.setData(localUri);return PendingIntent.getBroadcast(paramContext, 0, localIntent1, 0);}

由于这是反编译的结果,略微有点混乱,但还是可以看出思路,目的是通过PendingIntent来扔出1个Intent,接受者是SettingsAppWidgetProvider.class,接受的参数有2个,1个是Category:SettingsAppWidgetProvider.class(正是这个类自身),另1个是Data:Uri.parse(“custom:” + paramInt2),这个paramInt2是Widget中的图标按钮的序号。所有的序号在类的首部都有定义:

1
2
3
4
5
  private static final int BUTTON_BLUETOOTH = 4;private static final int BUTTON_BRIGHTNESS = 1;private static final int BUTTON_GPS = 3;private static final int BUTTON_SYNC = 2;private static final int BUTTON_WIFI = 0;

那么我们只要送出custom:3的Uri给SettingsAppWidgetProvider.class,就应该可以由SettingsAppWidgetProvider类来帮我们调用Settings.Secure.setLocationProviderEnabled方法了。
说到做到,在Activity中添加如下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
    private void toggleGPS() {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(this, 0, gpsIntent, 0).send();}catch (CanceledException e) {e.printStackTrace();}}

这个方法是1个纯开关,如果当前是开启的,那么就会关闭它,反之亦然。

检查GPS开关状态

那么,如何查看当前的GPS开关状态呢?可以用上面提到的反射方式调用isLocationProviderEnabled,代码片断如下:

1
2
3
4
5
    secureClass = cl.loadClass("android.provider.Settings$Secure");isMethod = secureClass.getMethod("isLocationProviderEnabled",ContentResolver.class, String.class);Boolean ret = (Boolean) isMethod.invoke(secureClass, this.getContentResolver(), "gps");

也可以直接用下面的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    private void isGPSEnable() {/* 用Setting.System来读取也可以,只是这是更旧的用法String str = Settings.System.getString(getContentResolver(),Settings.Secure.LOCATION_PROVIDERS_ALLOWED);*/String str = Settings.Secure.getString(getContentResolver(),Settings.Secure.LOCATION_PROVIDERS_ALLOWED);Log.v("GPS", str);if (str != null) {return str.contains("gps");}else{return false;}}

这2种方法的原理都是一样的,方法2其实也就是isLocationProviderEnabled实际调用的代码,只是Google未对读取操作进行权限限制。

总结

如果目标手机是运行Android 2.2的话,那么最好还是使用2.2开放的Settings.Secure类中的2个方法来操作。但如果目标手机运行的版本是2.1或以下的话,那么就只能使用变通的方法来实现了。这1方法在Android官方的Wiki上已经有人提出了,详情请见:Issue 7890。但可能是2.1版本已经古旧不再维护的原因,官方并未进行任何的Fix。

转载于:https://www.cnblogs.com/huanglong/archive/2011/07/26/2117344.html

如何编程实现开启或关闭GPS(转)相关推荐

  1. Android中如何通过程序打开或关闭GPS

    手机应用中最酷的可能就是位置服务相关的了,如何读取GPS信息,在官方文档上有相当详细的说明,后面如果有机会,我也会专门写例子来介绍(教程已完成,请参见:教程:实现Android的不同精度的定位(基于网 ...

  2. Visual Studio Code 编程时如何开启或关闭错误提示

    Visual Studio Code 编程时如何开启或关闭错误提示 1.进入文件->首选项->设置 2.在搜索框里输入 C_Cpp.errorSquiggles,将错误提醒设置为打开状态或 ...

  3. php禁用错误提示,php开启与关闭错误提示详解

    在php中开启与关闭错误提示的方法有几种一种可以直接在程序中使用相关函数来开户,另一种我们可以使用php.ini中配置参数来控制,下面小编来给各位同学介绍一下. windows系统开关php错误提示 ...

  4. android 10.0关闭gps定位功能

    1.概述 在10.0的产品定制化开发中,有些是不需要gps定位功能的,所以就需要屏蔽掉gps上报定位数据的功能,而在framework层中是通过/frameworks/base/location/ja ...

  5. 实现开启和关闭Android移动网络(做AppWidget开发的收获)

    之前在做Android AppWidget这方面的开发,本人菜鸟一个,刚接触android不久.所以在开发的过程中不免遇到诸多难处,不过在解决问题中收获知识是一种非常刺激的体验.接下来是本人在开发开关 ...

  6. CentOS7在防火墙开启与关闭以及端口操作

    CentOS7在安装软件包或类库的时候,常常会因为防火墙的拦截和端口未开放导致连接失败,数据调用或远程失败等,所以在使用CentOS时需学会对防火墙和端口操作... 工具/原料 已安装CentOS7的 ...

  7. HTTP的KeepAlive是开启还是关闭?

    转自:http://blog.csdn.net/gaogaoshan/article/details/38580013 1.KeepAlive的概念与优势 HTTP的KeepAlive就是浏览器和服务 ...

  8. Ubuntu中设置防火墙的开启与关闭

    今天在做 SVN 检出与提交的时候,一直失败,后来查找了多方面原因,是防火墙的问题.我用的 Ubuntu 是纯命令行界面的,所以需要通过命令进行开启与关闭. 这里介绍一下 Ubuntu 关于防火墙的设 ...

  9. CentOS开启与关闭防火墙

    CentOS Linux开启和关闭防火墙命令有两种,一种是临时的,重启即复原:另外一种是永久性的,重启不会复原. 1) 临时生效,重启后复原开启: service iptables start关闭: ...

最新文章

  1. 为什么使用单页应用_为什么我讨厌您的单页应用
  2. leetcode_Jump Game II
  3. 【收藏】GeoMesa整体架构模块介绍、创建Schema并导入数据
  4. Windows创建类似.project只有后缀名的文件的方法
  5. 解决:com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused:
  6. RobotFramework自动化测试框架的基础关键字(五)
  7. android+噪音测试,关于噪音测试App的选择与使用
  8. dajngo电商数据库设计图,通用版本
  9. JuiceFS 你应该知道的一些事
  10. Unable to install breakpoint in XXX due to missing line number attributes的解决
  11. Kubernetes部署项目报错ImagePullBackOff日志提示rpc error: code..http: server gave HTTP response to HTTPS client
  12. 如何全局使用php composer,php – 如何配置要全局安装的composer包?
  13. PPT幻灯片放映不显示备注,只让备注显示在自己屏幕上!
  14. 同样是写博客,为什么我男朋友的粉丝那么多?!
  15. echarts制作中国地图
  16. Markdown 全文检索
  17. Android 天气APP(三十六)运行到本地AS、更新项目版本依赖、去掉ButterKnife
  18. 2021-09-08 网安实验-编码解码-九宫格键盘编码
  19. 教师使用计算机的注意事项,李磊老师:计算机专业考研报考注意事项
  20. 【日常分享】规格化成绩如何计算

热门文章

  1. python基础教程书籍推荐-入门python有什么好的书籍推荐?
  2. python映射类型-python映射类型的相关介绍
  3. 21天学通python pdf-21天学通Python PDF百度网盘资源下载
  4. 学python需要什么文化基础-中国大学MOOC的APP2020Python编程基础答案
  5. 自学python有哪些网站-python有哪些学习网站
  6. python爬百度翻译-Python爬取百度翻译(利用json提取数据)
  7. 学好python需要多久-python入门要学多久
  8. python在当前目录创建txt文件-python-在目录中创建多个文本文件的字数字...
  9. python少儿编程 在线课程-石家庄Python人工智能编程
  10. php和python对比-python与java、php、go的优势对比