0

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.

smk
  • 5,340
  • 5
  • 27
  • 41
  • Are you trying to run it on multiple tablets sequentially or simultaneously? What precisely do you mean by "it all blows up"? – CommonsWare Nov 19 '12 at 21:33
  • Simultaneously. "By all blows up" I mean nothing happens. For example , in the monkeyrunner code I have pasted, its supposed to first open settings and then click on Auto-rotate screen and then change sleep to Always on. When I ran it on 2 devices connected to my pc, I noticed that just the display settings opened up. The other clicks did not happen. Again, it is not exactly same behavior every time I run the script. Sometimes some of the clicks work on 1 device, but not other. – smk Nov 19 '12 at 21:37
  • Btw, im assuming that the tablet is in landscape orientation. – smk Nov 19 '12 at 21:44

1 Answers1

1

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?

Paul Harris
  • 5,769
  • 1
  • 25
  • 41
  • Yep I know that some settings can be done programatically, but I need to change 1)location services 2) languages and input and security. This cannot be done programatically - correct? – smk Nov 19 '12 at 21:39
  • "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." - Im new to python , but isnt that what I am doing? in the for device in connected_devices loop? – smk Nov 19 '12 at 21:41
  • 1
    I am going to be honest you are going to find it hard to do some of those things using MonkeyRunner even if you get past this problem because I expect your tablets have different UIs, e.g. they are made by different people. This means that they surely have different co-ordinates for everything. You might find it best to limit this testing to the emulator which you can easily perform the activities you want and use the tablets to test other things. – Paul Harris Nov 19 '12 at 21:47
  • My situation is as follows. Its a 1 time thing. And we know before hand that ther will be like 2k brand new tablets and all same type. – smk Nov 19 '12 at 22:13
  • Do you know what version of android they are? – Paul Harris Nov 19 '12 at 22:39
  • You sir, are my hero.. Using the uiautomator tool worked very well. I talked to my mgr and I believe it should be JB. So I hope im good. – smk Nov 20 '12 at 17:12