Android SDK 版本号与版本名称对照及一个编程小技巧

时间:2024-03-03 11:26:47

  前几天,为了解决一个问题,逆了一个小工具软件。在这个过程发现了一些很有用的东西,在此跟大家分享一下。首先声明几点:1、逆出来的代码,需要大量的人工分析,我现在只看了一点点;2、代码不会公开,请不要向我要代码,我怕麻烦~~~唉,做了这件坏事,内心忐~~~忑~~~啊!

一、通过编程实现对GPS的开关

  在Android手机和模拟器上有一个管理GPS开关的设置界面,如下:

    

  通过这个管理界面,我们可以对GPS进行管理,以实现我们的手机定位功能。曾经在网上搜集资料,希望找到通过代码对GPS进行管理的源码,也确实找到了一份代码(稍后附上代码),但是这份代码在SDK 2.3及以上的版本中,始终不能运行。于是,产生了一个逆向的邪念~

  在分析上面提到的小工具之后,发现了其对GPS管理的功能模块,经过简单的分析之后,发现在Android SDK版本不同的情况下,对GPS控制的代码还不一样。首先附上在2.2版本及以前版本的GPS控制代码:

/**
* 实现了一个GPS的开关,当前关闭则打开,当前打开则关闭
* 适用版本号:
* 1.6 / 2.1 / 2.2
*
* Uri.parse()的参数"custom:3"中的数字3的枚举值如下:
* 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;
*
*/
private void toggleGPS() {
// 当SDK版本号为2.3以下版本时
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
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();
}
}
}

  以上这段代码,是利用Android平台自带的Widget插件对各种开关进行管理的。实现的是一个GPS的开关,如果当前GPS处于关闭状态,则将其打开;如果GPS处于打开状态,则将其关闭。

  大家可能已经注意到函数体内部的第一行注释“当SDK版本号为2.3一下版本时”,的确我们在这里做了一个针对SDK版本的判断。这一个判断也是我们下一个小节要重点介绍的内容,暂时放在一边,不要在这一节里面跑偏了。

  在SDK 2.3及之后的版本中,那个小工具利用了SDK中的类Settings.Secure的一个静态方法:

public static final void setLocationProviderEnabled (ContentResolver cr, String provider, boolean enabled)

Since: API Level 8

Thread-safe method for enabling or disabling a single location provider.

Parameters

cr

the content resolver to use

provider

the location provider to enable or disable

enabled

true if the provider should be enabled

  这个方法从API Level 8才开始提供,API Level 8对应的SDK版本是2.2,OK!那按照正常情况来说,这个函数应该是支持SDK2.3的。不妨写个函数来试试。(这个代码比较简单,我就不再贴代码了)结果却令人意外,没有给用户分配权限"android.permission.WRITE_SETTINGS";好嘛,那就加上权限;又提示没有权限“android.permission.WRITE_SECURE_SETTINGS”,好说,再加上这个权限。接下来,见证悲催的时刻到了,还是提示没有“android.permission.WRITE_SECURE_SETTINGS”的权限。明明已经加上了权限,为何还是提示。最后也是在各种大小论坛里面查找资料,说是在2.3版本里面,Google把这个权限完全锁住了,好吧,悲剧了,除非你自己改Android代码,否则就真的没有别的办法了。

  所以,在第一节结束的时候,提醒各位童鞋,如果想在SDK2.3版本管理GPS,还是乖乖的用你的Intent打开系统默认的管理GPS的Activity吧。

二、SDK版本对照

  为了下载android SDK的源码,我到处找链接,好不容易一个链接,发现文件名后面怎么还有一个类似英文名的东西?

                

  的确,像我这样的初学者,是不知道这个英文单词代表什么意思的。但是在逆代码的过程,发现了Android API给我们提供了这样个类android.os.Build,在这个类中定义了Android SDK每个版本的版本号,版本名,以后其他一些信息,感兴趣的同学可以去开发文档中看看。

  这里的英文单词,就是每个SDK版本的版本名称。

VERSION_CODES
/**
* Enumeration of the currently known SDK version codes. These are the
* values that can be found in {
@link VERSION#SDK}. Version numbers
* increment monotonically with each official platform release.
*/
public static class VERSION_CODES {
/**
* Magic version number for a current development build, which has
* not yet turned into an official release.
*/
public static final int CUR_DEVELOPMENT = 10000;

/**
* October 2008: The original, first, version of Android. Yay!
*/
public static final int BASE = 1;

/**
* February 2009: First Android update, officially called 1.1.
*/
public static final int BASE_1_1 = 2;

/**
* May 2009: Android 1.5.
*/
public static final int CUPCAKE = 3;

/**
* September 2009: Android 1.6.
*
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
* <ul>
* <li> They must explicitly request the
* {
@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission to be
* able to modify the contents of the SD card. (Apps targeting
* earlier versions will always request the permission.)
* <li> They must explicitly request the
* {
@link android.Manifest.permission#READ_PHONE_STATE} permission to be
* able to be able to retrieve phone state info. (Apps targeting
* earlier versions will always request the permission.)
* <li> They are assumed to support different screen densities and
* sizes. (Apps targeting earlier versions are assumed to only support
* medium density normal size screens unless otherwise indicated).
* They can still explicitly specify screen support either way with the
* supports-screens manifest tag.
* </ul>
*/
public static final int DONUT = 4;

/**
* November 2009: Android 2.0
*
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
* <ul>
* <li> The {
@link android.app.Service#onStartCommand
* Service.onStartCommand} function will return the new
* {
@link android.app.Service#START_STICKY} behavior instead of the
* old compatibility {
@link android.app.Service#START_STICKY_COMPATIBILITY}.
* <li> The {
@link android.app.Activity} class will now execute back
* key presses on the key up instead of key down, to be able to detect
* canceled presses from virtual keys.
* <li> The {
@link android.widget.TabWidget} class will use a new color scheme
* for tabs. In the new scheme, the foreground tab has a medium gray background
* the background tabs have a dark gray background.
* </ul>
*/
public static final int ECLAIR = 5;

/**
* December 2009: Android 2.0.1
*/
public static final int ECLAIR_0_1 = 6;

/**
* January 2010: Android 2.1
*/
public static final int ECLAIR_MR1 = 7;

/**
* June 2010: Android 2.2
*/
public static final int FROYO = 8;

/**
* Newest version of Android, version 2.3.
*/
public static final int GINGERBREAD = 9;
}

  Android 1.5:Cupcake(杯子蛋糕)
  Android 1.6:Donut(甜甜圈)
  Android 2.0 / 2.1:Eclair(闪电泡芙)
  Android 2.2:Froyo(冷冻忧格)
  Android 2.3:Gingerbread(姜饼)
  Android 3.0:Honeycomb(蜂巢)

  有时候在编码过程,的确会遇到在不同的SDK版本下,某一个功能的实现方案不一样的情况,这时就需要大家判断SDK的版本,采取不同的实现方案,这样才能让我们的App保证良好的兼容性。所以相信下面这个简单的判断语句对你来说,会非常有用:

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
......
}

  如果想对这个有一个更加深入的了解,建议仔细看看Class android.os.Build,开发文档始终使我们学习的利器。

  希望以上的这些东西对大家会有用!与大家共勉!