Reputation:
I am currently trying to automate some Android actions through ADB and getting stuck with the contact import through vCards. There are 2 ways of doing this :
automate the exact "tappings" of the user, which supposes you have to determine the position of each "button" according to the screen resolution, etc. It is what I have done right now but it really seem hard to maintain, since there are too much parameters to take into account (custom roms, wierd resolutions, portrait/landscape mod, etc).
find what's happening when you click on "import contact from vCards" and do this action through ADB
Basically, I would like to apply the 2nd option, but I don't know what is happening when you click on "import contacts from vCard", which I would need to call the same action/intent from ADB. Any idea on the ADB command I should execute ?
Upvotes: 7
Views: 14957
Reputation: 31
Selected answer didn't work for me. I needed that functionality for several specific tests. So what I did is added Override BeforeSuite to test class inside which I called methods from the below classes and called super class method after.
public class AdbUtils {
private static final String CH_DIR = "cd ";
private static final String LOCATE_ADB = "locate -r ~/\".*platform-tools/adb\"";
public static void createContacts(List<Contact> contacts) throws Exception {
for (int i = 0; i < contacts.size(); i++) {
if (i < contacts.size() - 1) {
System.out.println(executeCommand(AdbCommands.CREATE_AND_SAVE_CONTACT
.getCommand(new String[]{contacts.get(i).getName(), contacts.get(i).getPhoneNumber()})));
} else {
System.out.println(executeCommand(AdbCommands.CREATE_AND_SAVE_CONTACT
.getCommand(new String[]{contacts.get(i).getName(), contacts.get(i).getPhoneNumber()})));
System.out.println(executeCommand(AdbCommands.START_CONTACTS_APP_LIST_STATE.getCommand(null)
+ " && " + AdbCommands.SLEEP.getCommand(new String[]{"3"})
+ " && " + AdbCommands.PRESS_BACK_BUTTON.getCommand(null)));
}
}
}
public static void removeAllContacts() {
System.out.println("DEBUG - Delete all contacts: " + executeCommand(new String[]{AdbCommands.DELETE_ALL_CONTACTS_CMD.getCommand(null)}));
}
private static String executeCommand(String command) {
return executeCommand(new String[]{command});
}
private static String executeCommand(String[] commandLines) {
String adbDir = locatePlatformToolsAdb();
adbDir = adbDir.substring(0, adbDir.length() - 4);
String[] command = new String[commandLines.length + 2];
command[0] = "bash";
command[1] = "-c";
commandLines[0] = CH_DIR + adbDir + " && " + commandLines[0];
System.arraycopy(commandLines, 0, command, 2, commandLines.length + 2 - 2);
String input;
String errorInput = null;
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(command);
proc.waitFor();
input = parseInputStream(proc.getInputStream());
errorInput = parseInputStream(proc.getErrorStream());
proc.destroy();
return input;
} catch (Exception ex) {
ex.printStackTrace();
}
return errorInput;
}
private static String locatePlatformToolsAdb() {
String path = null;
String error = null;
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(new String[]{"bash", "-c", LOCATE_ADB});
proc.waitFor();
path = parseInputStream(proc.getInputStream());
error = parseInputStream(proc.getErrorStream());
proc.destroy();
}
catch (Exception ex) {
ex.printStackTrace();
}
if(null != path){
System.out.println("DEBUG - Located platform tools: " + path);
return path;
}
else throw new IllegalStateException("DEBUG - error locating adb: " + error);
}
private static String parseInputStream(InputStream input) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String line;
StringBuilder resultBuilder = new StringBuilder();
while ((line = reader.readLine()) != null) {
resultBuilder.append(line);
}
return resultBuilder.toString();
}
catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
}
and
public enum AdbCommands {
WAIT("./adb shell wait"),
SLEEP("./adb shell sleep %s"),
DELETE_ALL_CONTACTS_CMD("./adb shell pm clear com.android.providers.contacts"),
START_CONTACTS_APP_LIST_STATE("./adb shell am start com.android.contacts"),
PRESS_RECENT_BUTTON("./adb shell input keyevent 187"),
PRESS_HOME_BUTTON("./adb shell input keyevent 3"),
PRESS_BACK_BUTTON("./adb shell input keyevent 4"),
CREATE_CONTACT("./adb shell am start -a android.intent.action.INSERT -t vnd.android.cursor.dir/contact " + "-e name '%s' -e phone %s"),
CREATE_AND_SAVE_CONTACT(CREATE_CONTACT.getCommand(null) + " && ./" + SLEEP.getCommand(new String[]{"3"})
+ " && ./" + PRESS_RECENT_BUTTON.getCommand(null) + " && ./" + SLEEP.getCommand(new String[]{"3"})
+ " && ./" + PRESS_RECENT_BUTTON.getCommand(null) + " && ./" + SLEEP.getCommand(new String[]{"3"})
+ " && ./" + PRESS_BACK_BUTTON.getCommand(null) + " && ./" + SLEEP.getCommand(new String[]{"3"}));
private String command;
private static final String arg = "%s";
AdbCommands(String command){ this.command = command; }
public String getCommand(@Nullable String[] args){
String command = this.command;
if(null == args) {
return this.command;
}
else{
if(countSubstring(this.command, arg) != args.length) throw new IllegalArgumentException("wrong args count!");
for (String arg : args) {
command = command.replaceFirst(AdbCommands.arg, arg);
}
return command;
}
}
private int countSubstring(String str, final String subStr){
int lastIndex = 0;
int count = 0;
while(lastIndex != -1){
lastIndex = str.indexOf(subStr,lastIndex);
if(lastIndex != -1){
count ++;
lastIndex += subStr.length();
}
}
return count;
}
}
Upvotes: 3
Reputation: 17615
Try this. Update -d
option with correct vcf
path.
adb shell am start -t "text/x-vcard" -d "file:///sdcard/contacts.vcf" -a android.intent.action.VIEW com.android.contacts
text/vcard
or text/x-vcard
android.intent.action.VIEW
com.android.contacts
Upvotes: 15