I am trying to run a monkeyrunner script on multiple devices to do some basic operations.I figured out that initialy I will start of writing a script to perform basic action in two connected devices.
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
import time
import sys
import time
devices = os.popen('adb devices').read().strip().split('\n')[1:]
device1 = MonkeyRunner.waitForConnection( devices[0].split('\t')[0])
package = 'com.android.browser'
activity = 'com.android.browser.BrowserActivity'
runComponent = package + '/' + activity
device1.startActivity(component=runComponent)
MonkeyRunner.sleep(1)
device2 = MonkeyRunner.waitForConnection( devices[1].split('\t')[0])
package = 'com.android.browser'
activity = 'com.android.browser.BrowserActivity'
runComponent = package + '/' + activity
device2.startActivity(component=runComponent)
When i run this script, it never finish executing. The browser action happen on one of the connected device but not on other. Can you guys help me fix this or if you have a better code(ideas) to run an activity on multiple devices, Please do let me know~ I am newbie and completely new to the programming world!Thanks in advance
you can give like
device1 = MonkeyRunner.waitForConnection('', devices[0].split('\t')[0])
this will help
A better way to do it is to write a script that explicitly binds to the devices. The link below shows how for emulators
http://chanakaudaya.wordpress.com/2012/04/10/monkeyrunner-tutorial-running-tests-on-multiple-devices-with-monkeyrunner-13/
also seems similar to this question(Which i answered):
Can not simultaneously run monkeyrunner scripts (e.g. two monkeyrunner process) on multi device
Related
I have an app that crashes at random times when I don't have a computer nearby to view logcat. Therefore I want to write the reason for a fatal error / every error to a file on my phone that I can read later to debug. I tried using try catch, but I am looking for a complete solution, like a command I enter once and it captures every crash and saves it, like an observer above the code respectively a kind of virtual box.
Which command helps me here?
Using a file for this is a bad idea - Not only do you possible have to worry about extra permissions but you also have to write a fair amount of code.
There are many libraries out there to catch Exceptions and log them for you.
Furthermore in a live environment this won't work at catching bugs since you can't ask users to send them a log file.
I use Fabric (Firebase)
https://firebase.google.com/docs/crashlytics/get-started
You're probably looking for Thread.UncaughtExceptionHandler or even better, Firebase Crashlytics.
I to wanted something similar, the solution that I came up with that works a bit was a Debug Log activity in the app that reads the logcat output in to a TextView.
I then Start this activity from a Menu Item or Button to show previous crashes.
Normally Android Studio Logcat window is just opening a remote shell on to the device with ADB and running the logcat command on the Android Device.
This method runs the logcat command on the Device itself without the need of a remote shell, but you need some Java code in your app to do this.
(This Extra Activity has to be in the Same App as you only have permission to see you own App's logcat)
(This does not always seem to pick up always all Log output but it does pickup crashes)
NOTE
The try and catch in this example code has nothing to do with trying to catch the errors Alex is Hunting as some people thought but to catch a possible error in the logcat display code. The logcat text shown by this Activity will show stack traces of those errors Alex is hunting.
This could then be run after restarting the app.
Code to do this is (Note you need to replace the "YOUR_APPS_TAG" with the Log TAG used by your app) See https://developer.android.com/studio/command-line/logcat for the filter specs
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class DebugLogActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_debug_log);
try {
Process process = Runtime.getRuntime().exec("logcat -d -D -v long " + "YOUR_APPS_TAG" + ":V *:E");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
StringBuilder log=new StringBuilder();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
log.append(line );
log.append(System.getProperty("line.separator"));
}
TextView tv = (TextView)findViewById(R.id.debugLog);
tv.setMovementMethod(new ScrollingMovementMethod());
tv.setTextIsSelectable(true);
tv.setText(log.toString());
} catch (IOException e) {
if (BuildConfig.LOG) {
Log.e("YOUR_APPS_TAG", "DebugLogActivity:onCreate:" + e.toString() + Arrays.toString(e.getStackTrace()));
}
}
}
}
The xml (actvitiy_debug_log.xml) for this extra activity
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".debuglogActivity">
<TextView
android:id="#+id/debugLog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars = "vertical"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
Example ScreenShot of running Activity after a crash
You can then copy and paste the text out and send it to yourself or just read it in the app.
I am new to Android Studio. I successfully created a Hello World app from the example in Android website. Now, I want to play around by using some statement to print in the logcat but it doesn't works. Below is my ApplicationTest.java code:
package com.example.abc.myloggingapplication;
import android.app.Application;
import android.test.ApplicationTestCase;
import android.util.Log;
/**
* Testing Fundamentals
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
Log.d("MyTest", "Here goes the output!"); // THIS IS THE NEW STATEMENT INSERTED BUT PRINTS NOTHING IN CONSOLE LOG IN ANDROID STUDIO SDK.
}
}
Other files are same as provided by the Hello World example in Android website. In Android Studio sdk, I entered the logcat to debug but still no luck. Can anybody point me out where I am going wrong.
Check your logcat:
Check View -> Tool windows -> Android Monitor.
Or Alt + 6
If that doesnt help, make sure you have an instance of your class. Otherwise the constructor is never called and therefor the log.d is never called.
Edit:
As other's have stated: Check if you are running the Test Application, if you want to do so. Otherwise make sure you code in your actual application and not your test application.
I would appreciate some help with some test automation on Android devices. We use Appium and RemoteWebDriver code to access the Android emulator, open up our application, tap and move around the application UI, and this all seems to work well.
However, as part of my testing, I would like to use Appium to initiate a telephone call on the device, keep the call open for a minute or so, and then hang up. Is there away to do this through the RemoteWebDriver object?
If not, what is the recommended way to make calls on the emulator? I have seen some discussion of using direct telnet calls to the emulator, but hope there is a better way!
You may set these desired capabilities :
capabilities.setCapability("androidPackage", "com.android.dialer");
capabilities.setCapability("appActivity", "DialtactsActivity");
and use this snippet to make call via Appium :
remoteWebDriver.findElement(By.id("com.android.dialer:id/search_view")).sendKeys("NAME_OF_PERSON");
remoteWebDriver.findElements(By.id("com.android.dialer:id/dialer_search_item_view")).get(0).click();
This would make call to the first search item
try {
Thread.sleep(60000); //
} catch (InterruptedException e) {
e.printStackTrace();
}
remoteWebDriver.findElement(By.id("com.android.dialer:id/endButton")).click();
This would disconnect the call after 60 seconds.
You can use a start a phone call using ADB:
public static int makePhoneCall(AppiumDriver driver, Srting deviceId, String phoneNum, int callDuration) throws IOException, InterruptedException {
callDuration *= 1000;
cmd = "adb -s " + deviceId + " shell am start -a android.intent.action.CALL -d tel:" + phoneNum; //open a Dialer and placing a call right away
Process exec = Runtime.getRuntime().exec(cmd); //starting a call and..
Thread.sleep(callDuration);//..waiting for callDuration seconds before hangup
driver.sendKeyEvent(6);// hang up phonecall
return exec.exitValue();
}
It turns out that this is possible, though perhaps a little more painfully than I expected. I had to do two things: specify the correct app to open, and work out the xpath references to the buttons on the dial pad. The activity is com.android.contacts.activities.DialtactsActivity and the xpaths to some of the buttons are:
Number text field: /linear/linear/editText
Number 1 button: /linear/table/row[1]/imageButton[1]
Number 5 button: /linear/table/row[2]/imageButton[2]
Dial button: /linear/frame/imageButton
If anyone has a better way to do this, I'd be very pleased to see it! Martin
press home button
driver.sendKeyEvent(3);
Press call button.
dr.sendKeyEvent(5);
locate dial pad
driver.findElementById("com.android.dialer:id/dialpad_button").click();
type number by send key or by sendKeyEvents.
driver.findElement(By.className("android.widget.EditText")).sendKeys(phoneNumber);
Press call button
driver.findElementById("com.android.dialer:id/dial_button").click();
put some wait and press End call button.
dr.findElementById("com.android.dialer:id/endButton").click();
Im trying to figure out an easier (more automated way) to see all the version numbers of the apk's (both user installed and preinstalled) that are currently installed on an Android device.
currently I have been going about it like this:
a. The version is in the apk
b. The apk is typically in /system/app
c. The package name to apk name can be found in /data/system/packages.xml
d. The tricky part is that the application NAME is usually in a string resource in the apk file – like strings.xml (default name)
e. This can also be done from within the android SDK using the PackageManager family of API’s
This is extremely time consuming and Im doing this for many, many, many devices. Im just thinking that there has to be an easier way then how Im going about it.
Thanks for the help, as always, its very appreciated.
The only one of your approaches that is valid is:
This can also be done from within the android SDK using the PackageManager family of API’s
The rest... I have no idea why you think it would even work, let alone do so reliably. What makes you think that people will be using string resources for these, considering that versionCode in particular never has to be translated?
This is extremely time consuming
The code to call PackageManager, iterate over the installed applications, and retrieve the version information should take a handful of milliseconds.
I did it, whoooo!!! ..... I am posting this code to anyone else that need to find the packagenames and version names of everything on the device.
import java.util.List;
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.widget.TextView;
public class main extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String bldr = new String();
List<PackageInfo> packs = getPackageManager().getInstalledPackages(0);
bldr = "Total packages --> " + packs.size() + "\n";
for(int i=0;i<packs.size();i++){
PackageInfo p = packs.get(i);
bldr = bldr + "<" + p.packageName + ">" + "\t" + "v" + p.versionName + "\n";
}
TextView tv = new TextView(this);
tv.setMaxLines(packs.size() + 2);
tv.setMovementMethod(new ScrollingMovementMethod());
tv.setText(bldr);
setContentView(tv);
Log.w("com.tmobile.pr.showAllPackages", bldr.toString());
}
}
Is it possible to capture MMI result in Android?
I need to do things like put on hold, merge calls, etc. and as the only telephony events in android are NEW_OUTGOING_CALL, RINGING, OFFHOOK and IDLE, I need to get the result when i dial any MMI code like Held Code.
Is it possible?
The best solution for me would be to find some way to discover when an outgoing call gets actually connected. Maybe has somebody find any workaround for that?
I made some progress in that question reading system logs (LogCat) and searching for determinate strings, but it seems that logs differs between models and SO versions so this is not a consistent aproach.
Thanks for your help!
Maybe you can get it using RIL(Radio Interface Layer)
try something like:
1) adb device shell
2) logcat -b radio
// Navigate to the page that you have dial *#06# in dialpad then execute jar below to get the IMEI result
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiScrollable;
import android.util.Log;
public class SIM_Info_Reader_png extends UiAutomatorTestCase{
public void getPromptedIMEI() throws UiObjectNotFoundException {
UiObject list = new UiObject(new UiSelector().resourceId("android:id/text1"));
int i = 0;
System.out.println("IMEI=" + list.getText());
}
}