Ⅰ appium怎样利用java进行截图
public class ContactsTest {
18 private AppiumDriver driver;
19 @Before
20 public void setUp() throws Exception {
21 //设置apk的路径
22 File classpathRoot = new File(System.getProperty("user.dir"));
23 File appDir = new File(classpathRoot, "apps");
24 File app = new File(appDir, "ContactManager.apk");
25
26 //设置自动化相关参数
27 DesiredCapabilities capabilities = new DesiredCapabilities();
28 capabilities.setCapability(CapabilityType.BROWSER_NAME, "");
29 capabilities.setCapability("platformName", "android");
30 capabilities.setCapability("deviceName", "Android Emulator");
31
32 //设置安卓系统版本
33 capabilities.setCapability("platformVersion", "4.3");
34 //设置apk路径
35 capabilities.setCapability("app", app.getAbsolutePath());
36
37 //设置app的主包名和主类名
38 capabilities.setCapability("appPackage", "com.example.android.contactmanager");
39 capabilities.setCapability("appActivity", ".ContactManager");
40
41 //初始化
42 driver = new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
43 }
44
45 @Test
46 public void addContact(){
47 WebElement el = driver.findElement(By.name("Add Contact"));
48 el.click();
49 List<WebElement> textFieldsList = driver.findElementsByClassName("android.widget.EditText");
50 textFieldsList.get(0).sendKeys("Some Name");
51 textFieldsList.get(2).sendKeys("[email protected]");
52 driver.swipe(100, 500, 100, 100, 2);
53 driver.findElementByName("Save").click();
54 }
55
56 @After
57 public void tearDown() throws Exception {
58 driver.quit();
59 }
60 }
Ⅱ appium-desktop-Setup 找不到Java命令
展开全部 安装Appium在控制台运行npm命令来安装a... 1 创建一个java工程将pom.xml文件放到工... 2 修改AndroidContactsTest.java文件,修... 3 启动模拟器和Appium命令行运行appium,... 4 进入java工程的根目录,运行Maven命令... 5 开发包参考下载地
Ⅲ appium 脚本运行不起来,为啥呀
首先,要保证appium服务正确的启动了,这是第一步
看楼上应该是appium配置出了问题。
appium主要需要配置两个地方,一个是sdk路径,一个是ip+端口号
Ⅳ Appium超时错误连接到驱动程序时问题,怎么解决
问题
1. error: Failed to start an Appium session, err was: Error: Requested a new session but one was in progress
之前的会话没有关闭,然后你又运行了测试实例,也没有设置覆盖.
解决:
1.重新停止appium服务,开启Appium服务
2.在Genarel Setting那里设置覆盖Session,重启Appium
测试结束在AfterClass加driver.quit()
2. error: Failed to start an Appium session, err was: Error: Command failed: C:Windowssystem32cmd.exe /s /c "D:android-sdk-windowsplatform-toolsadb.exe -s adb server version (32) doesn't match this client (36); killing…
wait-for-device"
error: could not installsmartsocketlistener: cannot bind to 127.0.0.1:5037:
没有链接上手机或者模拟器,请确认已经连接成功,重新链接
3. error: Android devices must be of API level 17 or higher. Please change your device to Selendroid or upgrade Android on your device.
手机系统低于4.2,appium不支持4.2.2以下的系统,请换一个手机或者模拟器来测试。
4. Error: Permission to start activity denied.
**activity在清单文件里面没添加Android:exported="true"的话,你不能直接打开对应的activity,需要从启动页activity打开。
exported属性就是设置是否允许activity被其它程序调用**
5. error: Failed to start an Appium session, err was: Error: Activity used to start app doesn't exist or cannot ve launched! Make usre it exists and is launchable activity
要打开的activity不存在,activity路径错误,改为完整正确的activity路径
6. error: Failed to start an Appium session, err was: Error: 'java - version' failed. Error: Command failed: C:Windowssystem32cmd.exe /s /c "java -version"
Java版本错误,请安装最新的版本。
7.> info: [debug] Error: Command failed: C:Windowssystem32cmd.exe /s /c "D:android-sdk-windowsplatform-toolsadb.exe -s 8806a0b0 shell "echo 'ready'"error: unknown host service
链接手机失败,重新链接手机即可,我就是重新拔插了一下usb
Error: Command failed: C:Windowssystem32cmd.exe /s /c "D:android-sdk-windowsplatform-toolsadb.exe -s 8806a0b0 shell "echo 'ping'""
error: unknown host service
adb被突然占用导致,例如你在运行用例的时候运行了模拟器。
8. UIAutomatorViewer提示: Unable to connect to adb. Check if adb is installed correctly
解决,sdk升级到了25产生的问题。
解决方法:
将adb.exe复制一份到uiautomatorviewer.bat目录下
修改uiautomatorviewer.bat文件最后一行(改binddir=%prog_dir%为自己的platform-tools本地路径)
9 error: Failed to start an Appium session, err was:INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install io.appium.settings without first uninstalling
When you are at final step to execute test automation script for mobile app testing on a mobile emulator or a virtual device or a real device, you might observe that script execution fails with different kinds of errors, In context to current article you will look at the error and solutions for: INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install io.appium.settings without first uninstalling.
Error in Appium Server:
1
2
3
4
5
6
7
8
Error: Command failed: C:Windowssystem32cmd.exe /s /c
"C:Users{User}-toolsadb.exe -s
emulator-5554 install
"C:Program Files (x86)Appium ode_molesappiumuildsettings_apksettings_apk-debug.apk""
> Failed to install C:Program Files (x86)Appium ode_molesappiumuildsettings_apk
settings_apk-debug.apk: Failure [INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install
io.appium.settings without first uninstalling.]
Error in Android studio run console:
1
2
3
4
5
6
7
8
9
org.openqa.selenium.SessionNotCreatedException: A new session could not be created.
(Original error: Command failed: C:Windowssystem32cmd.exe /s /c
"C:Users{User}-toolsadb.exe -s emulator-5554 install
"C:Program Files (x86)Appium ode_molesappiumuildsettings_apksettings_apk-debug.apk""
Failed to install C:Program Files (x86)Appium ode_molesappiumuildsettings_apk
settings_apk-debug.apk: Failure [INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install
io.appium.settings without first uninstalling.]
) (WARNING: The server did not provide any stacktrace information)
Command ration or timeout: 0 milliseconds
For the first time when you execute the script itmight pass, but it will fail with above error when you try to execute the same or any other script multiple times. Or when your test script execution fails on the first attempt for some other reason, and when you fix it and execute it again, you might encounter this new issue.
原因:
The reason for this error is that Appium installs 2 mobile applications before executing the script.
1. io.appium.settings
2. io.appium.unlock
Theseare the supportive mobile applications appium utilizes to execute the test automation script in Mobile Emulator or virtual device or a real mobile device.
Ideally Appium should remove these files every time at the end of the script execution or termination, if it is intends to install themevery time a script is executed, or it should conditionally install these apps / apksto the mobile emulator or mobile device.
In your mobile emulator / Virtual Device / Real device, the 2 mobile applications appear as below:
There are multiple ways to troubleshootthis error and go ahead for asuccessful test script execution.
解决办法
Solution 1: ADB's uninstall command to remove the files.
You can open command prompt, assuming that you already had set the environment variables for ANDROID_HOME and Path variables for sdk tools and platform tools.
And execute commands as shown below:
Solution 2: Uninstall manually
You can open the mobile emulator / virtual device / real device and go to apps and uninstall them.
Solution 3: Write code as part of your test automation script.
As part of your selenium test automation script, you could write instructions to execute the commands provided in solution 1 above, so that this issue would not arise.
Hope this article has been helpful and you are able to proceed further with script execution.
Request to kindly share any of your queries in form of comments, we would try our best to provide any solution for you.
10.出错信息里含有"ps 'uiautomator',具体信息未 A new session could not be created. (Original error: Command failed: C:Windowssystem32cmd.exe /s /c "C:Userssxie-toolsadb.exe -s emulator-5554 shell "ps 'uiautomator'""
android-appium: A new session could not be created
junitexceptionandroidappium自动化
detail log:
org.openqa.selenium.SessionNotCreatedException: A new session could not be created. (Original error: Command failed: C:Windowssystem32cmd.exe /s /c "C:Userssxie-toolsadb.exe -s emulator-5554 shell "ps 'uiautomator'""
) (WARNING: The server did not provide any stacktrace information)
Command ration or timeout: 0 milliseconds
Build info: version: '3.4.0', revision: 'unknown', time: 'unknown'
System info: host: 'WL00070299', ip: '10.110.12.39', os.name: 'Windows 8.1', os.arch: 'x86', os.version: '6.3', java.version: '1.8.0_40'
Driver info: driver.version: AndroidDriver
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect..newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:215)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:167)
at io.appium.java_client.remote.AppiumProtocolHandShake.createSession(AppiumProtocolHandShake.java:161)
at io.appium.java_client.remote.AppiumProtocolHandShake.createSession(AppiumProtocolHandShake.java:76)
at io.appium.java_client.remote.AppiumCommandExecutor.doExecute(AppiumCommandExecutor.java:111)
at io.appium.java_client.remote.AppiumCommandExecutor.execute(AppiumCommandExecutor.java:162)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:637)
at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:42)
at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1)
at io.appium.java_client.android.AndroidDriver.execute(AndroidDriver.java:1)
at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:250)
at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:236)
at org.openqa.selenium.remote.RemoteWebDriver.(RemoteWebDriver.java:137)
at io.appium.java_client.DefaultGenericMobileDriver.(DefaultGenericMobileDriver.java:38)
at io.appium.java_client.AppiumDriver.(AppiumDriver.java:88)
at io.appium.java_client.AppiumDriver.(AppiumDriver.java:112)
at io.appium.java_client.android.AndroidDriver.(AndroidDriver.java:73)
at com.sky.demo.ContactTest.setUp(ContactTest.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schele(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
==========================================
直接在cmd中执行"C:Windowssystem32cmd.exe /s /c "C:Userssxie-toolsadb.exe -s emulator-5554 shell "ps 'uiautomator'""
bad pid 'uiautomator'", 报错: bad pid 'uiautomator'
代码内容为
public class ContactTest {
private AndroidDriver driver;
@Before
public void setUp() throws Exception {
//设置apk的路径
File classpathRoot = new File(System.getProperty("user.dir"));
File appDir = new File(classpathRoot, "apps");
File app = new File(appDir, "ContactManager.apk");
}
解决办法:
resolved by this way:
adb.js(C:Program Files (x86)Appium
ode_molesappium
ode_molesappium-adblibadb.js) 中1035 行this.shell("ps '" + name + "'", function (err, stdout) {
对应执行的指令是ps 'uiautomator', Android7不支持这个指令格式,所以执行结果是bad pid 'uiautomator'
目前Appium未对此进行处理,所以需要修改此指令的执行方式
即将
this.shell("ps '" + name + "'", function (err, stdout) {
if (err) return cb(err);
替换成
this.shell_grep("ps", name, function (err, stdout) {
if (err) {
logger.debug("No matching processes found");
return cb(null, []);
}
并增加上面用到的shell_grep函数:
ADB.prototype.shell_grep = function (cmd, grep, cb) {
if (cmd.indexOf('"') === -1) {
cmd = '"' + cmd + '"';
}
var execCmd = 'shell ' + cmd + '| grep ' + grep;
this.exec(execCmd, cb);
};
11.Android 7.0系统的手机无法执行appium脚本的问题
AppiumAppium 版本 1.4.16,Android 设备固件 7.x,执行脚本时,报错使用语言:python报错如下:
WebDriverException: Message: A new session could not be created. (Original error: Could not extract PIDs from ps output. PIDS: [], Procs: ["bad pid 'uiautomator'"])
这个是因为appium版本1.4.16使用的uiatumator1.0不支持的原因导致?如果不升级appium版本,是否有解决方案?
解决办法
uiautomator1.0应该是不支持7.0,不升版本就换用uiautomator2.0吧,或者用下面的改脚本的方法使用。
解决Android 7.0系统的手机无法执行appium脚本的问题,改问题的具体解决方法如下:
找到appium的安装目录下的adb.js文件,windows版本的目录如下:Appium
ode_molesappium
ode_molesappium-adblib
2、打开adb.js,手动修改该文件下的内容,此方法我已经试验成功。
adb.js 中1035 行this.shell("ps '" + name + "'", function (err, stdout) {
对应执行的指令是ps 'uiautomator', Android7不支持这个指令格式,所以执行结果是bad pid 'uiautomator'
目前Appium未对此进行处理,所以需要修改此指令的执行方式
即将
this.shell("ps '" + name + "'", function (err, stdout) {
if (err) return cb(err);
替换成
this.shell_grep("ps", name, function (err, stdout) {
if (err) {
logger.debug("No matching processes found");
return cb(null, []);
}
并增加上面用到的shell_grep函数:
ADB.prototype.shell_grep = function (cmd, grep, cb) {
if (cmd.indexOf('"') === -1) {
cmd = '"' + cmd + '"';
}
var execCmd = 'shell ' + cmd + '| grep ' + grep;
this.exec(execCmd, cb);
};
网上还有如下的修改解决办法:以下我未试验。
ADB.prototype.getPIDsByName = function (name, cb) {
logger.debug("Getting all processes with '" + name + "'");
this.shell("ps '" + name + "'", function (err, stdout) {
if (err) return cb(err);
stdout = stdout.trim();
var procs = [];
var outlines = stdout.split("
");
outlines.shift(); //在该处添加此行代码
3、重启appium
技巧
1.每次测试都重新安装app
为capabilities色设置noReset为true
capabilities.setCapability("noReset", true);
2.中文乱码
这都是编码问题:
1.方法1:
Android Studio修改文件编码的方法,最底部的UTf-8,点击选GBK就可以了,reload文件。(ps:先把文件内容全选复制一下再转换编码,再粘贴,不然文件内容就变乱码了)
2.方法2:
用的是原来的UTF-8编码,然后在测试mole的build.gradle里面添加三行代码
tasks.withType(JavaCompile){
options.encoding = 'UTF-8'
}
3.清除编辑框EditText内容
这个问题好像是看手机系统的,我之前的手机就会出现sendKeys的时候没有全选去掉本来的内容,现在都会自动全选覆盖了,这个也不算问题了。
/**
* 逐字删除编辑框中的文字
* @param element 文本框架控件
*/
public void clearText(AndroidElement element){
String className = element.getClass().getSimpleName();
if (className.equals("EditText")){
String text = element.getText();
//跳到最后
driver.pressKeyCode(KEYCODE_MOVE_END);
for (int i = 0; i < text.length(); i ++){
//循环后退删除
driver.pressKeyCode(BACKSPACE);
}
}else {
print("不是文本输入框架,无法删除文字");
}
}
1
4.点击输入法键盘的回车搜索
方法1:切换输入法
利用adb命令先切换为自己的输入法,按了搜索再切换为appium的输入法
查看当前手机的输入法
cmd执行下面的的代码
adb shell ime list -s
可以看到类似下面的结果,
C:UsersLITP>adb shell ime list -s
com..input_mi/.ImeService
com.sohu.inputmethod.sogou.xiaomi/.SogouIME
io.appium.android.ime/.UnicodeIME
C:UsersLITP>
执行adb命令
先写好一个执行cmd的方法
/**
* 执行adb命令
* @param s 要执行的命令
*/
private void excuteAdbShell(String s) {
Runtime runtime=Runtime.getRuntime();
try{
runtime.exec(s);
}catch(Exception e){
print("执行命令:"+s+"出错");
}
}
在需要搜索的时候执行下面的代码,切换的输入法用自己查看列表的输入法内容,我这里是搜狗输入法
//使用adb shell 切换输入法-更改为搜狗拼音,这个看你本来用的什么输入法
excuteAdbShell("adb shell ime set com.sohu.inputmethod.sogou.xiaomi/.SogouIME");
//再次点击输入框,调取键盘,软键盘被成功调出
clickView(page.getSearch());
//点击右下角的搜索,即ENTER键
pressKeyCode(AndroidKeyCode.ENTER);
//再次切回 输入法键盘为Appium unicodeKeyboard
excuteAdbShell("adb shell ime set io.appium.android.ime/.UnicodeIME");
Ⅳ appium长时间运行内存溢出解决方式
下班的时候开始执行,第二天来的时候发现没跑完,appium各种异常,后来看了appium的log发现是内存溢出了,报错如下:
<--- Last few GCs --->
[68480:0x102845000] 22938475 ms: Mark-sweep 4085.6 (4104.9) -> 4085.6 (4104.9) MB, 54.7 / 0.0 ms (average mu = 0.957, current mu = 0.000) last resort GC in old space requested
[68480:0x102845000] 22938532 ms: Mark-sweep 4085.6 (4104.9) -> 4085.6 (4104.4) MB, 56.5 / 0.0 ms (average mu = 0.922, current mu = 0.000) last resort GC in old space requested
<--- JS stacktrace --->
==== JS stack trace =========================================
0: ExitFrame [pc: 0x57e8fedbe3d]
Security context: 0x078c1981e6e9 <JSObject>
1: test [0x78c19809561](this=0x078c4a932069 >,0x078c1f607219 )
2: truncate [0x78ccb9c31a9] [/Applications/Appium.app/Contents/Resources/app/node_moles/appium/node_moles/lodash/lodash.js:~15070] [pc=0x57e90fd3b85](this=0x078c14...
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
1: 0x10003d035 node::Abort() [/usr/local/bin/node]
2: 0x10003d23f node::OnFatalError(char const*, char const*) [/usr/local/bin/node]
3: 0x1001b8e15 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
4: 0x100586d72 v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/usr/local/bin/node]
5: 0x100590274 v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node]
6: 0x100561b25 v8::internal::Factory::NewRawOneByteString(int, v8::internal::PretenureFlag) [/usr/local/bin/node]
7: 0x100693c38 v8::internal::String::SlowFlatten(v8::internal::Handle, v8::internal::PretenureFlag) [/usr/local/bin/node]
8: 0x100779c08 v8::internal::RegExpImpl::IrregexpExec(v8::internal::Handle, v8::internal::Handle, int, v8::internal::Handle) [/usr/local/bin/node]
9: 0x10081c670 v8::internal::Runtime_RegExpExec(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node]
10: 0x57e8fedbe3d
Abort trap: 6
于是上网找了以下的几种方式:
1.使用终端运行appium ,并且把appium内存扩展到4096MB
我的是:node --max_old_space_size=4096 /Applications/Appium.app/Contents/Resources/app/node_moles/appium/build/lib/main.js -p 4723
2.logcat.js文件注释push
附上当时eclipse的报错:
1、
org.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. Original error: Could not proxy command to remote server. Original error: Error: read ECONNRESET
Build info: version: '3.12.0', revision: '7c6e0b3', time: '2018-05-08T14:04:26.12Z'
System info: host: 'ruby-Mac.local', ip: 'fe80:0:0:0:69:1eb2:920:7aaf%en0', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.14.6', java.version: '12.0.2'
Driver info: io.appium.java_client.ios.IOSDriver
2、
org.openqa.selenium.NoSuchSessionException: Session does not exist
Build info: version: '3.12.0', revision: '7c6e0b3', time: '2018-05-08T14:04:26.12Z'
System info: host: 'ruby-Mac.local', ip: 'fe80:0:0:0:69:1eb2:920:7aaf%en0', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.14.6', java.version: '12.0.2'
Driver info: io.appium.java_client.ios.IOSDriver
Ⅵ Appium运行java脚本,报错Activity used to start app doesn't exist or cannot be launched!Make sure
1、在你的程序中,初始化appium设置的appActivity这项,值不对,不是当前被测app启动时调用的activity
可以通过命令行aapt mp badging D:xxx.apk,可以检查到此apk的packageName和activityName
要求先进去androidSDK的build-tools目录下
Ⅶ appium+java处理alertDialog失败
知识点:
1、利用反射,阻止AlertDialog每次的dismiss事件;
在使用AlertDialog的时候,我们设置positive,negative和neutral的button,在点击之后,即使不手动调用dismiss方法,系统都会自动的帮我们dismiss掉了。
但是我这里可能点击了之后,还有一些时间比较长的工作处理之后,才能够dismiss掉此AlertDialog;那么这就是一个问题了。我们先直接看怎么来阻止这个系统的dismiss事件。
话不多述,我们直接先上代码,看看如何操作的,然后在稍微看看源码,一探究竟:
首先是来一个button,设置点击事件,弹出dialog
[java]view plain
@Override
publicvoidonClick(Viewv){
switch(v.getId()){
caseR.id.btn_rDialog:
showDialog();
break;
}
}
然后在activity里头,创建showDialog方法,如下:
[java]view plain
/**
*利用反射,阻止dialog点击确定或者取消按钮,总是会使得dialog消失的结果
*/
voidshowDialog(){
AlertDialogalertDialog=newAlertDialog.Builder(this)
.setTitle("title")
.setMessage("content")
.setIcon(R.drawable.__leak_canary_icon)
.setPositiveButton(R.string.ok,
newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
//就算阻止了dialog的dismiss事件,这里调用dismiss也还是可以dismiss掉dialog的
//dialog.dismiss();
}
})
.setNegativeButton(R.string.cancel,newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
dialog.dismiss();
}
}).create();
alertDialog.setCanceledOnTouchOutside(false);
setDialogCancelable(alertDialog);
//setDialogIsCanceled(alertDialog,false);
/*显示对话框*/
alertDialog.show();
}
/**
*通过重新设置一个button处理类,达到点击确定按钮不dismiss掉dialog的效果
*
*@paramalertDialogalertDialog
*/
voidsetDialogCancelable(AlertDialogalertDialog){
try{
Fieldfield=alertDialog.getClass().getDeclaredField("mAlert");
field.setAccessible(true);
/*获得mAlert变量的值*/
Objectobj=field.get(alertDialog);
field=obj.getClass().getDeclaredField("mHandler");
field.setAccessible(true);
/*修改mHandler变量的值,使用新的ButtonHandler类*/
field.set(obj,newIButtonHandler(alertDialog));
}catch(Exceptione){
e.printStackTrace();
}
}
/**
*通过获取mShowing字段,修改它的值,达到点击确定按钮不dismiss掉dialog的效果
*但是好像是没有用的,不起效果
*
*@paramalertDialogalertDialog
*@=此dialog已经关闭了,反之则是为关闭
*/
voidsetDialogIsCanceled(AlertDialogalertDialog,booleanisCanceled){
try{
/*这里有一个层级关系需要记住,看字段是属于父类,还是属于父类的父类*/
Fieldfield=alertDialog.getClass()
.getSuperclass().getSuperclass().getDeclaredField("mShowing");
field.setAccessible(true);
/*将mShowing变量设为false,表示对话框已关闭*/
field.set(alertDialog,isCanceled);
alertDialog.dismiss();
}catch(Exceptione){
e.printStackTrace();
}
}
还有涉及到一个IButtonHandler的类
[java]view plain
packagecom.yaojt.ui.reflect;
importandroid.content.DialogInterface;
importandroid.os.Handler;
importandroid.os.Message;
importjava.lang.ref.WeakReference;
/**
*desc:自定义的dialog点击按钮事件处理机制
*<p>
*author:kuyu.yaojt(tanksu)
*<p>
*email:[email protected]
*<p>
*date:17/3/7
*/
{
/*使用弱引用,避免内存泄漏*/
privateWeakReference<DialogInterface>mDialog;
/**
*构造方法
*
*@paramdialogdialog
*/
publicIButtonHandler(DialogInterfacedialog){
mDialog=newWeakReference<>(dialog);
}
@Override
publicvoidhandleMessage(Messagemsg){
switch(msg.what){
caseDialogInterface.BUTTON_POSITIVE:
caseDialogInterface.BUTTON_NEGATIVE:
caseDialogInterface.BUTTON_NEUTRAL:
((DialogInterface.OnClickListener)msg.obj).onClick(mDialog.get(),msg.what);
break;
/**
*AlertController,最终都会调用以下代码,并且传入MSG_DISMISS_DIALOG标志
*//
mHandler.obtainMessage(IButtonHandler.MSG_DISMISS_DIALOG,mDialog)
.sendToTarget();
然后到下面代码
//以下是原始的ButtonHandler类可以看到最后的最后,都会走到这一个入口里去了
导致所有的dialog方法都会被dismiss掉,只要拦截这个就可以了。做法就是重新定义一个ButtonHandler
设置取代原来的ButtonHandler实例即可。有一点不好那就是会影响到所有的dialog。
但是我们在确定监听里头是调用dismiss,是可以dismiss掉dialog的
其实就是不要dismiss的这个方法入口
{
//ButtonclickshaveMessage.whatastheBUTTON{1,2,3}constant
privatestaticfinalintMSG_DISMISS_DIALOG=1;
privateWeakReference<DialogInterface>mDialog;
publicIButtonHandler(DialogInterfacedialog){
mDialog=newWeakReference<>(dialog);
}
@(Messagemsg){
switch(msg.what){
caseDialogInterface.BUTTON_POSITIVE:
caseDialogInterface.BUTTON_NEGATIVE:
caseDialogInterface.BUTTON_NEUTRAL:
((DialogInterface.OnClickListener)msg.obj).onClick(mDialog.get(),msg.what);
break;
caseMSG_DISMISS_DIALOG:
((DialogInterface)msg.obj).dismiss();
}
}
}
*/
}
}
}
代码就是以上这些,都有注释的了。
反射确实挺好用的,可以在运行时动态地加载一个类,然后调用执行类里面的方法,在高级开发中,这个是必须的技能,要好好学习。
另外,这个也是有风险的做法,其他人也可以使用这个来获取到你的类的相关信息,然后做一些坏事什么的。
阅读全文
Ⅷ appium + java 怎么实现滑动页面到某个元素的位置 · TesterHome
public class MyAndroidDriver extends AndroidDriver {
public MyAndroidDriver(URL remoteAddress, Capabilities desiredCapabilities) {
super(remoteAddress, desiredCapabilities);
}
static String UiScrollable(String uiSelector) {
return "new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView("
+ uiSelector + ".instance(0));";
}
/**
* 滑动到某元素
* @param uiScrollables 符合UiScrollable的string串
* @return
*/
public WebElement scrollToElement(String uiScrollables ) {
String uiScrollables = UiScrollable(uiScrollables );
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
return (uiScrollables);
}
}
看了AndroidDriver源码中scrollTo方法之后的思路,当然了,这边的uiScrollables 需要构造,例如:new UiSelector().className(\"android.widget.TextView\").textContains(\"测试测试\").resourceId(\"com.xx.xxx:id/package_exchange_textview\")