手机应用中最酷的可能就是位置服务相关的了,如何读取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中添加如下方法:
//打开GPS
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,代码片断如下:
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。
分享到:
相关推荐
【Android】代码开启/关闭GPSDemo 相关文章:... 为了方便看效果,您可以在在onCreate中添加finish();方法,然后打开系统GPS设置页面再运行代码,这样就能看到GPS开关的变化了。
本DEMO代码旨在展示如何在Android应用中实现基本的GPS功能,让开发者能够理解和学习如何获取用户的位置坐标。下面我们将深入探讨这个DEMO涉及的关键知识点。 1. **权限声明**:在AndroidManifest.xml文件中,你需要...
支持2.1以上的android版本,可以把里面的APK下载到真机上测试,可以做到和系统的GPS开关同步控制,源码是在LINUX下编译的,因为android2.1把修改GPS开关的代码HIDE了,所以在2.1window平台下是编译不了。但是APK直接...
然而,有些开发者可能需要在没有用户交互的情况下强制开启GPS,这涉及到对Android API的深入理解和使用。以下是对这个主题的详细阐述: 首先,Android提供了LocationManager服务,它允许应用请求位置更新并管理不同...
本文将详细介绍如何通过源代码在Android设备上获取GPS定位信息,并将其存储到SQLite本地数据库中。 首先,Android系统提供了LocationManager服务来获取GPS定位数据。在AndroidManifest.xml文件中,我们需要添加访问...
我们将基于提供的"android 测试GPS搜星程序及源代码"进行讨论。 首先,GPS搜星程序的主要目标是检测和追踪卫星信号,以实现精确的地理位置定位。Android系统提供了一个名为"Location Services"的框架,允许开发者...
Android GPS 架构中的 GPS 开启与关闭需要了解普通应用程序启动 GPS 设备的代码实现、Settings.Secure.setLocationProviderEnabled 的调用过程、数据库写入过程、Android 启动过程等相关知识点。只有掌握这些知识点...
为了提高用户体验,项目可能还包含了错误处理和用户提示,例如当GPS未开启时提示用户打开GPS服务,或者在定位失败时给出相应提示。此外,为了提供更准确的定位,开发者可能也考虑了网络定位作为GPS的补充。 总的来...
总的来说,这个源代码示例涵盖了Android应用如何请求定位权限,配置UI来显示位置信息,并通过`LocationManager`获取GPS坐标的基本步骤。在实际的开发过程中,还需要考虑性能优化,如使用`...
要检测GPS是否开启,我们可以调用`LocationManager`的`isProviderEnabled()`方法,传入`LocationManager.GPS_PROVIDER`作为参数。如果返回值为`true`,则表示GPS已开启;反之,则表示关闭。 在获取GPS定位时,我们...
二,当你开启GPS,provider的值为GPS。这时的定位方式为GPS,由于GPS定位慢,所以它不可能立即返回你一个Location对象,所以就返回null了。 **3.推荐locationManager.requestLocationUpdates();方法** ...
如果用户未开启GPS,应用可以提示用户打开。 6. **请求位置更新**:调用`LocationManager.requestLocationUpdates()`可以设置位置更新的频率和最小距离变化,以便在满足条件时触发位置更新。 7. **处理位置数据**...
添加权限的方法是在 AndroidManifest.xml 文件中添加以下代码:<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"> 二、判断 GPS 模块是否存在或者是开启 在使用 GPS 设备之前,需要判断 ...
此外,考虑到用户可能没有开启GPS或网络不稳定,你应该处理这些情况。例如,你可以检查位置提供者是否可用,或者设置超时机制。同时,为了提高用户体验,可以使用 fused location provider(融合定位服务),它能...
在Android系统中,GPS(全球定位系统)是设备获取地理位置信息的重要途径。...通过以上方法,用户可以有效地提升GPS信号质量和定位精度,享受到更顺畅的定位服务。对于复杂问题,可能需要寻求专业技术人员的帮助。
Android GPS 代码分析主要涉及 Android 系统中GPS功能的实现机制,这一过程涵盖了从应用程序层到硬件层的交互。下面将详细阐述Android系统如何管理和使用GPS功能。 首先,Android的GPS结构主要分为三个层次:应用...
4. **设置和控制**:HAL提供了设置GPS参数的接口,例如开启/关闭GPS,设置定位精度、更新频率等。 5. **电源管理**:驱动还需要处理电源管理,确保在不需要定位服务时,能有效降低功耗。 在源码层面,Android GPS...
这个“android GPS地图源代码,可以获取GPS位置,可以运行.zip”压缩包文件提供了实现这一功能的实例源码,是学习和研究的好资料。 首先,我们需要了解Android中的Location API。这是Android系统提供的接口,用于...
在Android系统中,GPS(全球定位系统)是设备获取地理位置信息的重要途径。NMEA(National Marine Electronics Association)数据是GPS接收器输出的一种标准格式,包含了关于地理位置、时间、卫星状态等丰富的信息。...
在代码层面,首先需要实例化一个LocationManager对象,并通过调用`locationManager.requestLocationUpdates()`方法来订阅位置更新。这里需要传入定位提供者(通常是`LocationManager.GPS_PROVIDER`),更新的最小...