public static final TAG = "Legendry Eagle";
Issue: I want to see logs of "Legendry Eagle" from the commandline.
I tried:
adb logcat -s "Legendry Eagle"
adb logcat -s <Legendry Eagle>
But Still it is not working.
If you only want to show logcat for a specific TAG, do it like this:
adb logcat YourTAGHere:Priority *:S
The *:S is important, as it sets all other tags to silent. If I want to track only my MainActivity tag at Verbose level, the syntax would look like this.
adb logcat MainActivity:V *:S
Edit:
I found no good way of filtering out tags with spaces. LegendryEagle works fine, but I was not able to filter out Legendry Eagle
If the standard adb logcat -s tagname doesn't work, you can always pipe the output of adb to find to filter what you need, something like
adb logcat | find "Legendry Eagle"
This passes the entire logcat to DOS find command, which in turn filters out rows containing Legendry Eagle string.
adb logcat | grep "your tag"
will only display logs with "your tag"
Answer is very simple . Please remove space between two words and try again.
public static final TAG = "LegendryEagle";
adb logcat -s "LegendryEagle"
and see the logcat . You got your answer.
use this command adb logcat *:W and read this. http://developer.android.com/tools/debugging/debugging-log.html
Assuming you are using Eagle as the logging tag, use this:
adb logcat Eagle:* *:s
as I understand the Eagle:* means to turn on all logs for the Eagle tag, and the *:s means to make all other tags silent
I personally find the eclipse logcat view much easier to use than the command line, it has different colors for different levels of logs, and you can create a filter and save it, it'll stay there forever until you delete that filter
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());
#Override
public void run() {
try {
exec = Runtime.getRuntime().exec("getevent | grep event1");
InputStreamReader is = new InputStreamReader(
exec.getInputStream());
String s;
BufferedReader br = new BufferedReader(is);
Log.i("br.readLine", " = " + br.readLine());
while ((s = br.readLine()) != null) {
Log.i("s2", " " + s);
}
// is.close();
// exec.destroy();
} catch (IOException e) {
Log.e("thread ioexception", " " + e.getCause());
e.printStackTrace();
}
}
I tried logging the results of the command to getevent in thread.
But put the results of the command in the buffer, the buffer is empty(null).
Perhaps as soon as this command is executed, it seems that ends without receiving any input.
While maintaining thread I want to continue to be run getevent command.
How this can be done? any idea?
Edit
getErrorStream()
getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]
-t: show time stamps
-n: don't print newlines
-s: print switch states for given bits
-S: print all switch states
-v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)
-d: show HID descriptor, if available
-p: show possible events (errs, dev, name, pos. events)
-i: show all device info and possible events
-l: label event types and names in plain text
-q: quiet (clear verbosity mask)
-c: print given number of events then exit
-r: print rate events are received
GetErrorStream comes out as the result of a manual getevent.
If the instruction is to operate normally, it would not have been any log (the other normal commands actually did. Ex) ls )
I think getevent command seems to have caused various problems since the CALLBACK method.
Edit: I think now I got your problem. The pipe behavior is not cross-platform, as it is a functionality of the executed shell. Thats why it is not working as you expect in java. Try to use a script like the following to spawn a new shell which implements the pipe function as you expect.
String[] cmd = {
"/system/bin/sh",
"-c",
"getevent | grep event1"
};
I'll keep the rest of the answer, as it could help somebody.
I think you are executing getevent | grep event1 without the correct permissions. At least you need to be root user or in input group.
Edit: I still think you do not have the correct permissions. Of course, for running getevent no special permissions are necessary, as it can be executed by everyone. But keep in mind, that getevent reads /dev/input/*, which has the following permissions:
crw-rw---- root input 13, 64 2016-01-24 21:34 event1
Try to make sure your application is really allowed to read event1.
You should also try to use getErrorStream() instead of getInputStream() to see what is going wrong.
Regarding the second part of your question, I am not sure I understand it correctly. You want to execute the command periodically in the same thread right? (I did not, see edit below.)
Then you can simply run your code in a while(1) loop and sleep as long as you want. A bit more advanced would be to use a Timer and a TimerTask.
If you want to control every loop from outside your Thread you can simply use Object.wait() and Object.notify(). Another, also more advanced, possibility is to use Thread pools. The interesting one for you could be the SingleThreadExecutor.
Edit: As I thought, I did not understood you correctly. However, I'll keep the second part of my answer, maybe it helps someone else.
For your use case your code should work correctly. I think it does return immediately because an error is happening. As described above, try to use getErrorStream() to see what is actually happening.
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();
}
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 am using windows cmd terminal to output logs of my application using following command:
adb.exe logcat | find "%part_of_my_apps_name%"
however, not all logs appear in the output. Only messages like this one:
I/AppService(10597): Received start id 1: Intent { cmp=package_name/.AppService(has extras) }
And in my AppService I have the following code:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Received start id " + startId + ": " + intent);
Log.i(TAG, "Test");
So what am I doing wrong?
UPD: I asked a bit wrong question. I actually used part of my app's name, not package, so it MUST appear in the log output.
Depending on what your TAG variable is, you use the command
adb.exe logcat -s "[tagname]"
For example if in my code, my TAG was declared as:
public static final String TAG = "com.myapp";
my LogCat would be
adb.exe logcat -s "com.myapp"
It also appears the quotes are optional.
Logcat output is not associated with the package name, but with the string TAG you are using in your code. You could change all your tags to be your package name, or you could explicitly add your package name to the message in each Log.i/w/e/v() line, and then you will get the behavior you want. However, I would actually for with #A--C suggestion instead, as it allows you to have more granular filtering of the output of specific classes only.
I used a part of app's name, however, because "find" is basically case sensitive it did show me only that particular output ( name appeared in package name ) , so I came up with the following command:
adb.exe logcat -v time | find "%part_of_my_apps_name%" /I