why process give null inputstream in test runner class? - android

In my android test project, I simply read the logcat using adb command
like,
public StringBuilder log=new StringBuilder();
public String line="";
public String temp="";
public void testSolo() throws Exception {
String baseCommand = "logcat -v time";
baseCommand += " ActivityManager:I "; // Info for my app
baseCommand += " *:S "; // Silence others
try {
Process logReaderProcess = Runtime.getRuntime().exec(baseCommand);
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(logReaderProcess.getInputStream()));
while ((line =bufferedReader.readLine()) != null) {
log.append(line); // here readLine() returns null
}
}
catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
but, here in string line I always get null value,
while the same thing always run in the android activity's onCreate() .
I don't understand why this happen?
Same thing runs in activity class and not in the android test project.
I also add use -permission for READ_LOGS and WRITE_EXTERNAL_STORAGE in test project's
manifest.xml file.
Is there anybody knows how it works or what happens?
Thanks in advance.

Try to add
<uses-permission android:name="android.permission.READ_LOGS" />
to your manifest.

String []baseCommand = new String[]{"logcat", "-v","time"};
Process logReaderProcess = Runtime.getRuntime().exec(baseCommand);
try this out

Related

Read logs from code programmatically and matching with a string in android app

How can we read logs(verbose,debug etc) programmatically from android class and then search for a string or matching with a provided string in android.
Sometimes we need to handle some system or kernel layer related event. But as we have limited access of those code we can't handle them. We can see the logcat via adb and also see some log comes from kernel/framework layer.
Now the question is, How we can override or handling some event in our app based on those logs?
Here is a solution to this from any android app:
We need to make a class with some code like below:
public class LogsUtil {
private static final String processId = Integer.toString(android.os.Process
.myPid());
public static StringBuilder readLogs() {
StringBuilder logBuilder = new StringBuilder();
try {
String[] command = new String[] { "logcat", "-d", "threadtime" };
Process process = Runtime.getRuntime().exec(command);
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
if (line.contains(processId)) {
logBuilder.append(line);
//Code here
}
}
} catch (IOException e) {
}
return logBuilder;
}
}
Then need to write below code in our activity from where we need to check the logs string:
//read the logs
StringBuilder logs = LogsUtil.readLogs();
if(logs.toString().contains("your_text"))
//your code
else //your code

Unable to input "enter" key event from within my app android

I want to input "enter" key event programmatically from within my app.
I have tried it using abd shell command as well as using AccessibilityService, but found no luck in it.
Similar question was asked here as well
Below is my code which I used to execute adb shell command :
try {
Runtime runtime = Runtime.getRuntime();
Process p = runtime.exec("input keyevent 66");
BufferedReader standardIn = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader errorIn = new BufferedReader(new InputStreamReader(p.getErrorStream()));
String output = "";
String line;
while ((line = standardIn.readLine()) != null) {
output += line + "\n";
}
while ((line = errorIn.readLine()) != null) {
output += line + "\n";
}
Log.d("output", "" + output);
} catch (IOException e) {
e.printStackTrace();
}
I am getting the following output :
sh: resetreason: can't execute: Permission denied
Someone please help me out.
If anyone knows how to achieve it using AccessibilityService as well, please let me know.
Thanks in advance!
Add this <uses-permission android:name="android.permission.ACCESS_SUPERUSER" /> permission & Try again .

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

Categories

Resources