在Uiautomator中使用Content Provider获取数据

注:1.本文针对Uiautomator2.0

  2.本文不对Content Provider进行介绍,如果您对Content Provider不了解,建议您先阅读相关的文章

Content Provider Basics

ConTent Provider 介绍

  推广自动化已经有半年的时间了。在推广过程中也也遇到了一些问题,今天来讲下如何使用Android的Content Provider来快捷的获取某个程序的数据。
  首先先简单介绍一下,什么是Content Provider,这里直接摘抄官网的定义:

A content provider manages access to a central repository of data.
A provider is part of an Android application, which often provides its own UI for working with the data.

  简单来讲,Conent Provider是用来访问程序的内部数据,由于谷歌的安全机制,外部程序是没办法访问,程序内部数据的,因此当需要访问某一个程序内部的数据时,就需要使用到Content Provider。这里举个例子:比如:应用A想知道手机里有多少个短信,那么就需要查询短信app的数据库,如果直接访问,肯定是不行的,因此就需要使用到Content provider来访问。

  废话不多说,下面来讲讲在自动化测试中,Content Provider的使用场景,
不知道大家有没有遇到以下的问题:

  1. 在自动化测试的时候,知道手机里有多少个联系人?
  2. 在手机里添加了一个联系人,想检查是否添加成功?
  3. 知道某个联系人的名字想获取他的手机号?

  如果让你来做你会怎么处理?怎么才能最简单?

  1. 怎么在程序里获取手机里有多少个联系人?
  2. 是使用UICollection配合UIScrollable一页一页的滚动,然后统计?
  3. 如何知道添加的联系人是否成功了?滑动查找,遍历整个联系人列表?
  4. 如果在联系人少的时候,此方案听起来还是蛮不错的,但是,如果你手机里有1000个联系人呢?光一个查找就需要花费多少时间呢?

  因此这里强烈推荐你使用Content Provider,直接查询联系人的数据库。简单快捷。

  下图,展示了。Content Provider 和其他组件的关系:
Content Provider和其他组件的关系

下面我们来了解下,如何在测试中使用Content Provider。

1.在AndroidManifest.xml文件中添加读写联系人的权限。

1
2
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_CONTACTS"></uses-permission>

mainfest

2.指定主机地址

1
private static Uri uri = ContactsContract.Data.CONTENT_URI;

3.获取到目标应用程序的Content
注:为了方便后续使用,这里封装成一个方法。

1
2
3
public static Context getTargetContext(){
return InstrumentationRegistry.getTargetContext();
}

4.获取到contentResolver.

1
private static ContentResolver contentResolver = getTargetContext().getContentResolver();

5.创建查询条件

1
Cursor cursorData = contentResolver.query(uri, null, null, null, null);

注:null表示返回所有信息

6.操作cusor读取详细信息。

1
2
3
4
5
6
7
8
9
if (cursorData != null) {
while (cursorData.moveToNext()) {
String mimeType = cursorData.getString(cursorData.getColumnIndex(ContactsContract.Contacts.Data.MIMETYPE));
String data1 = cursorData.getString(cursorData.getColumnIndex(ContactsContract.Contacts.Data.DATA1));
System.out.println("AAA"+data1);
}
}

  最后附上完成的源码和截图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package rory.tech.contentproviderdemo;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.test.InstrumentationRegistry;
import org.junit.Test;
/**
* Created by Rory on 2017/03/14.
*/
public class ContentProviderTestDemo {
//Define the content provider host url.
private static Uri uri = ContactsContract.Data.CONTENT_URI;
private static ContentResolver contentResolver = getTargetContext().getContentResolver();
@Test
public void testContentProvider() {
Cursor cursorData = contentResolver.query(uri, null, null, null, null);
if (cursorData != null) {
while (cursorData.moveToNext()) {
String mimeType = cursorData.getString(cursorData.getColumnIndex(ContactsContract.Contacts.Data.MIMETYPE));
String data1 = cursorData.getString(cursorData.getColumnIndex(ContactsContract.Contacts.Data.DATA1));
System.out.println("AAA"+data1);
}
}
}
public static Context getTargetContext() {
return InstrumentationRegistry.getTargetContext();
}
}

系统联系人截图
系统联系人截图

控制台打印截图:

控制台打印
注:

  1. 这里只是一个Demo,没有做处理,这样获取到的信息,是不方便查看的,你不知道1001-2是名字还是电话。所以在实际使用中,需要对信息进行判断。
  2. 可以使用mimeType来进行数据的识别。这里就不做演示啦!!!
  3. 实际使用时建议使用Java Been来做数据处理。

    完整示例下载