Switch from native-activity to a normal java activity - android

I am creating a game for android. The native activity is used for the main part of the game but i want to be able to switch to a java activity. I've searched almost all android header files but i cant find any function which allows me to switch activity.
Is there some way i can start a java activity?

The am command from the shell can be used to send Intents to Actvities. In the source code of SuperUser you can find, for instance:
char sysCmd[1024];
sprintf(sysCmd, "am start -a android.intent.action.MAIN -n com.koushikdutta.superuser/com.koushikdutta.superuser.SuperuserRequestActivity --ei uid %d --ei pid %d > /dev/null", g_puid, ppid);
if (system(sysCmd))
return executionFailure("am.");

Related

ADB starting activity with extra string data [duplicate]

This question already has an answer here:
Send Intent to Start Activity With String Extras Via ADB
(1 answer)
Closed 1 year ago.
I am executing the following from ADB:
PS C:\> adb shell am start -a android.intent.action.MAIN -n boha.notify/.MainActivity -e primaryheader "One Two" -e primarytext "Primary text"
Starting: Intent { act=android.intent.action.MAIN pkg=Two cmp=boha.notify/.MainActivity (has extras) }
Warning: Activity not started, its current task has been brought to the front
PS C:\>
My application is setup to properly handle the new intent request without restarting the already running activity. I've overridden onNewIntent() as required. It's shown below:
#Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
Log.d( "AGENT", "NEW INTENT Extra data = " + intent.getStringExtra("primaryheader"));
String strPrimaryHeader = intent.getStringExtra("primaryheader");
String strPrimaryText = intent.getStringExtra("primarytext");
String strSecondayHeader = intent.getStringExtra("secondaryheader");
String strSecondaryText = intent.getStringExtra("secondarytext");
}
When I check the logcat I see that the extra data strings I'm passing in aren't being received correctly. Only the first word of each string is correct.
See below:
09-13 18:30:36.583 12248-12248/? D/AGENT: NEW INTENT Extra data = One
Why is the activity new intent only receiving "One" instead of "One Two"?
Am I not using the correct ADB am command parameters?
Use --es for string extras
adb shell am start -a android.intent.action.MAIN -n boha.notify/.MainActivity --es primaryheader "One Two" --es primarytext "Primary text"
I have explained the root cause multiple times before. It's because you have multiple sub shells. And when the outer shell (in your case powershell) parses the command it eats the " (i.e. uses them for properly splitting the command into separate command line parameters). But this information (that your multi word string is a single parameter) gets lost by the time the command reaches the inner shell (the /bin/sh of your android device). So as the result it launches the am command with every word being a separate parameter.
The easiest way to mitigate that is to double-quote the whole adb shell subcommand and use single quotes for the internal strings:
PS C:\> adb shell "am start -a android.intent.action.MAIN -n boha.notify/.MainActivity -e primaryheader 'One Two' -e primarytext 'Primary text'"

Android- performing su commands programatically does not work

I need my app to perform some su commands programatically (phone is rooted).
When done using adb, the commands work.
For instance:
su -c "mkdir /sdcard/testdir" creates a directory called "testdir" in /sdcard.
When I call:
p = Runtime.getRuntime().exec("su -c \"mkdir /sdcard/testdir\"");
p.waitFor();
It just moves on and no change happens.
I tried reading the input:
DataInputStream dis = new DataInputStream(p.getInputStream());
while((temp = dis.readLine())!=null)
Log.d(ctx.TAG,"shell:"+temp);
But it reports nothing (loop does 0 iterations).
Has anyone ever faced this issue before? How can it be solved?
Needless to day, non-su commands do work programatically with this method.
Note: I gave mkdir as an example (I know it doesn't necessarily require su). I need a lot of varied commands to be performed under su
Thank you!
EDIT: when I call su -c "id" programatically, there's output that uid=0.
I can get stuck on a problem for days, and the moment I gather up the courage to ask about it on StackOverflow, it is solved within minutes.
The fix is:
p=Runtime.getRuntime().exec("su");
DataOutputStream dos = new DataOutputStream(p.getOutputStream());
dos.writeBytes("mkdir /sdcard/testdir\n");
dos.writeBytes("exit\n");
dos.flush();
dos.close();
p.waitFor();
Don't forget \n at the end of each command you write to the DataOutputStream, as it will not work without it.
You wrote that you "need varied commands to be performed under su". Note that the use of "Runtime.exec()" is discouraged by Chainfire, the developer of the most famous SuperSU root app.
It is tempting to use Runtime.getRuntime().exec("su -c [command]");, but you should be aware that [command] should be a single parameter, and thus may require quoting. Unfortunately both quoting the [command] parameter as well as passing the paramaters as separate variables to either Runtime.exec() or ProcessBuilder does not work consistently across all Android versions, and thus this construct should be avoided entirely. It is not impossible to do this right - but there's a high risk of problems.
See the How to SU Document. So you might want to follow his recommendation here:
3.2. Making the call
A common method to call su that avoids the known issues listed above is by creating an interactive shell and piping commands to it. This is done by calling Runtime.getRuntime().exec("su");, and retrieving input and output streams from the returned Process object. Doing this is a fairly straight-forward piece of code, but including the debug logs and checks it's a bit long to reproduce here.
The core code is located here: [libsuperuser :: Shell.java # GitHub]. Shell.run() is a generic call to run shell code, the following more specific (static) utility functions are the ones you will probably end up using:
List<String> Shell.SH.run(String command)
List<String> Shell.SH.run(List<String> commands)
List<String> Shell.SH.run(String[] commands)
List<String> Shell.SU.run(String command)
List<String> Shell.SU.run(List<String> commands)
List<String> Shell.SU.run(String[] commands)
The SH variants are used for a non-root shell, where the SU variants are used for a root shell. These calls return a List containing the output of the shell commands. If there was no output, the list is empty, but not null. The result is only null in case an error occured - including the user not granting your app su access. These are blocking calls.
Note that in debug compiles, all shell STDIN/STDOUT/STDERR will be logged to logcat, and these calls will (intentionally) crash your app if called from the main thread. The reason for this will be discussed in section 4. When to call su.
If you use double quotes, it will work:
su -c ""command with args""
You might be calling Runtime.getRuntime().exec() in main thread and p.waitFor() makes your main thread wait until it executes. Try calling in another thread, like the following snippet.
new Thread(){
#override
public void run(){
p = Runtime.getRuntime().exec("su -c \"mkdir /sdcard/testdir\"");
p.waitFor();
}.start();
}

Android shell get foreground app package name [duplicate]

This question already has answers here:
ADB - Android - Getting the name of the current activity
(13 answers)
Closed 5 years ago.
I'm using tasker to automate the SMS sending for which I need to check if the current foreground app package name is x. If it is x then do something else do something else. I tried to use pgrep but it returns the pid even when the app x is in the background. Is there a way to check from shell if x is in foreground?
Thanks
This worked for me:
adb shell dumpsys window windows | grep -E 'mCurrentFocus' | cut -d '/' -f1 | sed 's/.* //g'
com.facebook.katana
Updated answer for Android Q as mCurrentFocus was no longer working for me:
adb shell dumpsys activity recents | grep 'Recent #0' | cut -d= -f2 | sed 's| .*||' | cut -d '/' -f1
The accepted answer might give unexpected results in many cases.
Some UI elements (e.g., dialogs) will not show the package name on the mCurrentFocus (neither mFocusedApp) field. For example, when an app throws a dialog, the mCurrentFocus is often the dialog's title. Some apps show these on app start, making this approach unusable to detect if an app was successfully brought on foreground.
For example, the app com.imo.android.imoimbeta asks for the user country at start, and its current focus is:
$ adb shell dumpsys window windows | grep mCurrentFocus
mCurrentFocus=Window{21e4cca8 u0 Choose a country}
The mFocusedApp is null in this case, so the only way to know which app package name originated this dialog is by checking its mOwnerUID:
Window #3 Window{21d12418 u0 Choose a country}:
mDisplayId=0 mSession=Session{21cb88b8 5876:u0a10071} mClient=android.os.BinderProxy#21c32160
mOwnerUid=10071 mShowToOwnerOnly=true package=com.imo.android.imoimbeta appop=NONE
Depending on the use case the accepted solution might suffice but its worth mentioning its limitations.
A solution that i found to work so far:
window_output = %x(adb shell dumpsys window windows)
windows = Hash.new
app_window = nil
window_output.each_line do |line|
case line
#matches the mCurrentFocus, so we can check the actual owner
when /Window #\d+[^{]+({[^}]+})/ #New window
app_window=$1
#owner of the current window
when /mOwnerUid=[\d]+\s[^\s]+\spackage=([^\s]+)/
app_package=$1
#Lets store the respective app_package
windows[app_window] = app_package
when /mCurrentFocus=[^{]+({[^}]+})/
app_focus=$1
puts "Current Focus package name: #{windows[app_focus]}"
break
end
end

Qt/C++: interrupt QProcess arbitrarily with button (simulate ^c)

So I need to make a Qt Application (with GUI) that executes the "adb logcat" command (it's a log that keeps being generated until ^c is pressed).
I need a GUI button to make the process stop and pass the output to a Text Browser.
This is the code I use to get the QProcess output:
QProcess process;
process.start("adb logcat");
process.waitForFinished(-1);
QByteArray logcatOut = process.readAllStandardOutput();
ui->devicesOutput->setText(logcatOut);
Thank you
process.waitForFinished(-1);
would prevent your program of being executed further, till the process "adb" has finished.
So your GUI will be frozen.
You should define QProcess process as a class variable. Use QProcess
*process; instead of creating it on stack. (Best practice for all QObject derivates)
Declare a slot which handles clicked-signal of your button.
call process->terminate() in the slot.
use QProcess::terminate to stop running app

Execute commands via C code in Android

I want to execute the screenshot command "adb shell /system/bin/screencap -p /sdcard/img.png" into C. I was searching for the same and I got a solution for another command and I modified the command as
execl("/system/bin/screencap", "-p", "storage/sdcard0/screenShot.png", (char *)NULL);
but when I run my application and call method of above command, application gets crash.
How should I modify the "/system/bin/screencap -p /sdcard/img.png" command to run from C code.
Update after tom answer
Application is getting closed again and here is log
06-21 11:52:01.488: I/WindowState(279): WIN DEATH: Window{40fed2c0 u0 com.mytest.ndktestapplication/com.mytest.ndktestapplication.MainActivity}
06-21 11:52:01.498: I/ActivityManager(279): Process com.mytest.ndktestapplication (pid 7745) has died.
06-21 11:52:01.498: W/ActivityManager(279): Force removing ActivityRecord{40ea9ab8 u0 com.mytest.ndktestapplication/.MainActivity}: app died, no saved state
This is the expected result of exec() family functions.
What they do is replace the current program with the specified one. So bye-bye app.
To avoid that you would first need to call fork(), and then call exec() only in the child, something like this:
if (!fork()) {
// fork() returned zero, so we are in the child
execl...
}
You might also have to do some cleanup before calling the exec function.
Note however that you will not be able to take a screenshot from an app on most devices, as application code runs under a user id which lacks the permission to do so. But I seem to recall that there was a narrow period where some devices shipped without permission checks on this functionality, so it might work on those.
The invocation is
execl(path, arg0, arg1, ..., (char*) NULL);
The second argument, arg0, is the name the program is told was used to invoke it. The actual arguments given to the program only start at arg1.
So you should change your code to
execl("/system/bin/screencap", "screencap", "-p", "<pic>", (char *)NULL);

Categories

Resources