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'"
Related
I am working on a small proof of concept on a rooted phone, which relys on being able to read dumpsys output.
If I call dumpsys on my (rooted) phone running Android 11 like this, using adb:
adb shell dumpsys telephony.registry | grep "mCi="
I get a pretty long printout. The grep filters for lines containing cell tower IDs, but that shouldn't e important here (it's just an example). Now I'm trying to execute the same command inside a very simple app, and log its output, like this:
private fun test() {
try {
val process = Runtime.getRuntime().exec("su dumpsys telephony.registry | grep \"mCi=\"")
val bufferedReader = BufferedReader(InputStreamReader(process.inputStream))
val string = bufferedReader.readText()
Timber.d("output: $string")
bufferedReader.close() // do I need this?
} catch (e: IOException) {
// handle Exception
}
}
I get no output at all (string length is 0). If I replace my process command with something simple like this: Runtime.getRuntime().exec("echo 'abcde'") the output is logged as intended (output: 'abcde').
I also tried shortening the possible output, in case that was the problem by appending --max-count=1, to have grep only put out the first found line. Again, it works using adb, does not work in code.
what am I doing wrong?
(I am using Timber to print my logs, if anyone doesn't know what that line is in the xample.)
The first thing you should do is to log the stderr stream that is available for your process as well. This will give you information about what is wrong with your command.
Your command is not correctly processed as it is seen as one command. The reason is explained in this answer.
The solution is to use a String[] as an argument of exec and explicitly execute the command with the shell. I wrote some code that executes your command, but it is in Java on an unrooted device. Still, it generates output and grep works.
String[] arrayCommand = {"sh", "-c","dumpsys telephony.registry | grep \"permission\""};
Runtime r = Runtime.getRuntime();
Process process = r.exec(arrayCommand);
String stdoutString = convertInputStreamToString(process.getInputStream());
String stderrString = convertInputStreamToString(process.getErrorStream());
I'm trying to run adb commands programmatically from inside an Android priviledged app (apk file uploaded to priv-app folder, privapp-permissions-platform.xml file uploaded to /etc/permissions/.
private fun executeAdbCommand() {
val commandStart = "am start -n com.abc.bcd/com.abc.bcd.MainActivity"
val process = Runtime.getRuntime().exec(commandStart)
val bufferedReader = BufferedReader(InputStreamReader(process.inputStream))
val commandBattery = "dumpsys battery set level 20"
val processBattery = Runtime.getRuntime().exec(commandBattery)
val bufferedReaderBattery = BufferedReader(InputStreamReader(processBattery.inputStream))
val commandBack = "input keyevent ${KeyEvent.KEYCODE_BACK}"
val processBack = Runtime.getRuntime().exec(commandBack)
val bufferedReaderThree = BufferedReader(InputStreamReader(processBack.inputStream))
}
The first two commands produce no result. The third one is actually pressing the Back Button.
When I run the first two commands from a PowerShell windows they are both executed correctly:
adb shell am start -n com.abc.bcd/com.abc.bcd.MainActivity is starting the mentioned activity,
adb shell dumpsys battery set level 20 is setting the emulator's battery to 20%.
I am targeting Android 10 (API level 29) - is this the expected behaviour of the system? What is the particular reason the first two commands are getting discarded (no error log is generated) and the third one is getting executed? Is there any way of getting the first two commands running (might this be a missing permission or something similar)?
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
I want to watch the layout of App without boring tap and tap.
I tried adb shell setprop debug.layout true but didn't work unless reboot or open setting.
This may caused by setting haven't update.
I tried to writing a little App with code SystemProperties.set("debug.layout", "true") , no use too.
Maybe the app's authority…
Sorry for my poor English and appreciation for help :p
This works for me:
adb shell setprop debug.layout true
adb shell service call activity 1599295570
After we have enabled Show layout bounds using adb shell setprop debug.layout true, we have to poke the SystemProperties to see the changes
as Show layout bounds QS Tiles does:
#Override
public void onClick() {
setIsEnabled(getQsTile().getState() == Tile.STATE_INACTIVE);
new DevelopmentSettings.SystemPropPoker().execute(); // Settings app magic
refresh();
}
Here's the original method from AOSP source:
public static class SystemPropPoker extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
String[] services = ServiceManager.listServices();
for (String service : services) {
IBinder obj = ServiceManager.checkService(service);
if (obj != null) {
Parcel data = Parcel.obtain();
try {
obj.transact(IBinder.SYSPROPS_TRANSACTION, data, null, 0);
} catch (RemoteException e) {
} catch (Exception e) {
Log.i(TAG, "Someone wrote a bad service '" + service
+ "' that doesn't like to be poked: " + e);
}
data.recycle();
}
}
return null;
}
}
The number 1599295570 is called SYSPROPS_TRANSACTION
Reference: https://github.com/dhelleberg/android-scripts/blob/master/src/devtools.groovy
UPDATED: I created this app to add many developer toggle to the quick settings for Android 7.0+
You don't need to start the settings app. Just exit your app, set the property, and start your app.
adb shell am force-stop com.company.appname ; adb shell setprop debug.layout true ; adb shell monkey -p com.company.appname -c android.intent.category.LAUNCHER 1
I found a DevelopQuickSetting tool can easily make this.
https://github.com/kyze8439690/DevelopQuickSetting
and the core code translate to adb shel is:
adb shell setprop debug.layout true
adb shell service check SurfaceFlinger
This tool works fine.
You need to install groovy before launch this program.
https://github.com/dhelleberg/android-scripts
Here is my fish shell function that will also help you to choose from multiple devices with fzf. save it in ~/.config/fish.functions/ and use it like this:
and if you have more than one device it will prompt to select one with fzf
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.");