GMS认证之verifier--LOCATION源码赏析

来源:互联网 发布:淘宝正品运动鞋店推荐 编辑:程序博客网 时间:2024/04/30 13:01

这里写图片描述

LOCATION 测试简单介绍

verifier 测试的LOCATION,主要是测试位置模式是否生效,分别测试位置模式为省电模式,仅仅是设备模式,高精度模式和位置关闭模式。

这里写图片描述

关键测试内容

其实verifier此测试项,主要是测试LOCATION功能是否正常,也就是检查一下是否当前的位置模式与设置后的位置模式是否匹配,校验核心代码非常简单:

以Batteru Saving Mode Test为例,只是比较一下db数据库的数据:

testIsExpectedMode(1, Secure.LOCATION_MODE_BATTERY_SAVING);
protected void testIsExpectedMode(int i, int expectedMode) {        int mode = getLocationMode();        boolean passed = mode == expectedMode;        ……………}
private int getLocationMode() {        ContentResolver cr = getContentResolver();        return Secure.getInt(cr, Secure.LOCATION_MODE, Secure.LOCATION_MODE_OFF);}

同样的,其它三种测试:

Device Only Mode Test:

testIsExpectedMode(1, Secure.LOCATION_MODE_SENSORS_ONLY);

Hight Accuracy Mode Test:

testIsExpectedMode(1, Secure.LOCATION_MODE_HIGH_ACCURACY);

Location Mode Off Test:

testIsExpectedMode(0, Secure.LOCATION_MODE_OFF);

源码结构赏析

location目录代码:

这里写图片描述

我看完这一块代码,对google公司写此段代码的哥哥非常敬佩,觉得这才是一个合格的软件工程师写出来的作品。

先来张UML类图:
这里写图片描述

怎么样,不是我写的太简单,而是源码就是如此简洁。
简单的介绍一下此uml类图吧:

LocationModeTestActivity:
此类是一个父类,定义了三个抽象方法:
createTestItems ():—-创建测试项
setInfoResources():—-设置测试项的名称
testAdvance(int state):—-测试逻辑

关键的几个属性:
LayoutInflater mInflater—-处理UI界面
ViewGroup mItemList—-处理UI界面,主要是添加测试项
Runnable mRunner—-处理逻辑的线程
View mHandler—-处理逻辑线程的发动者

在LocationModeTestActivity类中,我们已经定义好了上面三个抽象方法的执行方法,然后我们在后面的具体测试实现类中,也就是:
LocationModeBatterySavingTestActivity(测试省电模式)
LocationModeHighAccuracyTestActivity(测试高精度模式)
LocationModeDeviceOnlyTestActivity(仅仅设备模式)
LocationModeOffTestActivity(位置关闭模式)

实现上面定义的三个抽象方法,并且实现是非常的简洁,就ok了。

是不是觉得非常神奇,是不是觉得非常好扩展,是不是觉得结构非常的眼孰啊,记不记得有一种设计模式就是此特点。

哈哈,对,这就是常见的模板模式(如果你不知道模板模式,如果是新手快点学,如果是工作几年的老手,那只能证明你还是个新手,并且不合格,啊噢)。

如果是一般的程序员来实现此功能,他可能会觉得这个实现不难,针对各个位置模式,分别写一个检测算法,实现完事。后面的同事如果再要扩展此实现,不好意思,请客官自己从零开始实现吧。

这就是一般程序员和android公司的程序员的区别:

一位针对具体实现编程,一位针对接口和抽象来编程!
一位完成自己工作编程,一位针对程序框架编程,选择适合成熟的设计模式,方便程序扩展,方便多人协作。

这就是当我看到此模块的代码时的想法!

小弟经常感觉自己每天都在和一帮忙乌合之众在上班,真的,android的软件工程师,好想和你们做朋友啊。

源码关键实现赏析

那我们再来看看几个关键的怎么实现的吧:

界面是如何实现的

在LocationModeTestActivity类中的onCreate方法中,我们就定义了界面的相关逻辑:

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        ........        mRunner = this;        mInflater = getLayoutInflater();        View view = mInflater.inflate(R.layout.location_mode_main, null);        mItemList = (ViewGroup) view.findViewById(R.id.test_items);        mHandler = mItemList;        createTestItems();        ..........        setContentView(view);        ............        setInfoResources();        ...............    }

我们可以明显的知道,抽象方法createTestItems()和setInfoResources在onCreate方法中,用以来实现子类的界面的自定义。

那子类的界面是如何自定义的呢:
我们以LocationModeBatterySavingTestActivity为例,查看具体实现方法:

    @Override    protected void createTestItems() {        createUserItem(R.string.location_mode_turn_on);        createUserItem(R.string.location_mode_select_battery_saving);        createAutoItem(R.string.location_mode_secure_gps_off);        createAutoItem(R.string.location_mode_secure_nlp_on);        createAutoItem(R.string.location_mode_manager_gps_off);        createAutoItem(R.string.location_mode_manager_nlp_on);    }
    @Override    protected void setInfoResources() {        setInfoResources(R.string.location_mode_battery_saving_test,                R.string.location_mode_battery_saving_info, -1);    }

在createTestItems方法中,主要调用createUserItem方法,我们再查看LocationModeTestActivity类中的createUserItem方法:

protected View createUserItem(int stringId) {        View item = mInflater.inflate(R.layout.location_mode_item, mItemList, false);        TextView instructions = (TextView) item.findViewById(R.id.instructions);        instructions.setText(stringId);        mItemList.addView(item);        return item;}

看到没,就是直接把一个view添加到mItemList中,简单明了吧。

setInfoResources也是同样的原理。

测试逻辑是如何实现的

我们查看LocationModeTestActivity类:

public abstract class LocationModeTestActivity        extends PassFailButtons.Activity implements Runnable {

也就说,LocationModeTestActivity类实现了接口Runnable,我们来看run方法:

public void run() {    ........    testAdvance(mState);    ........}

从中我们可以看出实现测试逻辑的方法testAdvance是在run()方法中来调用的,那么我们是在那里调用run方法呢?
我们定义:

private Runnable mRunner;private View mHandler;

然后在next()和delay()方法中调用接口run()方法:

    protected void next() {        mHandler.post(mRunner);    }
    protected void delay() {        mHandler.postDelayed(mRunner, 2000);    }

那么next()和delay()方法是什么时候调用呢?

    protected void testIsOn(int i) {        ......        next();    }
    protected void testIsExpectedMode(int i, int expectedMode) {        ...        next();        ....        delay();    }
    protected void testSecureProviderIsEnabled(int i, String provider) {        ....        next();    }
    protected void testSecureProviderIsDisabled(int i, String provider) {        ....        next();    }
    protected void testManagerProviderIsEnabled(int i, String gpsProvider) {        ....        next();    }
protected void testManagerProviderIsDisabled(int i, String gpsProvider) {    .....    next();}

看明白没,对,这就是每个测试项后,都直接执行next(),来调用对应的方法来测试对应的逻辑。

最让我感觉意外的是:

private ViewGroup mItemList;private View mHandler;
mItemList = (ViewGroup) view.findViewById(R.id.test_items);mHandler = mItemList;
mHandler.post(mRunner);mHandler.postDelayed(mRunner, 2000);

难道View有handler的作用吗?可以调用post和postDelayed方法?

好吧,我打开国内打不开的android官网,查看了一个view类的说明:

java.lang.Object   ↳    android.view.View
boolean post(Runnable action)Causes the Runnable to be added to the message queue.
boolean postDelayed(Runnable action, long delayMillis)Causes the Runnable to be added to the message queue, to be run after the specified amount of time elapses.

好吧,懂你。
我真是没有见识。

至此,文章已经写完了。可能有的人会问,此源码在那里,好吧,如果你有兴趣,可以去源码的cts/apps/CtsVerifier目录下去查看了。

0 0
原创粉丝点击