`
fuerbosi
  • 浏览: 465148 次
文章分类
社区版块
存档分类
最新评论

Android中如何通过程序打开或关闭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

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

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的代码中用到如下方法:

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中的图标按钮的序号。所有的序号在类的首部都有定义:

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中添加如下方法:
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开关状态

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

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

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。



转自:http://www.itivy.com/android/archive/2011/6/17/android-open-or-close-gps.html

分享到:
评论

相关推荐

    Android程序设计基础

    第3章探讨用户界面,也就是大多数Android程序中最重要的部分。  致谢  我要感谢为本书成功出版做出贡献的许多人,包括审稿人Anthony Stevens、Gabor Paller、Fred Burke、Dianne Hackborn和Laurent Pontier,...

    GPSDetector:适用于Android的PhoneGap插件-检测GPS是打开还是关闭

    GPS探测器特征PhoneGap插件用于检测GPS是否在设备上启用或禁用,并能够打开“位置设置”并手动激活它们与Cordova 2.2.0到3.1.0兼容(未测试旧版本和较新版本) 在Android 4.4 KitKat(Nexus 5)上经过测试(并且可以...

    《Google Android SDK开发范例大全(第3版)》.pdf

    8.14 远程下载安装android程序 560 8.15 手机下载看3gp影片 566 8.16 访问网站login api 573 8.17 地震速报 578 8.18 通过web api动态更改手机spinner控件 587 8.19 网络语音搜索 590 8.20 网络...

    Google Android SDK开发范例大全(第3版) 1/5

    8.14 远程下载安装Android程序 8.15 手机下载看3gp影片 8.16 访问网站Login API 8.17 地震速报 8.18 通过Web API动态更改手机Spinner控件 8.19 网络语音搜索 8.20 网络下载过程中显示加载中 8.21 快照WebView加载的...

    新版Android开发教程.rar

    Android 是一个专门针对移动设备的软件集,它包括一个操作系统,中间件和一些重要的应用程序。 Beta 版 的 Android SDK 提供了在 Android 平台上使用 JaVa 语言进行 Android 应用开发必须的工具和 API 接口。 特性 ...

    Google Android SDK开发范例大全(第3版) 4/5

    8.14 远程下载安装Android程序 8.15 手机下载看3gp影片 8.16 访问网站Login API 8.17 地震速报 8.18 通过Web API动态更改手机Spinner控件 8.19 网络语音搜索 8.20 网络下载过程中显示加载中 8.21 快照WebView加载的...

    Google Android SDK开发范例大全(第3版) 3/5

    8.14 远程下载安装Android程序 8.15 手机下载看3gp影片 8.16 访问网站Login API 8.17 地震速报 8.18 通过Web API动态更改手机Spinner控件 8.19 网络语音搜索 8.20 网络下载过程中显示加载中 8.21 快照WebView加载的...

    Google Android SDK开发范例大全(第3版) 5/5

    8.14 远程下载安装Android程序 8.15 手机下载看3gp影片 8.16 访问网站Login API 8.17 地震速报 8.18 通过Web API动态更改手机Spinner控件 8.19 网络语音搜索 8.20 网络下载过程中显示加载中 8.21 快照WebView加载的...

    android安卓绝对可以获取GPS经纬度的google map demo

    使用谷歌api,不需要网络,可以直接获取经纬度,获取经纬度写到一个类中,直接调用start,关闭使用stop。 注意要在室外使用! 打开应用,马上开始获取地址,多次点击 第一个按钮: 获取gps经纬度, 如果程序获取到...

    Google Android SDK开发范例大全(第3版)part2

     8.14 远程下载安装Android程序  8.15 手机下载看3gp影片  8.16 访问网站Login API  8.17 地震速报  8.18 通过Web API动态更改手机Spinner控件  8.19 网络语音搜索  8.20 网络下载过程中显示加载中  ...

    Google Android SDK开发范例大全(PDF高清完整版1)(4-1)

    8.14 远程下载安装Android程序——APKInstaller的应用 8.15 手机下载看3gp影片——Runnable混搭SurfaceView 8.16 访问网站LoginAPI——远程服务器验证程序运行权限 8.17 地震速报!——HttpURLConnection与Service...

    Google Android SDK开发范例大全(PDF完整版4)(4-4)

    8.14 远程下载安装Android程序——APKInstaller的应用 8.15 手机下载看3gp影片——Runnable混搭SurfaceView 8.16 访问网站LoginAPI——远程服务器验证程序运行权限 8.17 地震速报!——HttpURLConnection与Service...

    Google Android SDK开发范例大全(PDF高清完整版3)(4-3)

    8.14 远程下载安装Android程序——APKInstaller的应用 8.15 手机下载看3gp影片——Runnable混搭SurfaceView 8.16 访问网站LoginAPI——远程服务器验证程序运行权限 8.17 地震速报!——HttpURLConnection与Service...

    Google Android SDK开发范例大全的目录

    8.14 远程下载安装Android程序——APKInstaller的应用 8.15 手机下载看3gp影片——Runnable混搭SurfaceView 8.16 访问网站LoginAPI——远程服务器验证程序运行权限 8.17 地震速报!——HttpURLConnection与Service...

    Xrob:Xrob 是通过 SMS 命令的 Android 设备管理器应用程序

    罗布 Xrob 是一个 Android 设备管理器应用程序。 在 Xrob 的帮助下,我们... 1 ) 在您的 Android 设备中安装此应用程序。 2) 拿另一部手机,输入指令并发送到您的手机号码。 3)完成。 命令是什么?? 注意:每条命令

    google android sdk开发范例大全 第二版 PDF 光盘代码

     8.14 远程下载安装Android程序   8.15 手机下载看3gp影片   8.16 访问网站Login API   8.17 地震速报   8.18 通过Web API动态更改手机Spinner控件   8.19 网络语音搜索   8.20 网络下载...

Global site tag (gtag.js) - Google Analytics