15

I am trying to write a batch(for win) and a shell script for linux to automate key and touch events on a android UI. At the moment in a windows batch file I am starting a adb shell for each event for eg

    :again

adb shell am start -a android.intent.action.MAIN -n com.q.me.fui.activity/.InitActivity

sleep 15

adb shell sendevent /dev/input/event0 3 0 281
adb shell sendevent /dev/input/event0 3 1 70
adb shell sendevent /dev/input/event0 1 330 1
adb shell sendevent /dev/input/event0 0 0 0
adb shell sendevent /dev/input/event0 1 330 0
adb shell sendevent /dev/input/event0 0 0 0   
adb shell sendevent /dev/input/event0 1 330 1
adb shell sendevent /dev/input/event0 0 0 0
adb shell sendevent /dev/input/event0 1 330 0
adb shell sendevent /dev/input/event0 0 0 0
adb shell sendevent /dev/input/event0 0 0 0
adb shell sendevent /dev/input/event0 0 0 0   

sleep 5

adb shell input keyevent 82
adb shell input keyevent 20
adb shell input keyevent 20
adb shell input keyevent 22
adb shell input keyevent 22
adb shell input keyevent 22
adb shell input keyevent 66

sleep 5

goto again

The above code is infact starting a new adb shell each time. I want to avoid this. I want my batch script to start the adb shell only once and I would like to route the sendevent and other commands to the subshell, ie the adb shell.

Any idea how I can do this in win batch and Lin shell script?

5 Answers 5

22

Put all the commands you want to run at once in an external file, one per line, then run:

adb shell < commands.txt
Sign up to request clarification or add additional context in comments.

2 Comments

A simple, elegant solution! I would only suggest putting a last line in the example commands.txt file that simply reads 'exit' (without quotes) to drop you back to your main shell.
In PowerShell use Get-Content .\commands.txt | adb shell
13

Topher's answer is almost correct.

Just remove the newlines and it will work.

adb shell "sendevent /dev/input/event9 3 53 215;sendevent /dev/input/event9 3 54 68;sendevent /dev/input/event9 3 48 40;sendevent /dev/input/event9 3 50 6;sendevent /dev/input/event9 3 57 0;sendevent /dev/input/event9 0 2 0;sendevent /dev/input/event9 0 0 0;sendevent /dev/input/event9 3 53 215;sendevent /dev/input/event9 3 54 68;sendevent /dev/input/event9 3 48 0;sendevent /dev/input/event9 3 50 6;sendevent /dev/input/event9 3 57 0;sendevent /dev/input/event9 0 2 0;sendevent /dev/input/event9 0 0 0;"

The only thing you need to take care of is, that you do not feed in more than 25 (that's the amount I used, 30 doesn work anymore) sendevents, because else adb will throw the error, that there are too many arguments or so.

1 Comment

@Vladimir, what if my shell commands include quotes? For example, adb shell input text "blah-blah"
11

I don't know much about batch scripting or shell scripting, but I was able to quickly write a java program to do this:

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

public class AndroidShell  {
   private ProcessBuilder builder;
   private Process adb;
   private static final byte[] LS = "\n".getBytes();

   private OutputStream processInput;
   private InputStream processOutput;

   private Thread t;

   /**
    * Starts the shell 
    */
   public void start() throws IOException  {
      builder = new ProcessBuilder("adb", "shell");
      adb = builder.start();

      // reads from the process output
      processInput = adb.getOutputStream();

      // sends to process's input
      processOutput = adb.getInputStream();

      // thread that reads process's output and prints it to system.out
      Thread t = new Thread() {
         public void run() {
            try   {
               int c = 0;
               byte[] buffer = new byte[2048];
               while((c = processOutput.read(buffer)) != -1) {
                     System.out.write(buffer, 0, c);
               }
            }catch(Exception e)  {}
         }
      };
      t.start();
   }

   /**
    * Stop the shell;
    */
   public void stop()   {
      try   {
         if(processOutput != null && t != null) {
            this.execCommand("exit");
            processOutput.close();
         }
      }catch(Exception ignore)  {}
   }

   /**
    * Executes a command on the shell
    * @param adbCommand the command line.
    * e.g. "am start -a android.intent.action.MAIN -n com.q.me.fui.activity/.InitActivity" 
    */
   public void execCommand(String adbCommand) throws IOException {
      processInput.write(adbCommand.getBytes());
      processInput.write(LS);
      processInput.flush();
   }

   public static void main(String[] args) throws Exception  {
      AndroidShell shell = new AndroidShell();
      shell.start();

      for(String arg : args)  {
         if(arg.startsWith("sleep"))   {
            String sleep = arg.split(" ")[1].trim();
            long sleepTime = Integer.parseInt(sleep) * 1000;
            Thread.sleep(sleepTime);
         }else {
            shell.execCommand(arg);
         }
      }

      shell.stop();
   }
}

You can then use this class in a shell script as you like passing the commands to execute as command line arguments in your main method.

e.g. Below is the shell script:

#!/bin/bash

java AndroidShell "am start -a android.intent.action.MAIN -n com.q.me.fui.activity/.InitActivity" \
"sleep 15" \
"sendevent /dev/input/event0 3 0 281" \
"sendevent /dev/input/event0 3 1 70" \
"sendevent /dev/input/event0 1 330 1" \
"sendevent /dev/input/event0 0 0 0" \
"sleep 10" \
"sendevent /dev/input/event0 1 330 0" \
"exit"

1 Comment

cool answer, just small mistake, the Thread t should not have method scope
7

I am doing something similar

(
   echo cd sdcard
   echo ls
) | adb shell

So it may work as below:

(
    echo am start -a android.intent.action.MAIN -n com.q.me.fui.activity/.InitActivity
    echo sleep 15
    echo sendevent /dev/input/event0 3 0 281
    echo sendevent /dev/input/event0 3 1 70
    echo sendevent /dev/input/event0 1 330 1
    echo sendevent /dev/input/event0 0 0 0
    echo sendevent /dev/input/event0 1 330 0
    echo sendevent /dev/input/event0 0 0 0   
    echo sendevent /dev/input/event0 1 330 1
    echo sendevent /dev/input/event0 0 0 0
    echo sendevent /dev/input/event0 1 330 0
    echo sendevent /dev/input/event0 0 0 0
    echo sendevent /dev/input/event0 0 0 0
    echo sendevent /dev/input/event0 0 0 0   
    echo sleep 5
    echo input keyevent 82
    echo input keyevent 20
    echo input keyevent 20
    echo input keyevent 22
    echo input keyevent 22
    echo input keyevent 22
    echo input keyevent 66
    echo sleep 5
) | adb shell

Comments

2

Another way to go is the following:

adb shell "sendevent /dev/input/event0 3 0 281;
           sendevent /dev/input/event0 3 1 70;
           sendevent /dev/input/event0 1 330 1;
           sendevent /dev/input/event0 0 0 0;
           sendevent /dev/input/event0 1 330 0;
           sendevent /dev/input/event0 0 0 0;
           sendevent /dev/input/event0 1 330 1;
           sendevent /dev/input/event0 0 0 0;
           sendevent /dev/input/event0 1 330 0;
           sendevent /dev/input/event0 0 0 0;
           sendevent /dev/input/event0 0 0 0;
           sendevent /dev/input/event0 0 0 0"

1 Comment

Just realized you're using a batch file. The above works in bash but I don't remember how DOS handles line continuation. Maybe this will work as-is? The semicolons are all that's necessary to issue multiple commands to adb shell (which is ash IIRC)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.