How to run monkeyrunner on an already installed .apk - android

I'm trying to run some commands on an application that is already installed through monkeyrunner. I've edited the sample code listed on d.android.com and I changed it to this:
# Imports the monkeyrunner modules used by this program
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
# 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.example.myTestApp'
# sets a variable with the name of an Activity in the package
# activity = 'com.example.android.myapplication.MainActivity'
# sets the name of the component to start
runComponent = package
# Runs the component
device.startActivity(component=runComponent)
# Presses the Menu button
device.press('KEYCODE_MENU', MonkeyDevice.DOWN_AND_UP)
# Takes a screenshot
result = device.takeSnapshot()
# Writes the screenshot to a file
result.writeToFile('myproject/shot1.png','png')
As you can see, I changed the code to (hopefully) open com.example.myTestApp But it doesn't open my application, but it seems it runs the commands on the current application. Any ideas?

You should specify the Activity in runComponent as
runComponent = package + "/" + activity
To get the names of the launchable Activities:
$ aapt dump badging <name>.apk | grep launchable-activity

I was able to get the launch activity from an any installed apk from the play store using this method:
get launchable activity name of package from adb
adb shell pm list packages -f
Then you can use adb pull:
adb pull <APK path from previous command> <toYourDesiredLocation>
For Example:(adb pull /system/app/MyAPK.apk C:\someLocation)
and then aapt to get the information you want (aapt is currently located in ~\sdk\build-tools\android-4.3):
aapt dump badging <FromYourDesiredLocation\pulledfile.apk>
then look for launchable-activity: name='SomeActivityName'
Hope that helps someone else looking for the same thing.

First check whether your app is installed.
apk_path = device.shell('pm path com.xx.yy')
if apk_path.startswith('package:'):
print "XXXYY already installed."
else:
print "XXXYY app is not installed, installing APKs..."
device.installPackage('D:/path to apk/yourapp.apk')
refer http://antoine-merle.com/introduction-to-the-monkey-runner-tool-2/

Related

Start activity with adb

I have a simplest possible test app, developed with xamarin, deployed to a usb connected droid. With the goal of having one day a working intent url, I'm trying to call my main activity with adb shell am. Here are the first few lines of my MainActivity...
namespace DematAEAT_Android
{
[Activity(Label = "DematAEAT_Android", MainLauncher = true, Icon = "#drawable/icon")]
[IntentFilter(new[] { "AcquireSignedImage" },
Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault })]
public class MainActivity : Activity
{
int count = 1;
Here are two shell commands. In the first, the package manager successfully understands the package name and reports the apk path. In the second, the activity manager fails to resolve the class MainActivity. It fails with or without the namespace.
C:\Program Files (x86)\Android\android-sdk\platform-tools>adb -d shell pm path "fr.company.DematAEAT_Android"
package:/data/app/fr.company.DematAEAT_Android-1/base.apk
C:\Program Files (x86)\Android\android-sdk\platform-tools>adb -d shell am start -n "fr.company.DematAEAT_Android/.DematAEAT_Android.MainActivity"
Starting: Intent { cmp=fr.company.DematAEAT_Android/.DematAEAT_Android.MainActivity }
Error type 3
Error: Activity class {fr.company.DematAEAT_Android/fr.company.DematAEAT_Android.DematAEAT_Android.MainActivity} does not exist.
edit...
And yet, I can launch happily using monkey. The following command works fine. Tis as if there's a problem with the way I'm naming my activity class in the adb shell am call, but I can't spot it.
C:\Program Files (x86)\Android\android-sdk\platform-tools>adb shell monkey -p fr.company.DematAEAT_Android 1
Events injected: 1
## Network stats: elapsed time=170ms (0ms mobile, 0ms wifi, 170ms not connected)
Can anyone tell me how to call this activity?
This was a breaking change in Xamarin Android 5.0
Android Callable Wrapper Naming
The name mangling scheme for Android Callable Wrappers is changing. Previously, the Android Callable Wrapper package name was constructed by lowercasing the namespace name, which would result in packaging failures if more than one assembly contained a type with the same fully-qualified name.
With the 5.0 release, the default package names for Android Callable Wrappers will be based on the MD5SUM of the assembly-qualified name of the type being exported. This allows the same fully-qualified name to be provided from two different assemblies and not get a packaging error.
https://developer.xamarin.com/releases/android/xamarin.android_5/xamarin.android_5.1/#Android_Callable_Wrapper_Naming
You can override that for your Activity by specifying the name in the [Activity] attribute:
[Activity(Name = "fr.company.demeat_android.MainActivity")]
public class MainActivity : Activity {
/* ... */
}
Well who knew? I needed to grub around in my manifest.xml to discover that xamarin is appending a hash as a namespace in front of my activity name. So the adb call that works looks like this...
C:\Program Files (x86)\Android\android-sdk\platform-tools>adb -d shell am start -n fr.company.DematAEAT_Android/md5abda05033ab0415fc7a776c5d9734c74.BrowsableActivity
Starting: Intent { cmp=fr.company.DematAEAT_Android/md5abda05033ab0415fc7a776c5d9734c74.BrowsableActivity }
The story continues here. This will likely be an issue for anyone trying to start a xamarin activity via adb shell am, or trying to start a xamarin activity with an intent, or an intent url.

debug.log for XposedBridge?

I currently work on an application with XposedBridge and I have a lot of questions. I will start with the simple ones.
How can I get the debug.log file?
I cannot find the debug.log file. I have tried the phone shell as well as two adb ways :
A. adb shell data/data/de.robv.android.xposed.installer/log/debug.log
B. adb shell "su -c 'cat data/data/de.robv.android.xposed.installer/log/debug.log'"
C. adb shell cat data/data/de.robv.android.xposed.installer/log/debug.log
adb says : " No such file or directory "
The phone shell can cd to /data and /data/data but not after. Cannot ls neither of the data's. Says access denied. So does adb when I try adb ls.
The phone, Moto E XT1023, is rooted. Despite, shell cannot read some directories. I have posted a question why here but no one seems to care to answer.
I had to go to ES File Explorer. Managed to get to /data. ES says folder empty. Managed to get to Emulator/0/de.robv.android.xposed.installer or something alike. There was a subdirectory called files. Inside was the installer. No debug.log.
Searched all directories with ES for debug.log. Nothing found.
Once I create the XposedBridge class in a separate file of the project and once I do whatever XposedBridge is supposed to do (override methods, insert code before and or after the methods, etcetera) the overridden methods or the methods with code run before and or after or the overridden data will continue to be overridden until the app exits. Is this true?
Is there any simple, yet powerful and comprehensive manual or reference or, the best, a tutorial?
Can I specify another directory for the debug.log.file?
In case I am able to make a directory \data\data manually, would this make the Xposed save debug.log there?
I am so happy I have managed to partially answer the first question which is not only related to XposedBridge but is a global root reach question for rooted phones, so I cannot even think of any other questions for now. I do not have a debug.log but I have error.log and I know how to read these. Here is how in case anyone is interested :
In order to be able to reed XposedBridge log files :
Go to the specialised Moto E adb ( may work with a standard one too ).
Type :
************
* adb root *
************
to ensure root access.
The Dollar Sign $ must appear as the sign before commands. $ means the adb shell environment has been entered.
After $, type :
******
* su *
******
The Sharp Sign # must appear as the sign before commands. # means root has been entered. Once root has been entered, there is a full access to the phone. Thus :
**************************************************
* cd /data/data/de.robv.android.xposed.installer *
**************************************************
can be executed and the directory /data/data/de.robv.android.xposed.installer will be entered.
Type :
******
* ls *
******
to see the contents of this directory.
In case error.log or debug.log files are there, type :
*****************
* cat error.log *
*****************
and or
*****************
* cat debug.log *
*****************
to view these files.
Type :
********
* exit *
********
to return to the safer $ prompt.
Type :
********
* exit *
********
to exit adb.
Note : adb root may not run while a project is developed. The rest works, though.
I still do not have any debug.log. May be the XposedBridge lines do not run. Will check with some simple method from the manual.
Here is what I have found out, though. I have created an empty text file called debug.log on the computer and transferred the file to the main root of the device, the /sdcard directory, themn copied the file to /data/data/de.robv.android.xposed.installer/log just to see what happens. Nothing happens. The file is empty.
Here is what I have found out which may be helpful:
COMMANDS TO READ THE LOG FILES :
adb shell
su
cd /data/data/de.robv.android.xposed.installer/log
cat error.log
USE cp SOURCE DESTINATION after su shell, the # prompt, to copy files from one
directory to another on the device.
IMPORTANT NOTES :
All Xposed classes must be put in xposed_init, otherwise Android Studio 1.2 reports them as never used.
In built.gradle, have :
/* SSB : Added manually so the gradle builds with the
XposedBridgeApi-54.jar which is in the app -> libs
but not to include the jar in the apk. */
dependencies {
provided fileTree(dir: 'libs', include: ['*.jar'])
}
THESE HAVE BEEN PUT MANUALLY.
Update : I have been able to clean the code and have managed to find why I do not have a debug.log. This is because the two XposedBridge classes I have ( one is initialisation of zygote and the other is the work file with hooks and replacements ) are not loaded. The error.log shows : Didn't find class " package ( strts without a com. ) NameOfThePackageWithoutComDot.NameOfTheExposedClass in the NameOfThePackageWithoutComDot-2.apk "
THIS IS SAID FOR THE TWO CLASSES.
Problem partially solved:
I have removed the string " package " from the xposed_init and this solved the problem. Thus, instead of :
package TheNameOfThePackage.TheNameOfTheClass
xposed_init contains :
TheNameOfThePackage.TheNameOfTheClass
without the word " package " in front of the names as Android Studio usually puts and requires.
Now, the custom class seems to load OK and XMain where zygote is init generates a novel.
Regardless, the custom class with the test code works OK. The debug.log file is generated. However, the application does not seem to write in the file and the debug.log only says :
d.xposed.installer/log/debug.log
inside.

Android apitrace failed to run

I would like to use the apitrace project on android. I followed the instructions from the readme file.
But get no trace where created.
I run this command
adb shell TRACE_FILE=/data/test.trace LD_PRELOAD=/data/egltrace.so am start -n APP_NAME
How can I make it work?
I tried following the instructions in Dalvik.markdown of the original distribution of apitrace, but without success.
The instructions say to set two properties: wrap._process_name_ and debug.apitrace.procname. The former has to be set, according to those instructions, to LD_PRELOAD=/data/egltrace.so. When launching the application I still wouldn't get any trace generated nor any apitrace-related message in the logcat.
I had more success by putting the LD_PRELOAD instruction in a script and using that as the wrapper. This is the script that I use, called /data/apitrace.sh:
LD_PRELOAD=/data/egltrace.so exec $#
You can also set the TRACE_FILE environment variable to specify the path to which the trace file should be written to. Otherwise it will be _/data/app_process.trace_. For example:
TRACE_FILE=/data/apitraces/mytrace.trace LD_PRELOAD=/data/egltrace.so exec $#
I believe apitrace takes care of adding numbers to the filename to prevent overwriting existing ones. So you'll have mytrace.trace, mytrace.1.trace, and so on.
So with this script in place I set the properties like so:
adb shell setprop wrap._process_name_ /data/apitrace.sh
adb shell setprop debug.apitrace.procname _process_name_
And then I launch the application. I see in the logcat something like the following:
I/dalvikvm( 5980): Exec: /system/bin/sh -c /data/apitrace.sh /system/bin/app_process /system/bin --application '--nice-name=_process_name_' com.android.internal.os.WrapperInit 25 17 'android.app.ActivityThread'
D/apitrace( 5991): apitrace: loaded
D/apitrace( 5991): apitrace[5991]: enabled for _process_name_
D/apitrace( 5991): apitrace: tracing to /data/app_process.trace
I'm using CyanogenMod 10.1.3, which is based on Android 4.2.2.

Start an Android Test from an Intent (or from SL4A)?

I'd like to run some android tests but I want to scedule or delay the execution of these tests. I'm trying to do this from SL4A. The idea is to install SL4A start the server from my laptop, run a special python script that will sleep for about 20 seconds then wakeup and launch the tests. I am performing some rather involved automation that requires my tests be run after I install them and disconnect the USB cable. I know I can issue intents from SL4A but I'm looking for the equivalent of:
adb shell am instrument \
-e class MyInstrumentationTestCase \
-w MyInstrumentationTestRunner
Can this be done via intent? Should I send a broadcast or use the start activity functions?
I've tried running a system command directly on the device from Python with this script but I get a "permission denied" error:
from subprocess import call
call(["am", "instrument", "-e", "class", "com.example.android.app.test.TestContactList", "-w", "com.example.app.test/com.zutubi.android.junitreport.JUnitReportTestRunner"])
UPDATE
I've also tried using os.system to run the command (see below modifications) and this gives a different error: soinfo_link_image(linker.cpp:1635): could not load library "libanroid_runtime.so" needed by "app_process"; caused by so info_relocate(linker.cpp:975): cannot locate symbol " sqlite3_stmt_readonly" referenced by "lib android_runtime.so"...CANNOT LINK EXECUTABLE
import os
#from subprocess import call
#call(["am", "instrument", "-e", "class", "com.example.android.app.test.TestContactList", "-w", "com.example.android.app.test/com.zutubi.android.junitreport.JUnitReportTestRunner"])
os.system('echo "Running tests"')
os.system('am instrument -e class com.example.android.app.test.TestContactList -w com.example.android.app.test/com.zutubi.android.junitreport.JUnitReportTestRunner')
What are any other options?
I have the following function, which will launch any SL4A script from within a Python SL4A script, as a separate process. You can not use subprocess for this type of thing.
You may be able to deduce what you need from this.
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)

Monkey Runner import giving error

i created an empty file an named it something.py, and then i just copied the lines of code from the android developer website. However, if i try to run it, i get an
ImportError: No module named com.android.monkeyrunner
Is there something i am missing? There doesn't seem to be anything at the android developer website that addresses this issue. Here are the lines of code
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
device = MonkeyRunner.waitForConnection()
device.installPackage('myproject/bin/Stamp_Client.apk')
package = 'com.example.main'
activity = 'com.example.Stamp_Client'
runComponent = package + '/' + activity
device.startActivity(component=runComponent)
device.press('KEYCODE_BUTTON_SELECT','DOWN_AND_UP')
device.press('KEYCODE_U','DOWN_AND_UP')
device.press('KEYCODE_S','DOWN_AND_UP')
device.press('KEYCODE_E','DOWN_AND_UP')
device.press('KEYCODE_R','DOWN_AND_UP')
device.press('KEYCODE_ENTER','DOWN_AND_UP')
device.press('KEYCODE_P','DOWN_AND_UP')
device.press('KEYCODE_A','DOWN_AND_UP')
device.press('KEYCODE_S','DOWN_AND_UP')
device.press('KEYCODE_S','DOWN_AND_UP')
device.press('KEYCODE_ENTER','DOWN_AND_UP')
device.press('KEYCODE_ENTER','DOWN_AND_UP')
Make sure you run:
$ monkeyrunner yourfile.py
instead of:
$ python yourfile.py
I guess you are missing the shebang:
#! /usr/bin/env monkeyrunner
that is if you are using Linux or OSX, for Windows you probably have to create a batch file.

Categories

Resources