Run a shell command via QProcess on Android Platform - android

I cannot run any command via QProcess on Android platform. I am using Qt library. Can anyone explain how to run shell commands from my application on Android platform ?
QProcess process();
process.execute("ls");
bool finished = process.waitForFinished(-1);
qDebug() << "End : " << finished << " Output : " << process.errorString();
The process doesn't finish if I don't specify timeout. process.waitForFinished() returns false when I specify timeout let's say 10000 ms.

Your example code is faulty and it will not work on ANY platform!
ls command is not an exactable! This command is build into a shell program for example bash.
Another bug in your code is that QProcess::execute is a static function.
So final line doesn't have impact on process you have tried to start.
So your code should look like this:
QProcess process;
process.start("bash", QStringList() << "-c" << "ls");
bool finished = process.waitForFinished(-1);

You are using QProcess::execute() which is a static function. Quoting Qt documentation: "Starts the program command in a new process, waits for it to finish".
So what could happen in your code is:
QProcess process();
process.execute("ls"); // Start "ls" and wait for it to finish
// "ls" has finished
bool finished = process.waitForFinished(-1); // Wait for the process to finish, but there is no process and you could get locked here forever...
There are 2 ways to fix your code:
QProcess process();
process.start("ls"); // Start "ls" and returns
bool finished = process.waitForFinished(-1);
qDebug() << "End : " << finished << " Output : " << process.errorString();
or
QProcess::execute("ls");

Related

C++ code on Android - execl() function call failure

The Story - I got a script file on a rooted Android Wear device and I want to run it with my c++ code.
First I tried this int ret = system(/system/bin/sh /full/path/a.sh), it turned out that every time system() return with code 127 - command not exists error.
I found this workaround here: system is returning error 127 when called from c++ in linux and I do as #Nikhilendra said:
int ret = execl("/system/bin/sh","/system/bin/sh","/full/path/a.sh",(char*)NULL)
Now my c++ code crash at this line every time, even without return value, so I cant get any error code on this.
Any help is highly appreciated.
EDIT1:
The script a.sh itself runs correctly.
EDIT2:
My question can be understood as a follow-up of system is returning error 127 when called from c++ in linux
If you want to use one of the exec functions to mimic the system call, you have to fork a new child process first because the current process (image) is replaced by the one given in the exec call. That is, the exec will only return, if it failed.
I can't say, if the fork system call works on Android. But, you can check the exec call with this little example. I actually tested it on a Linux machine. EDIT: You may have to change the path of sh to /system/bin/sh.
The content of a.sh:
#!/bin/sh
echo "Hello World."
The content of the C++ test program (called it exec_test).
extern "C" {
#include <unistd.h>
#include <errno.h>
}
#include <iostream>
int main()
{
execl("/bin/sh","sh","./a.sh",NULL);
// execl only returns if it failed
std::cout << "errno: " << errno << std::endl;
return 0;
}
The output:
$ ./exec_test
Hello World.

Android ADB Tool, 'fork' doesn't work

Environment
Android 5.0 # Samsung Galaxy 5
ADB # Windows (x64)
Native ADB Commandline tool
Use-case
An application that forks and immediately exit
Problem description
While fork returns a propper pid_t of the newly created process, no actual process is being created, ( 'adb -d shell ps | findstr shell' shows no new process )
Code snippet
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "\n");
pid_t pid = fork();
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "STARTED, pid = %d\n", pid);
if (0 != pid)
return S_OK;// Exits the parent process
HRESULT hr;
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "Initializing\n");
if (FAILED(hr = Initialize(pBaseAddress, wPort, uiMaxMessageSize)))
return hr;
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "Running modal loop\n");
hr = m_spIOCP->DoModal();
OnCleanup(hr);
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "STOPPED, pid = %d\n", pid);
return S_OK;
Logcat output
I/ScreenCapSvc(29062):
I/ScreenCapSvc(29062): STARTED, pid = 29064
Additional info
If rather them immediately exiting the parent process I call eg. sleep(2) than the child process is properly forked, HOWEVER, While the parent process actually terminate, 'ADB -d shell' never exit ( stays hanging infinity ).
Related link: https://stackoverflow.com/questions/28277361/android-adb-tool-c11-stdthread-usage
What am I doing wrong? why does the process doesn't fork?

How to run adb commands in VB.NET

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

Python - How to hide output after killed specified process

now i try to create a python script to get Android logcats automatically
below seciton is part of my codes
logcat_process = subprocess.Popen('adb logcat -v time > logcat.log', shell=True)
time.sleep(5)
os.kill((logcat_process.pid)+1, signal.SIGKILL)
however, every time after os.kill terminate the process,
it will print message like
"/bin/sh: line 1: 13961 Killed: 9 adb logcat -v time > logcat.log"**
on the screen.
Does anybody have any idea how to hide this message?
I want the result print of script more simple and clear....
You can do something like this:
logcat_process = subprocess.Popen('adb logcat -v time > logcat.log', shell=True)
time.sleep(5)
save_stdout = sys.stdout
sys.stdout = open(r'/youlib..../trash.txt', 'w')
os.kill((logcat_process.pid)+1, signal.SIGKILL)
# regain stdout to screen
sys.stdout.close()
sys.stdout = save_stdout
It will divert the stdout to the trash.txt file at the kill operation.
redirect the stdout/stderr in python and add a filter.

ADB Error codes

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".

Categories

Resources