在Android自动化测试中,通过自动化测试脚本填充联系人、通话记录、短信等数据,可以模拟出更接近真实用户的使用场景。这种模拟有助于发现那些在日常使用中才会出现的问题,从而提高测试的全面性和准确性。
联系人
权限
读写联系人需要以下权限,直接动态申请即可
1 2
| <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
|
填充方法
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
| private boolean insertContacts(String names, String num) { ArrayList<ContentProviderOperation> ops = new ArrayList<>(); ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null) .build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, names) .build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, num) .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE) .build());
try { getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); return true; } catch (Exception e) { Log.e(TAG, "insertContacts error: " + e); return false; } }
|
删除方法
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
| private void deleteAllContacts() { Uri uri = ContactsContract.Contacts.CONTENT_URI; String[] projection = new String[]{ContactsContract.Contacts._ID}; String selection = null; String[] selectionArgs = null; String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder); if (cursor != null) { try { while (cursor.moveToNext()) { @SuppressLint("Range") long contactId = cursor.getLong(cursor.getColumnIndex(ContactsContract.Contacts._ID)); if (deleteContact(contactId)) { Log.d(TAG, String.format("delete contact %s succ\n", contactId)); } else { Log.e(TAG, String.format("delete contact %s fail\n", contactId)); } } } finally { cursor.close(); } } }
private boolean deleteContact(long contactId) { try { Uri deleteUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId); int rowsDeleted = getContentResolver().delete(deleteUri, null, null); if (rowsDeleted > 0) { return true; } } catch (Exception e) { Log.e(TAG, "deleteContactError: " + e); } return false; }
|
通话记录
权限
读写通话记录需要以下权限,直接动态申请即可
1 2
| <uses-permission android:name="android.permission.READ_CALL_LOG"/> <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
|
填充方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| private boolean insertCallLog(String number, String duration, String type, String isNew) { ContentValues values = new ContentValues(); values.put(CallLog.Calls.NUMBER, number); values.put(CallLog.Calls.DATE, System.currentTimeMillis()); values.put(CallLog.Calls.DURATION, duration); values.put(CallLog.Calls.TYPE, type); values.put(CallLog.Calls.NEW, isNew); try { getContentResolver().insert(CallLog.Calls.CONTENT_URI, values); return true; } catch (Exception e) { Log.e(TAG, "insertCallLog error: " + e); return false; } }
|
删除方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| private boolean deleteAllCallLogs() { try { int rowsDeleted = getContentResolver().delete(CallLog.Calls.CONTENT_URI, null, null); if (rowsDeleted > 0) { return true; } } catch (Exception e) { Log.e(TAG, "deleteAllCallLogs error: " + e); } return false; }
|
短信
权限
短信较为特殊,由于Android4.4之后,除了默认短信应用以外,其他应用将无法插入短信。因此需要将APK伪装成一个短信应用,并设置为默认的短信应用。
仅在默认处理程序中使用的权限 | Android Developers
AndroidManifest.xml中添加
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| <uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.RECEIVE_SMS"/> <uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />
<application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/app" android:label="@string/app_name" android:roundIcon="@mipmap/app_round" android:supportsRtl="true" android:theme="@style/Theme.AutoFill" > <receiver android:name=".SmsReceiver" android:permission="android.permission.BROADCAST_SMS" android:exported="true" tools:ignore="WrongManifestParent"> <intent-filter> <action android:name="android.provider.Telephony.SMS_DELIVER" /> </intent-filter> </receiver> <receiver android:name=".MmsReceiver" android:permission="android.permission.BROADCAST_WAP_PUSH" android:exported="true" tools:ignore="WrongManifestParent"> <intent-filter> <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" /> <data android:mimeType="application/vnd.wap.mms-message" /> </intent-filter> </receiver> <service android:name=".HeadlessSmsSendService" android:exported="true" android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE" tools:ignore="WrongManifestParent"> <intent-filter> <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" /> <category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" /> <data android:scheme="smsto" /> <data android:scheme="mms" /> <data android:scheme="mmsto" /> </intent-filter> </service> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.SEND" /> <action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sms" /> <data android:scheme="smsto" /> <data android:scheme="mms" /> <data android:scheme="mmsto" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
|
分别创建空的HeadlessSmsSendService,MmsReceiver,SmsActivity,SmsReceiver,SmsService
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
| public class HeadlessSmsSendService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return null; } } public class MmsReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { } } public class SmsActivity extends Activity { } public class SmsReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { } } public class SmsReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { } }
|

最后,需要将APK设置为默认短信应用(需要手动授予)
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
| private String getDefaultSms() { String packageName = "null"; Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:")); PackageManager packageManager = getApplicationContext().getPackageManager(); ResolveInfo resolveInfo = packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); if (resolveInfo != null) { packageName = resolveInfo.activityInfo.packageName; } return packageName; }
private void setDefaultSms(int requestCode) { String defaultSmsPkg = Telephony.Sms.getDefaultSmsPackage(getApplicationContext()); Log.d(TAG, "default SMS: " + defaultSmsPkg); if (!defaultSmsPkg.equals(getPackageName())) { RoleManager roleManager = (RoleManager) getSystemService(Context.ROLE_SERVICE); if (roleManager != null && roleManager.isRoleAvailable(RoleManager.ROLE_SMS)) { Intent roleRequestIntent = roleManager.createRequestRoleIntent(RoleManager.ROLE_SMS); if (roleRequestIntent != null) { startActivityForResult(roleRequestIntent, requestCode); } } } }
protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); }
|
填充方法
1 2 3 4 5 6 7 8 9 10 11
| private void insertMessages(String num, String body, long date) { ContentResolver contentResolver = getContentResolver(); ContentValues values = new ContentValues(); Uri uri = Uri.parse("content://sms/"); values.put(Telephony.Sms.ADDRESS, num); values.put(Telephony.Sms.DATE, date); values.put(Telephony.Sms.READ, false); values.put(Telephony.Sms.STATUS, Telephony.Sms.STATUS_NONE); values.put(Telephony.Sms.BODY, body); contentResolver.insert(uri, values); }
|
删除方法
1 2 3 4 5 6 7 8 9 10
| private void deleteAllSMS() { Uri uriSms = Uri.parse("content://sms/"); Cursor c = getContentResolver().query(uriSms, null, null, null, null);
while (c.moveToNext()) { long id = c.getLong(c.getColumnIndexOrThrow("_id")); getContentResolver().delete(Uri.parse("content://sms/" + id), null, null); } c.close(); }
|