I have a simple requirement to run a set of files on url on MediaPlayer.
I am writing a script to do this.
There is a variable mediapath in MainActivity.java which takes url path.
Is it possible to give this variable url value using android monkeyrunner script.
currently there is no device.set function to set the particular value.
My script is:
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
device = MonkeyRunner.waitForConnection()
package = 'com.example.diagplayer'
activity = 'com.example.diagplayer.MainActivity'
file = open('filelist.txt', 'r')
rows = file.readlines()
for file_name in rows:
uri=file_name
extra = {}
extra['URI']=uri
print(uri)
runComponent = package + '/' + activity
device.set("MediaPath","uri")//getting error here
device.touch(100, 350, MonkeyDevice.DOWN)
device.touch(10,350, 'DOWN_AND_UP')
It would be impossible for a device.set() method to set a variable in a running Activity, which I think is your intention.
However you can set the extras of the Intent with the desired values (as you did) and then make your Activity extract them and set the variables.
Related
I want to pull a file from my android device through an adb command from my macOS application.
Everything works perfect with the code below, except when the name of the file I want to pull contains special characters like german umlauts (äöüÄÖÜ).
I get this error:
adb: error: failed to stat remote object '/storage/emulated/0/Download/Böse': No such file or directory.
But when I use the command adb pull /storage/emulated/0/Download/Böse ~/Desktop from within the Terminal.app, the file will be pulled to my computer.
The strange thing here is that if I copy the substring /storage/emulated/0/Download/Böse from the Xcode console output, the command is also not working within the Terminal.app until I delete the ö and replace it with an ö from my keyboard input.
I tried replacing the ö with the unicode representation \u{00f6}, but this has no effect (but the console output still shows an ö but the 'wrong' encoded one.
// Configure task.
let task = Process()
task.launchPath = "~/Library/Android/sdk/platform-tools/adb"
task.arguments = ["pull", "/storage/emulated/0/Download/Böse", "~/Desktop"]
// Configure pipe.
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
task.launch()
// Run task.
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)
task.waitUntilExit()
// adb: error: failed to stat remote object '/storage/emulated/0/Download/Böse': No such file or directory
print(output)
I found the following in the documentation, how the Process handles the arguments that I provide:
The NSTask object converts both path and the strings in arguments to appropriate C-style strings (using fileSystemRepresentation) before passing them to the task via argv[] . The strings in arguments do not undergo shell expansion, so you do not need to do special quoting, and shell variables, such as $PWD, are not resolved.
It seems like I am not the only one with this problem, and I found this workaround:
How to work around NSTask calling -[NSString fileSystemRepresentation] for arguments, but I was not able to make it work with Swift.
As a workaround I am now writing my adb command to a file and execute it from a bash command in my application.
let source = "/storage/emulated/0/Download/Böse"
let destination = "~/Desktop"
guard let uniqueURL = URL(string: destination + "/" + ProcessInfo.processInfo.globallyUniqueString) else { return }
// Write command to file
let scriptContent = "#!/bin/bash\n~/Library/Android/sdk/platform-tools/adb pull -a \"" + source + "\" \"" + destination + "\""
try? scriptContent.write(to: uniqueURL, atomically: false, encoding: .utf8)
// Configure task.
let task = Process()
task.environment = ["LC_ALL": "de_DE.UTF-8", "LANG": "de_DE.UTF-8"]
task.launchPath = "/bin/bash"
task.arguments = [uniqueURL.path]
// Configure pipe.
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
try? task.run()
// Run task.
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)
task.waitUntilExit()
print(output)
Even though this is working for now, it is not a satisfactory solution as it is not very elegant and not efficient too, so any improvements or better answers are welcome.
I am writing testcases in python script for android application using appium. I want to perform click/tap operation in a particular bounds/co-ordinates. but I am not able to perform it.Can any one tell me how to do it.
class firstTest(unittest.TestCase):
def tearDown(self):
"Tear down the test"
self.driver.quit()
def test_single_player_mode(self):
time.sleep(5)
element = self.driver.find_element_by_name("Enter your Email ID or User name")
element.send_keys("username")
element = self.driver.find_element_by_name("Let's get started!")
element.click()
time.sleep(5)
Till 'Lets get started it is working fine. After it in UI, I don't have any element name or id. I have only particular bound to click the element. I want to click on bound [918,154][1086,324] resource ID for above bound is "com.abc.android.cap:id/friends_selection_list" Please tell me how to do after it.
I hope you have content-description for this element. In that case you can tap on it by using it and tap method in TouchAction class.
ele = self.driver.find_element_by_accessibility_id('content-description of your element')
action = TouchAction(self.driver)
action.tap(ele).perform()
U can use Xpath of that element, for finding xpath u will need appium inspector, which is supported in MAC OSX only, so you have to use an mac and configure Android SDK and Appium on MAC in order to get it working.
Code will be like this :
#-*- coding: utf-8 -*-
__author__ = 'chetan.krishna'
import os
import time
import unittest
from time import sleep
from appium import webdriver
from pylab import *
from teamcity import is_running_under_teamcity
from teamcity.unittestpy import TeamcityTestRunner
import logging
# Returns absolute path relative to this file
PATH = lambda p: os.path.abspath(
os.path.join(os.path.dirname(__file__), p)
)
class AvavntiAndroidTests(unittest.TestCase):
def setUp(self):
desired_caps = {}
# Specify platform below(Android, iOS)
desired_caps['platformName'] = 'Android'
# Specify OS version(Settings->About phone -> android version)
desired_caps['platformVersion'] = '4.4.4'
# Obtain the Device name from Adb[For Android](Terminal Command: "adb devices")
desired_caps['deviceName'] = '4d0081004c8741a9'
desired_caps['noReset'] = False
# Specify the path to Application
desired_caps["app"] = PATH('AvantiMarket_v1.4.apk')
# Wait for email login activity to appear
desired_caps["appWaitActivity"]= ('com.android.avantimarket.ui.activity.EmailLoginActivity')
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
def tearDown(self):
# end the session
self.driver.quit()
def test_Avanti(self):
# wait for the login screen to appear
self.driver.implicitly_wait(20)
# set values for plotting pass and fail results
nPass = 0
nFail = 0
print('Checking login for registered user')
# Logging in as indiaone#avantilab.org
elf.driver.implicitly_wait('20')
print('Trying to login with abc#abc.org')
self.driver.find_element_by_xpath('//UIAApplication[1]/UIAWindow[2]/UIATextField[1]').send_keys('abc#abc.org.org')
self.driver.find_element_by_xpath('//UIAApplication[1]/UIAWindow[2]/UIASecureTextField[1]').send_keys('12345678')
self.driver.hide_keyboard()
self.driver.implicitly_wait(10)
self.driver.find_element_by_xpath('//UIAApplication[1]/UIAWindow[2]/UIAButton[3]').click()
time.sleep(20)
self.driver.implicitly_wait(99)
try:
self.driver.find_element_by_xpath('//UIAApplication[1]/UIAWindow[2]/UIASecureTextField[1]')
except :
print('Login failed, please check credentials and network')
else:
print('Login successful, creating pin')
self.driver.find_element_by_xpath('//UIAApplication[1]/UIAWindow[2]/UIASecureTextField[1]').send_keys('1')
self.driver.find_element_by_xpath('//UIAApplication[1]/UIAWindow[2]/UIASecureTextField[2]').send_keys('1')
self.driver.find_element_by_xpath('//UIAApplication[1]/UIAWindow[2]/UIASecureTextField[3]').send_keys('1')
self.driver.find_element_by_xpath('//UIAApplication[1]/UIAWindow[2]/UIASecureTextField[4]').send_keys('1')
self.driver.find_element_by_xpath('//UIAApplication[1]/UIAWindow[2]/UIASecureTextField[5]').send_keys('1')
self.driver.find_element_by_id('com.android.avantimarket:id/m_emailTextField').send_keys('abc#abc.org.org')
self.driver.back()
nPass= nPass+1
self.driver.implicitly_wait(20)
self.driver.find_element_by_id('com.android.avantimarket:id/m_passwordTextField').send_keys('12345678')
nPass= nPass+1
self.driver.back()
self.driver.implicitly_wait(10)
self.driver.find_element_by_name('SIGN IN').click()
self.driver.implicitly_wait(30)
time.sleep(5)
# validating for successful login
try:
self.driver.find_element_by_id('com.android.avantimarket:id/create_pin_fields_container')
print('Login successful')
nPass= nPass+1
except:
print('Login failed')
nFail = nFail + 1
else:
# Creating pin required for login
print('Creating Pin for user')
self.driver.find_element_by_id('com.android.avantimarket:id/create_pin_fields_container').send_keys('1111')
self.driver.find_element_by_id('com.android.avantimarket:id/reEnter_pin_fields_container').send_keys('1111')
self.driver.back()
self.driver.implicitly_wait(20)
self.driver.find_element_by_id('com.android.avantimarket:id/m_saveButton').click()
self.driver.implicitly_wait(10)
self.driver.find_element_by_id('com.android.avantimarket:id/btn_cominsoon_Yes').click()
self.driver.implicitly_wait(10)
time.sleep(8)
You can achieve this with Touch Actions.
action = TouchAction(self.driver)
action.tap(element=None, x=100, y=600, count=2).perform()
Or like this:
self.driver.tap([(100,600)], 500)
Where the first variable is a list of up to 5 x,y coordinates(e.g. self.driver.tap([(495,757), (200,500)], 500). The last number is duration of the tap.
I would like to start a background SL4A script (on a remote device) from within a different SL4A script. I can launch a script from a terminal by running something like this:
$ am start -a \
com.googlecode.android_scripting.action.LAUNCH_BACKGROUND_SCRIPT -n \
com.googlecode.android_scripting/.activity.ScriptingLayerServiceLauncher -e \
com.googlecode.android_scripting.extra.SCRIPT_PATH /sdcard/sl4a/scripts/main.py
I can't translate this into a startActivity call in Python.
The answer to a different question on opening a Twitter client works nicely, but I don't know how to extend that code. For example, how would you add a script path, and where would you put the line com.googlecode.android_scripting/.activity.ScriptingLayerServiceLauncher?
This function will launch any SL4A script from inside another one.
The first argument should be a path to the script you want to launch. The script can be in any language you have an interpreter installed for.
The second argument is optional and should be a bool. It defaults to False. It controls whether the terminal will be visible, so you can see output and errors. It does not effect whether the script has a UI or not.
from android import Android
droid = Android()
def launch_script(path, visible=False):
visibilty = 'FORE' if visible else 'BACK'
activity = 'com.googlecode.android_scripting.action.LAUNCH_{0}GROUND_SCRIPT'.format(visibilty)
extras = {'com.googlecode.android_scripting.extra.SCRIPT_PATH': path}
packagename = 'com.googlecode.android_scripting'
classname = 'com.googlecode.android_scripting.activity.ScriptingLayerServiceLauncher'
intent = droid.makeIntent(activity, None, None, extras, None, packagename, classname).result
droid.startActivityIntent(intent)
There's a gist for this code here.
After many, many failed attempts, I now have this working in Ruby - I had an easier time generating the JSON extras this way than in Python.
Important!
In the command-line version, you call on "com.googlecode.android_scripting/.activity.ScriptingLayerServiceLauncher"
From within a script, this is called as "com.googlecode.android_scripting.activity.ScriptingLayerServiceLauncher", without the slash. Leaving in the slash crashes sl4a.
[code]
require 'android'
require 'json/pure'
d=Android.new
script = '/sdcard/sl4a/scripts/YOUR_SCRIPT'
data = {"com.googlecode.android_scripting.extra.SCRIPT_PATH"=>script}
extras = JSON.generate(data)
d.startActivity('com.googlecode.android_scripting.action.LAUNCH_BACKGROUND_SCRIPT','','',data,true,'com.googlecode.android_scripting','com.googlecode.android_scripting.activity.ScriptingLayerServiceLauncher')
[/code]
I hope this helps!
Here's what I need to do. I have 2 devices which I need to test using monkeyrunner. It is an automated test using python and monkeyrunner. I want to execute the test simultaneously for the 2 devices so I thought of using thread.
here's the code
import threading
import datetime import os, sys
import ConfigParser from com.android.monkeyrunner
import MonkeyRunner, MonkeyDevice,MonkeyImage from datetime
import datetime import hashlib from java.net
import SocketException from com.ziclix.python.sql
import zxJDBC
def UseThread(data1, data2, data3, devID, Code, ScreenshotRef,
logFile):
device = MonkeyRunner.waitForConnection(10, devID)
'threaded code'
'initialization'
file = open(os.path.dirname(os.path.realpath(file)) +
'\Samples.txt','r') while 1:
while 1:
line = file.readline()
if not line:
print 'Done!'
break
else:
line
val=line.split('\t')
data1 = val[0]
data2 = val[1]
data3 = val[2]
threads = []
for Code in cp.options('p'):
devID = cp.get('product',Code).strip()
ScreenshotRef = cp.get('source','ScreenshotRef') + '\\' + prodCode.upper()
logFile = outputFolder + '\\' + prodCode.upper() + '\\logs.txt'
t=threading.Thread(target=UseThread,args=(data1, data2, data3, devID, prodCode, ScreenshotRef, logFile))
threads.append(t)
t.start()
for i in range(0,len(threads)):
threads[i].join()
The problem is this. When the while loops finish one run and proceed to 2nd run, the code hangs in the part when monkeyrunner is waiting for connection. To be exact, this is the part where it stops
device = MonkeyRunner.waitForConnection(10, devID)
the message says "Monkey command wake".
I assume that the problem has something to do with the connection, not with the thread because I tried to print something before that line which makes a connection and it works.
Is there an issue making a connection when you have already made one? do I need to close the previous connection first?
MonkeyRunner waitForConnection works only for one device. You cannot run this twice. You can run from another instance
I wanto to inject mouse event into an running application ( like clicking and moving the mouse pointer). Is it possible with monkey tool ? If yes, can you give me a roadmap about how to use monkey tool in android application development platform ?
I am driving apps in emulators using Monkey.
I have a Python script that gets fed to the monkeyrunner tool. This is largely coming from the sample on the Android developer website.
It is possible to invoke activities and respond to them.
For instance here I invoke an activity, which in turn runs another one; at that point I enter 4 digits and 'click' the coordinates 100,400 on the screen corresponding to the 'ok' button.
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
if __name__ == "__main__":
# Connects to the current device, returning a MonkeyDevice object
device = MonkeyRunner.waitForConnection()
# Installs the Android package. Notice that this method returns a boolean, so you can test
# to see if the installation worked.
# device.installPackage('myproject/bin/MyApplication.apk')
# sets a variable with the package's internal name
package = 'com.mypackage'
# sets a variable with the name of an Activity in the package
activity = 'com.mypackage.myactivity'
# sets the name of the component to start
runComponent = package + '/' + activity
# Runs the component
device.startActivity(component=runComponent)
if device.getProperty('am.current.comp.class') == 'com.mypackage.anotheractivity':
device.type('0000')
# Click the 'Enter' button on screen at coordinates 100,400
device.touch(100, 600, 'DOWN_AND_UP')
I hope that helps.