programmatically show the logcat within application of other applications - android

I need to read and filter logcat logs within my application, of others applications. I found other questions and the most useful if Read logcat programmatically within application.
So I tried to write my code, but the result is always the same, that is it returns the logcat logs that made until the application was started.
public void getLog() {
edLog.setText("");
Log.e("imgspa", "ciao");
try {
//Process logcat = Runtime.getRuntime().exec(new String[]{"logcat", "-d", "*:I"});
//Process logcat = Runtime.getRuntime().exec(new String[]{"logcat", "-d", "B4A:I"});
//Process logcat = Runtime.getRuntime().exec(new String[]{"logcat", "-d", "-v", "time", "-e", "*VFY*"});
//Process logcat = Runtime.getRuntime().exec(new String[]{"logcat", "-d", "-v", "time", "*:I"});
//Process logcat = Runtime.getRuntime().exec(new String[]{"logcat", "-d"});
Process logcat = Runtime.getRuntime().exec(new String[]{"logcat", "-d", "-v", "threadtime", "*:*"});
BufferedReader br = new BufferedReader(new InputStreamReader(logcat.getInputStream()));
String line;
final StringBuilder sb = new StringBuilder();
String separator = System.getProperty("line.separator");
sb.append("inizio");
sb.append(separator);
while ((line = br.readLine()) != null) {
sb.append(line);
sb.append(separator);
}
sb.append("fine");
edLog.setText(sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
As you can see I tried different solutions but no one can help me.
I need to get the logcat, where the application name is "B4A".
Let me point out that:
- I have a rooted device
- I already added the READ_LOGS permissions

As of JellyBean, you cannot access the log in logcat that was not add there by your application.
link

Since Android 4.1 it's no possible to read logs of other applications.
See an explanation
For rooted device you need to obtain the READ_LOGS permission manually
String pname = getPackageName();
String[] CMDLINE = { "su", "-c", null };
if(getPackageManager().checkPermission(android.Manifest.permission.READ_LOGS, pname) != 0) {
try {
CMDLINE[2] = String.format("pm grant %s android.permission.READ_LOGS", pname);
java.lang.Process p = Runtime.getRuntime().exec(CMDLINE);
int res = p.waitFor();
Log.d(TAG, "exec returned: " + res);
if (res != 0)
throw new Exception("failed to become root");
} catch (Exception e) {
Log.d(TAG, "exec(): " + e);
}
}
Or just try it with .exec("su -c logcat -d")

The change is that third party applications can no longer get the read logs permission, however every app can read the logs containing only the lines they have written, without needing any permission.
Unless you rooted you cannot do this since Jelly Bean. See this Android bug report and this related discussion. Quote:
img.simone For more query you have to read this
Hope it will help you!!

Related

Writing logcat output to a file periodically via background service in Android

I want to write logcat results to a file in the background via a service. I have created a service and used the following code for having the logcat results.
Process process = Runtime.getRuntime().exec("logcat -d");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
StringBuilder log = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
log.append(line);
}
Now with the above code, I am able to just write some of the logs only and if I remove the "-d" option then the service crashed.
You have to have the phone rooted with priveleges R/W to that now.
Grant permissions to READ_LOGS on Manifest.xml.
Then write this code in OnCreate() of the Activity
String pname = getPackageName();
String[] CMDLINE_GRANTPERMS = { "su", "-c", null };
if (getPackageManager().checkPermission(android.Manifest.permission.READ_LOGS, pname) != 0) {
Log.d(TAG, "we do not have the READ_LOGS permission!");
if (android.os.Build.VERSION.SDK_INT >= 16) {
Log.d(TAG, "Working around JellyBeans 'feature'...");
try {
// format the commandline parameter
CMDLINE_GRANTPERMS[2] = String.format("pm grant %s android.permission.READ_LOGS", pname);
java.lang.Process p = Runtime.getRuntime().exec(CMDLINE_GRANTPERMS);
int res = p.waitFor();
Log.d(TAG, "exec returned: " + res);
if (res != 0)
throw new Exception("failed to become root");
} catch (Exception e) {
Log.d(TAG, "exec(): " + e);
Toast.makeText(getApplicationContext(), "Failed to obtain READ_LOGS permission", Toast.LENGTH_LONG).show();
}
}
} else
Log.d(TAG, "we have the READ_LOGS permission already!");
and then your code should work, run this instead if not
Process process = Runtime.getRuntime().exec("su -c logcat D");

Self updating app

TL:DR; version ;)
my app should run without user interaction (autostart etc works)
it should update itself (via apk) without any user interaction
rooted devices are possible
.
problem:
querying a newer apk from a server works
when starting the apk with a (view?) intent, the "install app" prompt pops and needs a user confirmation
How do I solve this without any user interaction?
http://code.google.com/p/auto-update-apk-client/
This seems to be a solution, but there must be better approach.
I already found this: Install Application programmatically on Android
but that doesn't solve my problem.
Solved it! :D
It just works in rooted devices but works perfectly.
Using the unix cmd "pm" (packageManager) allows you to install apks from sdcard, when executing it as root.
Hope this could help some people in the future.
public static void installNewApk()
{
try
{
Runtime.getRuntime().exec(new String[] {"su", "-c", "pm install -r /mnt/internal/Download/fp.apk"});
}
catch (IOException e)
{
System.out.println(e.toString());
System.out.println("no root");
}
}
Required permissions:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
My suggestion is to use plugin mechanism instad of updating the app. You can dynamically load classes from the Web and run them inside your app without any user interaction. There is a lot of resources spread across the Internet:
How to load a Java class dynamically on android/dalvik?
http://android-developers.blogspot.com/2011/07/custom-class-loading-in-dalvik.html
If su -c doesn't work, try su 0 (only rooted devices can do su!)
The full answer looks like this:
private void installNewApk()
{
String path = mContext.getFilesDir().getAbsolutePath() + "/" + LOCAL_FILENAME;
mQuickLog.logD("Install at: " + path);
ProcessUtils.runProcessNoException(mQuickLog, "su", "0", "pm", "install", "-r", path);
}
With this class defined:
public class ProcessUtils {
Process process;
int errCode;
public ProcessUtils(String ...command) throws IOException, InterruptedException{
ProcessBuilder pb = new ProcessBuilder(command);
this.process = pb.start();
this.errCode = this.process.waitFor();
}
public int getErrCode() {
return errCode;
}
public String getOutput() throws IOException {
InputStream inputStream = process.getInputStream();
InputStream errStream = process.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line + System.getProperty("line.separator"));
}
br = new BufferedReader(new InputStreamReader(errStream));
while ((line = br.readLine()) != null) {
sb.append(line + System.getProperty("line.separator"));
}
return sb.toString();
}
public static String runProcess(String ...command) throws IOException, InterruptedException {
ProcessUtils p = new ProcessUtils(command);
if (p.getErrCode() != 0) {
// err
}
return p.getOutput();
}
public static void runProcessNoException(String ...command) {
try {
runProcess(command);
} catch (InterruptedException | IOException e) {
// err
}
}
}

Read logcat from app not working correctly

I am trying to read from the logcat output in my app. I am able to read in correctly, but it goes on reading it in endless loop. Somehow there seems no way to detect the end of stream.
Not sure what I am doing wrong.
Here is my code:
String baseCommand = "logcat -v time MyTag:D *:S";
Process process = null;
try {
process = Runtime.getRuntime().exec(baseCommand);
InputStreamReader reader = new InputStreamReader(process.getInputStream());
BufferedReader bufferedReader = new BufferedReader(reader);
String line;
while ((line = bufferedReader.readLine()) != null) {
Log.d("SomeOtherTag", line); //This line executes endlessly
}
} catch (IOException e) {
Log.e(DEBUG_TAG, "error in logging");
e.printStackTrace();
}
Logcat doesn't exit so the buffer is blocked.
Use 'logcat -d' in order to dump the log and then exit.
Hope this still helps, Yaron
Not positive but I believe you need to pass the logcat call if it has args in a String[] so it would be something like
String[] baseCommand = {"logcat", "-v", "time", "MyTag:D", "*:S"};
then the rest of your code.
The single string call is just the program name, not the args.

Reading Logcat within the app returns null

I read the other posts and can't figure out the "trick".
I looked at Log Collector but can't use a separate APK. I'm basically using the same approach and I consistently get nothing back on the processes inputstream.
I have READ_LOGS in the manifest.
From within my default activity, I'm able to get the log, but if I move the logic to another activity or utilize an asynctask, no output is returned.
this code is from my default activity... inline, i dump it to the log
try {
Process process = Runtime.getRuntime().exec("logcat -d");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
StringBuilder log=new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
log.append(line);
}
Log.d(LOGTAG, "Logcat: " +log.toString());
} catch (IOException e) {}
if i wrap it in an asynctask or just inline it in another activity, it returns nothing
ArrayList<String> commandLine = new ArrayList<String>();
//terminate on completion and suppress everything except the filter
commandLine.add("logcat -d -s");
...
//replace asynctask with inline (could not get log in asynctask)
showProgressDialog(getString(R.string.acquiring_log_progress_dialog_message));
final StringBuilder log = new StringBuilder();
BufferedReader bufferedReader = null;
try{
Process process = Runtime.getRuntime().exec(commandLine.toArray(new String[0]));
bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null){
log.append(line);
log.append(MangoApp.LINE_SEPARATOR);
}
sendIntent.putExtra(Intent.EXTRA_TEXT, log.toString());
startActivity(Intent.createChooser(sendIntent, getString(R.string.chooser_title)));
dismissProgressDialog();
dismissMainDialog();
finish();
}
catch (IOException e){
dismissProgressDialog();
showErrorDialog(getString(R.string.failed_to_get_log_message));
Log.e(LOGTAG, "Log collection failed: ", e);//$NON-NLS-1$
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ignore) {}
}
}
Can anyone spot the diff or explain the magic? I'm pretty sure the commandline is right in the second version so scratching my head. I'm using 2.1 SDK 7 on the emulator.
Thanks
Hope this will be helpful, you don't have to create file by your self just execute the below command, to get the error info.
Runtime.getRuntime().exec("logcat -v time -r 100 -f /sdcard/log.txt *:E");
Logcat parameters options:
-r <size in kilobytes> -> for specifying the size of file
-f <filename> -> file to which you want to write the logs.
Can you try it without the ArrayList. Just pass the command String
I have implemented it in the following way (without the ArrayList). It works for me.
String baseCommand = "logcat -v time";
baseCommand += " MyApp:I "; // Info for my app
baseCommand += " *:S "; // Silence others
ServicesController.logReaderProcess = Runtime.getRuntime().exec(baseCommand);

Can't reboot device using runtime.exec

For some reason I cannot reboot Android devices using Runtime.getRuntime().exec("/system/bin/reboot");. I have tried the following code on 3 devices now without luck. One was built from rowboat-android source. The other two are the Motorola Droid Pro (Rooted, stock) and the HTC Ledgent (Rooted, Cynogen Mod). All devices are running Android 2.2 Froyo.
Does anyone know why? su works as well as the Super User application is visible. I should note various other shell commands do work, like netcfg (chmod' to 777) and ls.
public static boolean executeCommand(SHELL_CMD iShellCmd){
String cmd = null;
String line = null;
String fullResponse = null;
Process lPs = null;
Log.d(Global.TAG,"--> !!!!! Running shell command");
if (iShellCmd == SHELL_CMD.restart_device){
cmd = "reboot";
}
Log.d(Global.TAG,"--> About to exec: " + cmd);
try {
lPs = Runtime.getRuntime().exec("su");
lPs = Runtime.getRuntime().exec("/system/bin/reboot");
} catch (Exception e) {
e.printStackTrace();
}
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(lPs.getOutputStream()));
BufferedReader in = new BufferedReader(new InputStreamReader(lPs.getInputStream()));
try {
while ((line = in.readLine()) != null) {
Log.d(Global.TAG,"--> Command result line: " + line);
if (fullResponse == null){
fullResponse = line;
}else{
fullResponse = fullResponse + "\n" + line;
}
}
} catch (Exception e) {
e.printStackTrace();
}
Log.d(Global.TAG,"--> Full response was: " + fullResponse);
return true;
}
Depending on how you've obtained root permission on your device, you can do any of the following:
Runtime.getRuntime().exec(new String[]{"/system/xbin/su","-c","reboot"});
or
Runtime.getRuntime().exec(new String[]{"/system/bin/su","-c","reboot"});
or
Runtime.getRuntime().exec(new String[]{"su","-c","reboot"});
Probably better to test all three scenarios in your application.
Finally after weeks of searching:
Runtime.getRuntime().exec(new String[]{"/system/bin/su","-c","reboot now"});
Try running "su /system/bin/reboot" instead of su and the command on different lines. That might help :)
If you want a button to be pressed try:
final Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
try {
Runtime.getRuntime().exec(new String[]{"/system/bin/su","-c","reboot"});
} catch (IOException e) {
}
}
});
By the way for this code to work the button has to be called button1.
instead of {"/system/bin/su","-c","reboot"} i changed the "/system/bin/su" part to just "su" and then it worked for me.
Like this Runtime.getRuntime().exec(new String[]{"su","-c","reboot"});

Categories

Resources