Ⅰ 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\")