How to easily "Show Layout bounds" for Android debugging? - android

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

Related

Android: How to process output of Runtime.getRuntime().exec() calling dumpsys on rooted phone

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());

Android: Child process (logcat) keeps running after parent process (app) died

our Android app spawns a logcat shell process and then reads its result for processing.
However, when the app stops (e.g. when restarted after recompilation during development), the logcat process will keep running. Here's an example of this behaviour:
processes = new ArrayList<Process>();
try {
processes.add(Runtime.getRuntime().exec("logcat -v time"));
processes.add(Runtime.getRuntime().exec("logcat -v time"));
processes.add(Runtime.getRuntime().exec("logcat -v time"));
processes.add(Runtime.getRuntime().exec("logcat -v time"));
} catch (IOException e) {
// oh no!
}
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
for (Process p : processes) {
p.destroy();
}
};
});
Add this to the onCreate() method of a test app, start it, then force-stop it using the settings manager. The child processes will keep running, now with a parent-id of 1.
In How to kill logcat process initiated by Android application? it was suggested to use ProcessBuilder, but that wasn't a solution and the process will keep running, too.
In Stop child process when parent process stops it was suggsted to use a shutdown hook - that doesn't work either as demonstrated above.
Thanks!
What you could do is spwaning another script of which the sole purpose is to watch your Java program. Whenever it dies, kill all of its children too.
A fragile example:
int pid = android.os.Process.myPid();
String script = "while [ -d /proc/" + pid + " ];do sleep 1;done; killall logcat";
Process p = Runtime.getRuntime().exec("/system/bin/sh", "-c", script);
This assumes that your process does not run as root, thereby only killing its own logcat processes. In your shutdown function, you should first kill the other processes (logcat) and then run p.destroy(); to stop this killer script.
The script above can be improved by removing the use of killall. Instead, get the process IDs of your logcat processes using Reflection (this answer points to http://www.golesny.de/p/code/javagetpid) and pass them to kill.

How to Programmatically press a button on Install/UnInstall APK Screen in android

Basically I want to install/uninstall an app on my android device from a remote Server.
I send a specific message (such as install or uninstall) from the remote server to my device.
But when the device initiates the process a system genrated Intent will start and shows the message below.
The OK button must be pressed in order to continue the process.
How can I programmatically press this button from the remote server and continue the process?
Hopefully you understand what I want to explain.
Any suggestions or ideas?
I'm afraid that this is possible only from play store. Click on the recycle bin, but not for external apps.
You can only ask the system to uninstall an app. Here's the reference.
Also, as pointed out in the comments:
When you open a dialog, the choice is user-driven.
It's against security guidelines.
I am looking the same solution for uninstalling any application by sending a SMS from server.
Bellow I'm giving some sample code it may help you.But you need your device as rooted one.
For rooting your device please download s/w from bellow link
http://forum.xda-developers.com/showthread.php?t=803682
The code is
public class MainActivity extends Activity {
Context context;
// boolean isEnabled;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Uninstall();
}
private void Uninstall() {
Process process;
try {
process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes("mount -o remount,rw -t rfs /dev/stl5 /system; \n");
os.writeBytes("rm -r /system/app/ActionsContentViewExample.apk; \n");
os.writeBytes("mount -o remount,ro -t rfs /dev/stl5 /system; \n");
} catch (IOException e) {
e.printStackTrace();
}
}
}

Android : How to enable or disable ADB? [duplicate]

I'm trying to enable ADB (USB debugging) only when my application is running and disabling it when my application is not. I have full access to the phone and it is rooted, su available, etc., but I cannot find a way to do the toggling.
What I've tried so far:
Process proc = Runtime.getRuntime().exec(new String [] { "su", "-c", "setprop", "persist.service.adb.enable", "0"});
proc.waitFor();
Process proc2 = Runtime.getRuntime().exec(new String [] { "su", "-c", "stop", "adbd"});
proc2.waitFor();
This however causes the phone to enter a reboot loop instantaneously.
The code that works is easy:
Settings.Secure.putInt(getContentResolver(),Settings.Secure.ADB_ENABLED, 0); // 0 to disable, 1 to enable
Edit/Update:
Thanks to #MohanT for the following update:
Settings.Global.putInt(getContentResolver(),Settings.Global.ADB_ENABLED, 0); // 0 to disable, 1 to enable
However, the app needs to be a system app to be able to use this. To get out of having to sign it, build a custom rom, etc.. I did the following to get it to be a system app.
First, I installed it regularly using eclipse, then adb shell:
> su
# mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system
# cat /data/app/filename.apk > /system/app/filename.apk
# mount -o remount,ro -t yaffs2 /dev/block/mtdblock3 /system
# reboot
You can achieve by following next steps:
Check whether ADB is currently enabled. To do that you can use a relevant global constant:
Settings.Global.ADB_ENABLED for API 17 and above.
Settings.Secure.ADB_ENABLED prior to API 17.
Use implicit Intent with Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS action to open developers options, where user can enable or disable ADB.
Code example:
Java
public static final int API = Build.VERSION.SDK_INT;
public static final int ENABLED=1, DISABLED=0;
public static boolean adbEnabled(Context context){
if(API>16)
return ENABLED == Settings.Global.getInt(context.getContentResolver(), Settings.Global.ADB_ENABLED,DISABLED);
else
return ENABLED == Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.ADB_ENABLED,DISABLED);
}
public void checkAdb(Context context){
//if ADB disabled
if(!adbEnabled(context)){
//open developer options settings
Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
context.startActivity(intent);
}
}
Kotlin
val API = Build.VERSION.SDK_INT
val ENABLED = 1
val DISABLED = 0
fun adbEnabled(context: Context): Boolean {
return if (API > 16)
ENABLED == Settings.Global.getInt(context.contentResolver, Settings.Global.ADB_ENABLED, DISABLED)
else
ENABLED == Settings.Secure.getInt(context.contentResolver, Settings.Secure.ADB_ENABLED, DISABLED)
}
fun checkAdb(context: Context) {
//if ADB disabled
if (!adbEnabled(context)) {
//open developer options settings
val intent = Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS)
context.startActivity(intent)
}
}
Just for reference:
Prior to API 3 (probably no longer relevant) Settings.System.ADB_ENABLED was used.
Chris's answer is correct except the ADB_ENABLED field in Secure class has been depreciated and the string has been moved to Global class. So you can use below command -
Settings.Global.putInt(getContentResolver(),Settings.Global.ADB_ENABLED, 0); // 0 to disable, 1 to enable
From my experiences using setprop doesn't always work reliable, and might even conflict with the Settings > Applications > Development > USB Debugging option. Besides that it might be irritating for instance if USB debugging is enabled but adb doesn't work etc. Therefore using Settings.Secure.ADB_ENABLED is the prefered way... plus you always have the notification in the status panel.
If you don't want to go through the hassle to install your app on system partition when only trying to access Settings.Secure.ADB_ENABLED then you can instead rely on another app that is doing this work already:
This app is called ADB Toggle. You can find it in Google Play:
https://play.google.com/store/apps/details?id=com.ramdroid.adbtoggle
The library to access USB debug settings via ADB Toggle is available here:
https://github.com/ramdroid/AdbToggleAccessLib

Looking to enable and disable (toggle) ADB or USB debugging using command line or in app

I'm trying to enable ADB (USB debugging) only when my application is running and disabling it when my application is not. I have full access to the phone and it is rooted, su available, etc., but I cannot find a way to do the toggling.
What I've tried so far:
Process proc = Runtime.getRuntime().exec(new String [] { "su", "-c", "setprop", "persist.service.adb.enable", "0"});
proc.waitFor();
Process proc2 = Runtime.getRuntime().exec(new String [] { "su", "-c", "stop", "adbd"});
proc2.waitFor();
This however causes the phone to enter a reboot loop instantaneously.
The code that works is easy:
Settings.Secure.putInt(getContentResolver(),Settings.Secure.ADB_ENABLED, 0); // 0 to disable, 1 to enable
Edit/Update:
Thanks to #MohanT for the following update:
Settings.Global.putInt(getContentResolver(),Settings.Global.ADB_ENABLED, 0); // 0 to disable, 1 to enable
However, the app needs to be a system app to be able to use this. To get out of having to sign it, build a custom rom, etc.. I did the following to get it to be a system app.
First, I installed it regularly using eclipse, then adb shell:
> su
# mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system
# cat /data/app/filename.apk > /system/app/filename.apk
# mount -o remount,ro -t yaffs2 /dev/block/mtdblock3 /system
# reboot
You can achieve by following next steps:
Check whether ADB is currently enabled. To do that you can use a relevant global constant:
Settings.Global.ADB_ENABLED for API 17 and above.
Settings.Secure.ADB_ENABLED prior to API 17.
Use implicit Intent with Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS action to open developers options, where user can enable or disable ADB.
Code example:
Java
public static final int API = Build.VERSION.SDK_INT;
public static final int ENABLED=1, DISABLED=0;
public static boolean adbEnabled(Context context){
if(API>16)
return ENABLED == Settings.Global.getInt(context.getContentResolver(), Settings.Global.ADB_ENABLED,DISABLED);
else
return ENABLED == Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.ADB_ENABLED,DISABLED);
}
public void checkAdb(Context context){
//if ADB disabled
if(!adbEnabled(context)){
//open developer options settings
Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
context.startActivity(intent);
}
}
Kotlin
val API = Build.VERSION.SDK_INT
val ENABLED = 1
val DISABLED = 0
fun adbEnabled(context: Context): Boolean {
return if (API > 16)
ENABLED == Settings.Global.getInt(context.contentResolver, Settings.Global.ADB_ENABLED, DISABLED)
else
ENABLED == Settings.Secure.getInt(context.contentResolver, Settings.Secure.ADB_ENABLED, DISABLED)
}
fun checkAdb(context: Context) {
//if ADB disabled
if (!adbEnabled(context)) {
//open developer options settings
val intent = Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS)
context.startActivity(intent)
}
}
Just for reference:
Prior to API 3 (probably no longer relevant) Settings.System.ADB_ENABLED was used.
Chris's answer is correct except the ADB_ENABLED field in Secure class has been depreciated and the string has been moved to Global class. So you can use below command -
Settings.Global.putInt(getContentResolver(),Settings.Global.ADB_ENABLED, 0); // 0 to disable, 1 to enable
From my experiences using setprop doesn't always work reliable, and might even conflict with the Settings > Applications > Development > USB Debugging option. Besides that it might be irritating for instance if USB debugging is enabled but adb doesn't work etc. Therefore using Settings.Secure.ADB_ENABLED is the prefered way... plus you always have the notification in the status panel.
If you don't want to go through the hassle to install your app on system partition when only trying to access Settings.Secure.ADB_ENABLED then you can instead rely on another app that is doing this work already:
This app is called ADB Toggle. You can find it in Google Play:
https://play.google.com/store/apps/details?id=com.ramdroid.adbtoggle
The library to access USB debug settings via ADB Toggle is available here:
https://github.com/ramdroid/AdbToggleAccessLib

Categories

Resources