I am studying android and .NET
I would like to use VB.NET to execute adb command
For example, I would like to enable or disable airplane mode from PC to Android phone
such as
adb shell settings put global airplane_mode_on 1
adb shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true
Dim psi As New ProcessStartInfo
Dim psi2 As New ProcessStartInfo
psi.WorkingDirectory = "C:\ad\adsystem\adb file"
psi.Arguments = "adb shell settings put global airplane_mode_on 0"
psi.FileName = "adb"
psi.WindowStyle = ProcessWindowStyle.Hidden
Process.Start(psi)
psi2.WorkingDirectory = "C:\ad\adsystem\adb file"
psi2.Arguments = "adb shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false"
psi2.FileName = "adb"
psi2.WindowStyle = ProcessWindowStyle.Hidden
Process.Start(psi)
I tried to use example from
How to get Output of a Command Prompt Window line by line in Visual Basic?
Shell commands in VB
However, It didn't really work and i am not really sure why ....
is there anyway to run adb command from VB.NET?
thanks
You can use cmd.exe to communicate with adb commands see my code example.
Declaring new process and process info
Dim My_Process As New Process()
Dim My_Process_Info As New ProcessStartInfo()
Using cmd.exe as the filename of my process.
My_Process_Info.FileName = "cmd.exe"
in argument you can use adb commands like this.
My_Process_Info.Arguments = "/c adb devices"
/c Carries out the command specified by string and then terminates.
Now set WorkingDirectory for adb.exe in cmd.exe. Don't confuse, it is same as cd command. Setting our working Directory to where your adb.exe file exists.
My_Process_Info.WorkingDirectory = "Directory of your adb.exe file"
Now some necessary settings for process.
My_Process_Info.CreateNoWindow = True ' Show or hide the process Window
My_Process_Info.UseShellExecute = False ' Don't use system shell to execute the process
My_Process_Info.RedirectStandardOutput = True ' Redirect (1) Output
My_Process_Info.RedirectStandardError = True ' Redirect non (1) Output
My_Process.EnableRaisingEvents = True ' Raise events
My_Process.StartInfo = My_Process_Info
Setting completed, Now start the process.
My_Process.Start()
If you want to get the reply/result of your sended adb command you can use StandardOutput property of the process.
Dim Process_ErrorOutput As String = My_Process.StandardOutput.ReadToEnd() ' Stores the Error Output (If any)
Dim Process_StandardOutput As String = My_Process.StandardOutput.ReadToEnd() ' Stores the Standard Output (If any)
Example Function:
Function adb(ByVal Arguments As String) As String
Try
Dim My_Process As New Process()
Dim My_Process_Info As New ProcessStartInfo()
My_Process_Info.FileName = "cmd.exe" ' Process filename
My_Process_Info.Arguments = Arguments ' Process arguments
My_Process_Info.WorkingDirectory = "C:\Users\<Your User Name>\AppData\Local\Android\android-sdk\platform-tools" 'this directory can be different in your case.
My_Process_Info.CreateNoWindow = True ' Show or hide the process Window
My_Process_Info.UseShellExecute = False ' Don't use system shell to execute the process
My_Process_Info.RedirectStandardOutput = True ' Redirect (1) Output
My_Process_Info.RedirectStandardError = True ' Redirect non (1) Output
My_Process.EnableRaisingEvents = True ' Raise events
My_Process.StartInfo = My_Process_Info
My_Process.Start() ' Run the process NOW
Dim Process_ErrorOutput As String = My_Process.StandardOutput.ReadToEnd() ' Stores the Error Output (If any)
Dim Process_StandardOutput As String = My_Process.StandardOutput.ReadToEnd() ' Stores the Standard Output (If any)
' Return output by priority
If Process_ErrorOutput IsNot Nothing Then Return Process_ErrorOutput ' Returns the ErrorOutput (if any)
If Process_StandardOutput IsNot Nothing Then Return Process_StandardOutput ' Returns the StandardOutput (if any)
Catch ex As Exception
Return ex.Message
End Try
Return "OK"
End Function
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
'Usage:
'Get the list of connected devices.
MsgBox(adb("/c adb devices"))
'Connect your phone wirelessly using wifi (required phone I.P)
MsgBox(adb("/c adb disconnect 192.168.xx.xx:5555"))
'Get the list of connected devices.
MsgBox(adb("/c adb devices"))
'Put your phone on airplane mode.
MsgBox(adb("/c adb shell settings put global airplane_mode_on 1"))
End Sub
Related
I need to specifically use Windows 10 Powershell, not gitbash or cygwin or CMD, as other answers on SO have provided. I need to be able to use wildcards. I need to be able to push from Windows to Android to a specific folder using wildcards (not entire folder at a time as other answers on SO have provided).
Ex: adb push *.png /sdcard/Android/data/myapp/files
Ex: adb pull /sdcard/Android/data/myapp/files/h*.txt
Apologies if this has been answered, I have yet to find this specific answer.
You can leverage loops in powershell to call adb command separately for each file. Get the files you want to push or pull, loop through and call adb for each.
$adb = 'C:\temp\platform-tools\adb.exe'
$local = 'C:\temp\testfiles'
$remote = '/sdcard/Android/data/myapp/files'
function push-adbfiles {
param ()
# use Get-ChildItem to capture which files to push
$files = Get-ChildItem -file $local\*.png
# loop using ForEach-Object and call adb push command for each
$files | ForEach-Object {
& $adb push $_ $remote
}
}
function pull-adbfiles {
param ()
# use nix find command to find and return full path of matching files
$files = & $adb shell find "$remote/h*"
# loop through files running adb pull on each
$files | ForEach-Object {
& $adb pull $_ $local
}
}
I am writing a simple app using react native to make some file operations done automatically. I have tried packages like strong text react-native-fs, but I found that there are some files/folders that can not be read using
RNFS.ls(PATH).
Trying to list files in that folder will throw an exception.
However, these files can be displayed using ls command in adb shell. So I am wondering if there is a way that we can run shell commands in react native like we make some system calls in java/python?
Thanks
Write your own Native Module.
You can easily run a shell command from Java and call it from React Native using React Native's Native Modules. You can find more information here:
https://facebook.github.io/react-native/docs/0.60/native-modules-android#callbacks
And for your Java command, you'd want to use something like this:
String command = "ls " + path; // Where path is your desired path.
Runtime runtime = Runtime.getRuntime();
Process result = runtime.exec( command );
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader( result.getInputStream() ) );
String[] parts = bufferedReader.readLine().split( "\\s+" );
#flyskywhy/react-native-android-shell works well even with root command e.g.
AndroidShell.executeCommand('su -c ifconfig eth0 down; su -c ifconfig eth0 hw ether 19:21:19:49:20:21; su -c ifconfig eth0 up', (result) => {
console.log(result)
});
So, I need to copy a file to /system, and have to use shell commands, because the application is not running with enough privileges (and is not even installed to /system/apps at that time) - so its impossible to write to /system directly.
String cmd = String.format("\"/bin/sh -c \'cp %s %s'", tempPath, out);
p = Runtime.getRuntime().exec(new String[] { "su", "-c", cmd });
However, SuperSU pop-up informs me, that following application was granted to run as root:
/bin/sh -c _cp %s %s_.
So ' are replaced with _, and eventually command takes no effect.
What is a proper way to run a command having so much quotes ("" and '' for a single argument to su)?
I know of using su's stdin to run commands separated by \n, but it seems to be having its own problems (and was not working too).
If you're calling through SuperSU, there are a ton of pitfalls, and the recommended way is to use libsuperuser. See http://su.chainfire.eu/ for details.
I have this .php file sending commands to my android application:
I have tried working with:
Runtime.getRuntime().exec(commandLine);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
but the commands echo, pwd and some others are not working.
I get the following exception:
java.io.IOException: Error running exec(). Command: [pwd] Working Directory: null Environment: null
As far as I understand this is because there is not any shell environment.
Then I have tried writing in a .sh file the command I want and then execute the command this way:
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("sh /runCmds/shTest.sh");
InputStream is = proc.getInputStream();
and got solved the problem with pwd, echo and most of the commands.
But later on I realized that I want to keep the state of the commands I execute.
For example I want to change directory(cd data) and execute the command mkdir Apoel
And here is when I face my problem. What to do?
I came up with another idea:
Make a shell script (.sh) and each time the user wants to execute a command append the new command in it (and run the hole script(.sh) again). But I think is not a very good way to do it!
Is there any easy way to it? Can my application open a terminal easily?
Here is a code I found for a Terminal Emulator, but it is too complicated!
https://github.com/jackpal/Android-Terminal-Emulator
An interactive shell is one which remains running, waiting for new commands which it receives from stdin, while producing it's output to stdout and stderr - as a result, it's environment including any changes is retained for the duration of the session. For the shell to be useful to a user, stdin, stoud, stderr need to be connected through to the user - via the console, a serial line, or xterm, etc.
On Android, typically what you do is hook onto the pipes corresponding to stdin, stdout, stderr for the shell process that you've created, and use them to push in commands provided by your java program and accept output for your program to interpret/display.
The idea of creating a script and running it would only work in the case where all the commands are entered before any of them execute.
First, some background. On any Posix system, in the shell, there are 2 types of commands:
Internal commands (pwd,cd,echo)
external commands (ls,cp,mv, sometimes echo as well)
All the directory context commands (cd,pwd etc) are commands implemented inside the shell and thus require the shell to remain running, if the changes are to hold (for eg. cd /data/local/tmp).
On the other hand, external commands are standalone and can run indepenedently, but acquire their directory context from their parent process (in most cases, the shell).
Now to solve the problem. Yes, using a script is a good idea, but it is painful to implement, as it requires an overhead of file editing. However, we can use the shell to create a script on the fly and execute it using the -c option. For example:
/system/bin/sh -c 'cd /data/local/tmp; touch abc; cp abc def; cd /; rm /data/local/tmp/abc'
In summery:
String sPrefix="/system/bin/sh -c 'cd someplace;";
String sInputCmd=getCommand(); // this is simulating your command input
String sPostfix="'";
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(sPrefix+sInputCmd+sPostfix); // sh -c 'cd someplace; echo do something'
InputStream is = proc.getInputStream();
However, this does not give us the capability to set a directory context, so we need to simulate that. Directory contexts can be added by using the Runtime.exec(String command, String[] envp, File dir) method. With this we have the possibility of maintaining directory
context between commands. But how do we actually do that? One solution is to append pwd to the command and take the last line of the output as the new directory context. Thus
String sPath = "/"; // start in root directory
String sPrefix = "/system/bin/sh -c 'cd someplace;";
String sInputCmd; // this is simulating your command input
String sPostfix = ";echo;pwd'";
Runtime rt = Runtime.getRuntime();
while(!(sInputCmd=getCommand()).equals("")) {
File dir= new File(sPath);
Process proc = rt.exec(sPrefix+sInputCmd+sPostfix, NULL, dir);
InputStream is = proc.getInputStream();
// Do processing on input.
sPath= last_line_of_is ;
}
Finally, the last option is to integrate one of the terminal emulators into you app.
[1] http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#exec%28java.lang.String,%20java.lang.String%5B%5D,%20java.io.File%29
We have an android device and as part of testing I need to excute a console test application on the target device. If the test application detects an error it returns -1.
I can use adb shell to run the test applications remotely on the target but I can't find a way of getting back the return code. I need this so I that I can build this into an automated test suite.
I could try grepping the console output for some failure text but that is a bit grubby. Does anyone know of a more elegant solution?
This is a workaround to get the exit code:
adb shell '{your command here} > /dev/null 2>&1; echo $?'
This is a wrapper around adb in Ruby:
def adb(opt)
input = "#{adb_command} #{opt[:command]} #{opt[:params]}"
puts "Executing #{input}...\n"
output = nil
exit_code = 0
def wait_for(secs)
if secs
begin
Timeout::timeout(secs) { yield }
rescue
print 'execution expired'
end
else
yield
end
end
wait_for(opt[:timeout]) do
case opt[:command]
when :install, :push, :uninstall
output, exit_code = `#{input}`, $?.to_i
when :shell
input = "#{adb_command} shell \"#{opt[:params]}; echo \\$?\""
output = `#{input}`.split("\n")
exit_code = output.pop.to_i
output = output.join("\n")
else
raise 'Error: param command to adb not defined!'
end
end
return if opt[:ignore_fail] and output =~ /#{opt[:ignore_fail]}/
raise output unless exit_code == 0
end
You could use Facebook's fb-adb, a "A better shell for Android devices" which "propagates program exit status instead of always exiting with status 0".