每次拉取共享路径上最新的被测 apk 包运行自动化用例,但是发现在 oppo r9s 手机上每次安装被测 app 、Settings 、unlock 程序的时候会弹出密码输入框,而且需要手动点击 “安装” 按钮。
实现原理:使用 AccessibilityService 实现自动输入密码、点击安装按钮,步骤如下:
(1)新建 android 工程,创建 AutoInstallService ,如下
public class AutoInstallService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
Log.d("InstallService", "onAccessibilityEvent");
//针对oppo r9s,oppo手机上就是很麻烦需要点击多步安装
sendInstallPassword("com.coloros.safecenter:id/et_login_passwd_edit","123456");//输入安装密码123456,不同的oppo时id还不一样
clickInstallButton("android:id/button1");//点击安装按钮
clickInstallButton("com.android.packageinstaller:id/btn_allow_once");//点击安装按钮
clickInstallButton("com.android.packageinstaller:id/ok_button");//点击安装按钮
clickInstallButton("com.android.packageinstaller:id/bottom_button_one");//点击完成按钮
}
private void sendInstallPassword(String id,String text){
if(getRootInActiveWindow() == null)
return;
try{
List<AccessibilityNodeInfo> nodes = getRootInActiveWindow().findAccessibilityNodeInfosByViewId(id);
if(nodes.size()==1){
Log.d("AutoInstallService", "m的值:"+m);
AccessibilityNodeInfo node = nodes.get(0);
AccessibilityNodeInfo target = node.findFocus(AccessibilityNodeInfo.FOCUS_INPUT);
if (target == null) {
Log.d("AutoInstallService", "inputPassword: null");
return;
}
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("label",text);
clipboard.setPrimaryClip(clip);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
target.performAction(AccessibilityNodeInfo.ACTION_PASTE);
}
}
}catch (NullPointerException e){
Log.d("AutoInstallService","没有找到控件");
}
}
private void clickInstallButton(String id){
if(getRootInActiveWindow() == null){
return;
}
try{
//以下操作针对oppo手机上,点击'继续安装'按钮
List<AccessibilityNodeInfo> nodes = getRootInActiveWindow().findAccessibilityNodeInfosByViewId(id);
for(int i = 0;i<nodes.size();i++){
AccessibilityNodeInfo node = nodes.get(i);
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}catch (NullPointerException e){
Log.d("AutoInstallService","没有找到控件");
}
}
@Override
protected void onServiceConnected() {
super.onServiceConnected();
PrintUtils.log("onServiceConnected");
}
@Override
public void onInterrupt() {
PrintUtils.log("onInterrupt");
}
}
(2)在 AndroidManifest.xml 中配置 service :
<service
android:name=".service.AutoInstallService"
android:enabled="true"
android:exported="true"
android:label="@string/app_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/auto_install_services_config" />
</service>
(3)安装该 apk 之后,在手机设置->辅助设置中打开该服务开关,安装 app 的时候回自动输入密码,自动点击安装:
原因:使用 adb 命令行安装实际上是分两个步骤,第一步 push apk 包到 data 目录,第二步安装 apk ,oppo 手机比较特别的一点就是 push 到 data 目录开始安装的时候就会返回 success ,导致 apk 还没有安装完成 appium 就会 launch 入口 activity,导致提示 " Activity used to start app doesn't exist or cannot be launched" 。
解决方法:比较山寨,就是在连接 appium 服务之前提前安装被测 apk。
每次安装之后调用 adb 命令退出安装 apk,adb.quit_app('com.android.packageinstaller'),如下:
for i in range(len(udids)):
a = adb.ADB(udids[i])
a.remove_app('com.lemon.faceu')
apkPath = BASE_DIR + '/img/'+ runnerBase.getApkname()
result = a.install_app(apkPath)
while not result: #如果安装不成功,等待
time.sleep(2)
#oppo手机上的一个bug,需要杀死系统安装程序
adb.ADB(udids[i]).quit_app('com.android.packageinstaller') #安装成功之后
main() #进入运行 case 流程