Sending MMS via MonkeyRunner on Android throws Java exception
Question: I need to send MMS by writing a MonkeyRunner script. My script is as below and
it throws an exception. Can anyone please help? I am interested in writing
scripts using intents and not using co-ordinates method:

    
    
    from com.android.monkeyrunner import MonkeyDevice, MonkeyRunner, MonkeyImage
    device= MonkeyDevice
    for i in range(5):
    device =MonkeyRunner.waitForConnection(8)
    if device != None:
    print "Device found..."
    break;
    Intent sendIntent = new Intent("android.intent.action.SEND_MSG"); 
    sendIntent.putExtra("999999", toText); 
    sendIntent.putExtra(Intent.EXTRA_SUBJECT, "MMS");
    sendIntent.putExtra("sms_body", textMessage); 
    sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File("/sdcard/file.gif")));
    sendIntent.setType("image/jpeg");
    device.startActivity(sendIntent);
    

> 130508 12:37:35.663:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions]
> Script terminated due to an exception  
>  130508 12:37:35.663:S [main]
> [com.android.monkeyrunner.MonkeyRunnerOptions]Synta xError: ("mismatched
> input 'sendIntent' expecting NEWLINE",
> ('C:\Users\halappa\Work\MMBU\EOS2\ES2\Samsung\adt-bundle-
> windows-x86_64-20130219\adt-bundle
> -windows-x86_64-20130219\sdk\tools\mms.py', 9, 7, 'Intent sendIntent = new
> Intent("android.intent.action.SEND_MSG"); \n'))  
>  130508 12:37:35.663:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions]  
>  at org.python.core.ParserFacade.fixParseError(ParserFacade.java:94)  
>  130508 12:37:35.663:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions]
> at org.python.core.ParserFacade.parse(ParserFacade.java:143)  
>  130508 12:37:35.663:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions]  
>  at org.python.core.Py.compile_flags(Py.java:1644)  
>  130508 12:37:35.663:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions]  
>  at org.python.core.**builtin**.execfile_flags(**builtin**.java:530)  
>  130508 12:37:35.663:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions]  
>  at org.python.util.PythonInterpreter.execfile(PythonInterpreter.java:156)  
>  130508 12:37:35.663:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions]  
>  at com.android.monkeyrunner.ScriptRunner.run(ScriptRunner.java:116)  
>  130508 12:37:35.663:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions]  
>  at
> com.android.monkeyrunner.MonkeyRunnerStarter.run(MonkeyRunnerStarter.java:77)  
>  130508 12:37:35.663:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions]  
>  at
> com.android.monkeyrunner.MonkeyRunnerStarter.main(MonkeyRunnerStarter.java:18
> 9)


Answer: There is a way to send an SMS or an MMS programatically in a monkeyrunner
script using a device shell command to use activity manager to start an
activity with an intent built with the start parameters

    
    
    device.shell("am start -a android.intent.action.VIEW -t vnd.android-dir/mms-sms -e address \'number or adderess goes here\' -e subject \'subject goes here\' -e sms_body \'message body goes here\'")
    

This will launch the default SMS or MMS application with the number/address,
subject and message as supplied in the intent extras.

If you don't have a default SMS/MMS messaging application and there are more
than one on the device, you will need to choose one of the several in a popup
dialog.

Whether you send an SMS or MMS seems to depend on whether there is a subject
extra included. On my devices, the message is an SMS if there is no subject
extra and is an MMS if there is a subject extra.

The above will only launch the SMS/MMS application with the supplied address
and message and, if also supplied, the subject. However, it won't send the
message. I've always had to add a touch to the send button with its x, y
coordinates to get the message to send.

    
    
    device.touch(x coordinate here, y coordinate here, MonkeyDevice.DOWN_AND_UP)
    

There are three extras for the intent, an address, a subject and a sms_body.
I've tried using monkeyrunner with the direct intent creation and not the `am
start` command from the device shell but I've never successfully extras into
the intent with that approach whereas the code above works. The other direct
intent creation works for me only when the intent doesn't need extras.

If you need the x, y coordinates of the send button, you can get them for more
recent devices by turning on "Pointer location" in the device's developer
options. The device's screen will then have a very narrow translucent ribbon
at the top of the screen with information about your screen touches, blue
crosshairs marking a current touch location and a blue track/trail from any
touch motion. The ribbon at the top indicates location, velocity of motion and
other data. For touch coordinates, launch the application and touch the screen
where the send button is to find its coordinates.

Coordinates are ALWAYS relative to the uppermost left corner of the current
device orientation. That means if you rotate the device from portrait to
landscape, the coordinates will be relative to whatever corner becomes the
uppermost left corner in the new orientation even if the application doesn't
rearrange itself for the new orientation.

Also, in my scripts, I dismiss the soft keyboard with a programatic BACK
button just before the touch for the send button.

    
    
    device.press('KEYCODE_BACK', MonkeyDevice.DOWN_AND_UP)
    

I've found that whether the soft keyboard is shown or not is not very
predictable, so, before dismissing the soft keyboard, I include a test for
whether it is showing or not using a method shown here in another stack
overflow answer:

[How to Determine Whether Soft Keyboard Is Shown on
Screen](http://stackoverflow.com/questions/12903907/how-to-determine-whether-
softkeyboard-is-shown-on-the-screen-while-using-monke/19686510#19686510)

Enjoy!

