smk
smk

Reputation: 5842

Monkeyrunner parallel execution on devices

Im trying to use monkeyrunner to configure multiple tablets attached to the same pc. The code works ok for 1 tablet but the moment I try to run it on multiple tablets it all blows up.

Here is the code which invokes the monkeyrunner python file. mr1.py is the monkeyrunner file I am trying to run.

import sys

import util
import threading
import commands
class myThread (threading.Thread):
    def __init__(self, threadID, deviceId,env_path):
        self.threadID = threadID
        self.deviceId = deviceId
        self.path = env_path
        threading.Thread.__init__(self)
    def run(self):
        print "Starting " + self.deviceId
        ret = commands.getstatusoutput(self.path+"monkeyrunner mr1.py "+self.deviceId)
        print ret
        print "Exiting " + self.deviceId

def main():
    connected_devices = util.get_connected_devices()
    count = 0
    path = "/Users/ad/Desktop/android-sdk-macosx/tools/"
    for device in connected_devices:
        thread = myThread(count,device[0],path)
        thread.start()
        count = count + 1


if __name__ == "__main__":
    main()

I came across this blogpost which describes about a race condition in monkeyrunner. I am not sure if thats what is causing the problem.

http://distributedreasoner.blogspot.com/2011/06/android-monkeyrunner-and-google-adb.html

I also tried using the MAML library mentioned in the above blog post, but I still havent been able to get monkeyrunner to execute simulatenously on multiple devices. Here is the actual monkeyrunner code.

import sys
import maml
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice



deviceId = sys.argv[1]

# Connects to the current device, returning a MonkeyDevice object
device = MonkeyRunner.waitForConnection(10.0,deviceId)

packagename = "com.android.settings"
classname =    "com.android.settings.DisplaySettings" #SecuritySettings" #".DisplaySettings" 
componentname = packagename + "/" + classname 
device.startActivity(component=componentname) 
maml.click(device,1088,300)
MonkeyRunner.sleep(0.4)
maml.click(device,864,361)
MonkeyRunner.sleep(0.4)
maml.click(device,612,621)
MonkeyRunner.sleep(0.5)
device.press ('KEYCODE_HOME', 'DOWN_AND_UP')

print "Exiting for device !" + deviceId

Based on Commonsware's question, I replaced the threading code with the following sequential code and it seems to work ok, but obviously this is not the most ideal situation.

for device in connected_devices:
        print device[0]
        ret = commands.getstatusoutput(path+"monkeyrunner mr1.py "+device[0])
        print ret

Because Android doesnt allow you to modify location / language settings etc programatically, and I need to configure many tablets to change settings, the immediate option was to use MonkeyRunner. A couple of notes, I am open to other tools that I could use other than monkeyrunner to solve this problem. Any help on this problem would be greatly appreciated.

Upvotes: 0

Views: 2336

Answers (1)

Paul Harris
Paul Harris

Reputation: 5819

What settings are you trying to change? language can be sort of done within your application if that is the only one.

public void setLocale(Locale locale, Instrumentation inst){
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    inst.getTargetContext().getResources().updateConfiguration(config, inst.getTargetContext().getResources().getDisplayMetrics());
}

Are all your tablets api level 16+ (jely bean?) if so you might want to look at http://developer.android.com/tools/testing/testing_ui.html

Finally if you still want to do it with monkey runner I would recommend getting hold of all your devices in one thread and then passing in each device to each thread separately.

Python is not my specialty and i do not have access/knowledge fo all the libraries you are using (i could do it in java for you maybe?) but what i think might work better is something like:

class myThread (threading.Thread):
    def __init__(self, device):
        self.device = device
        threading.Thread.__init__(self)

    def run(self):
        packagename = "com.android.settings"
        classname = "com.android.settings.DisplaySettings"
        componentname = packagename + "/" + classname
        self.device.startActivity(component=componentname)
        maml.click(self.device, 1088, 300)
        MonkeyRunner.sleep(0.4)
        maml.click(self.device, 864, 361)
        MonkeyRunner.sleep(0.4)
        maml.click(self.device, 612, 621)
        MonkeyRunner.sleep(0.5)
        self.device.press('KEYCODE_HOME', 'DOWN_AND_UP')


def main():
    connected_devices = util.get_connected_devices()
    count = 0
    devices = []
    for deviceId in connected_devices:
        devices[count] = MonkeyRunner.waitForConnection(10.0, deviceId[0])
        count = count + 1
    for device in devices:
        thread = myThread(device)
        thread.start()


if __name__ == "__main__":
    main()

basically the difference is as i said above, you get all the devices in sequence and then call each thread with the device you got sequentially. Does that make sense?

Upvotes: 1

Related Questions