This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I check if an app running on Android?
I would like to know if there is a way to check if the Android default browser (browser in Android OS) has been opened. Suppose it's opened, I would like a toast to be displayed. How can I do this programmatically?
This is the code that I used in the class that extends the Service class which listens to the logs and checks if the Android default browser has been opened. If it is then it prints a log in the LogCat stating that the Android default browser has been opened.
try {
Process mLogcatProc = null;
BufferedReader reader = null;
mLogcatProc = Runtime.getRuntime().exec(new String[] { "logcat", "-d" });
reader = new BufferedReader(new InputStreamReader(mLogcatProc.getInputStream()));
String line;
final StringBuilder log = new StringBuilder();
String separator = System.getProperty("line.separator");
while ((line = reader.readLine()) != null) {
log.append(line);
log.append(separator);
}
String w = log.toString();
Log.d("LogService", "The log is: " + w);
if (w.contains("Starting activity: Intent { act=android.intent.action.MAIN flg=0x10000000 cmp=com.android.browser/.BrowserActivity }")) {
Log.d("LogService", "The browser has been opened");
}
}
catch (Exception e) {
Log.d("LogService", "The stacktrace is: " + e.getMessage());
}
google said on the google IO that such a behavior is considered as malware .
however , up until API 15 (including) , you can use a service that listens to the logs , and check if the desired app has started . that's because each time you run an app , android writes to the log about it .
this is considered as a workaround but a lot of apps use it and it works fine .
not sure if on the new version (API 16) reading logs would be that simple . they said that the permission to read from logs won't work anymore , and that they allow apps to read their own logs instead (without any permission needed) .
of course , if the app you are trying to monitor gives any kind of API to tell the world (via intent for example) that it has started , you can use it . i don't think that the built in web browser does that , though.
Related
I'm working on an app that uses Android's MediaMuxer for recording the screen. Using Crashlytics, a significant number of users have the "Failed to stop the muxer" crash, but I can't reproduce it locally on any of my devices. According to another question, the MPEG4Writer logs generated while MediaMuxer is running should indicate what the source of the problem is, but since I'm unable to reproduce it locally, I need to collect those logs remotely and pass them over to Crashlytics.
So here's my problem: MediaMuxer and MPEG4Writer are system classes, so obviously I can't edit them to add Crashlytics.log() lines. I've thought of having the app read the Logcat output and storing all entries containing MPEG4Writer, which are then sent to Crashlytics if the muxer crashes, using this implementation as a base. Here's my code:
public class LogRetriever extends Thread {
private static final String TAG = LogRetriever.class.getCanonicalName();
public static ArrayList<String> logStorage = new ArrayList<>();
private AtomicBoolean mLoggingActive = new AtomicBoolean(true);
#Override
public void run() {
try {
String[] command = new String[] { "logcat" };
Process process = Runtime.getRuntime().exec(command);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while (mLoggingActive.get() && ((line = bufferedReader.readLine()) != null)){
if(line.contains("MPEG4Writer")) {
logStorage.add(line);
}
}
}
catch (IOException ex) {
Log.e(TAG, "start failed", ex);
}
}
public void stopLogging() {
mLoggingActive.set(false);
}
}
Using the above method, I only seem to get the first four log lines generated by MPEG4Writer. The rest are visible through Android Studio's logcat, but aren't collected by my code. I've also tried this library which seems to do the same thing, but again, same problem, only the first 4 lines are collected. I suspect that MediaMuxer is creating its own process after those 4 lines, at which point I can no longer read its logcat output because my LogRetriever class is now in a different process. So how am I supposed to collect those logs? Am I taking the wrong approach here?
So how am I supposed to collect those logs?
Generally, unless you are working for a device manufacturer, you don't collect those logs.
First, accessing LogCat at runtime has never been officially supported; hence, the clunky "fork logcat" approach that you have to take.
Beyond that, you need the READ_LOGS permission to get more than what you are. That permission has signature|privileged|development for the protectionLevel, meaning that ordinary apps cannot hold that permission.
This is for privacy reasons. READ_LOGS gives you access to all of LogCat, and lots of apps (and some system processes) log information that may be sensitive.
This question already has answers here:
How to launch the Google Play intent in 'Give Feedback' mode on Android?
(3 answers)
Closed 8 years ago.
Background
Some of Google's apps allow you to send feedback from within the app, instead of going to the play store.
For example this one (of this app) :
compare this to the original one:
The question
Is it possible to open this dialog?
If so, how? And what really happens when the user posts the feedback? Is it being sent directly to the developer console? Can the developer return an answer to such a feedback? Can the dialog request that the user would leave an email? What are the features of this dialog?
If not, what do they use? It looks really similar to the dialog of sending information about crashes. Could it be that they use the same mechanism?
The reason why i'm thinking it's the same mechanism of sending errors is this post i've written, but it's supported only from API 14 , and i'm not sure about the consequences...
Yes this is the crash report dialog. Yes the report goes to the developer console. No you cannot reply to the feedback. Yes, per the post you referenced it requires API 14 and can't be used otherwise. The dialog cannot be customized. The best way to see the features of the dialog is to open it using an app that provides it.
Based on your questions, it sounds that your requirements exceed what this dialog is capable of and you may need to invent a home-grown solution or use a third-party solution.
I've used this code fragment to enable sending feedback and explicitly opening the dialog with handled exceptions.
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public ApplicationErrorReport createErrorReport (Exception e) {
ApplicationErrorReport report = new ApplicationErrorReport ();
report.packageName = report.processName = this.getPackageName ();
report.time = System.currentTimeMillis ();
report.type = null == e ? ApplicationErrorReport.TYPE_NONE : ApplicationErrorReport.TYPE_CRASH;
report.systemApp = false;
if (null != e) {
ApplicationErrorReport.CrashInfo crash = new ApplicationErrorReport.CrashInfo ();
crash.exceptionClassName = e.getClass ().getSimpleName ();
crash.exceptionMessage = e.getMessage ();
StringWriter writer = new StringWriter ();
PrintWriter printer = new PrintWriter (writer);
e.printStackTrace (printer);
crash.stackTrace = writer.toString ();
StackTraceElement stack = e.getStackTrace ()[0];
crash.throwClassName = stack.getClassName ();
crash.throwFileName = stack.getFileName ();
crash.throwLineNumber = stack.getLineNumber ();
crash.throwMethodName = stack.getMethodName ();
report.crashInfo = crash;
}
return report;
}
I have a Java SE Application that use
input = new Scanner(System.in);
to get Input parameters
and use System.out.println("..");
to print results
Since all Java APIs used in the original Java Project are also available in Android, I have tried to import all classes without any error, but now I don't know how replicate the behaviour of the classic Java console in Android.
I have seen that there are developers that have achieved this in some IDE-like apps, but I don't know how.
Could you help me?
Example:
assume that you want to port this dummy Java SE Application in Android mantaining the console-like approach of the original code
public static void main(String[] args) {
System.out.println("Please enter your choice");
System.out.println("A, B");
Scanner myScanner = new Scanner(System.in);
String choice = myScanner .nextLine();
if (choice.charAt(0) == 'A') {
...do something
}
else{
...do something
}
}
You can execute system commands with exec(). Here is how to do it:
Runtime r = Runtime.getRuntime();
Process p = r.exec("uname -a"); // here goes your input
p.waitFor();
BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = b.readLine()) != null) {
System.out.println(line);
}
Update:
Ok, from what I understand, you would like to compile and run code written by user. I can see 3 options:
Most difficult I think. Get the source code of some Java compiler and include it in your project. So, user inputs a text. You compile it, run and give the output.
Using already built compiler. This requires root. Install javac on your device. Then, in your application you can call it with the above exec() code.
Easiest one. Using internet and for example, Ideone.com. In your app you send code to compile on Ideone. You get back the output and present it to the user.
I am trying to write an app which reads the logs created by adb logcat. Following the code on link1 and link2, I have the following code:
try {
Process process = Runtime.getRuntime().exec("logcat");
System.out.println("Process : " + process); // shows process id
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
System.out.println("Buffered reader : " + bufferedReader.readLine());
StringBuilder log = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
log.append(line);
}
TextView tv = (TextView) findViewById(R.id.textView1);
tv.setText(log.toString());
} catch (IOException e) {
}
To test what the buffered reader is reading, I put a println, but I get a message "cannot bind tcp:5038". The above code does not read any logs. I also tried using "logcat *:V" but I did not get logs of even lowest priority.
I gave my app the permission: android.permission.READ_LOGS.
I am testing my code on Android emulator.
Can someone please point out what am I doing wrong.
Thanks for helping.
EDIT:
I tried "logcat -d" and I got one line of log. In the code, it can be observed that a try/catch block has been provided; when I remove the permission READ_LOGS from the app, no exception is raised and the bufferReader simply prints null (Usually when an app does not find a permission it requires, it raises an exception). What is the reason for this behavior ?
EDIT2:
I tried Log.d(TAG, log.toString()) and got more than one line of text. Can someone please explain the last question from the previous edit: when I remove the required permission, why is an exception not raised by the app ?
You are likely getting the message "cannot bind tcp:5038" due to not having
<uses-permission android:name="android.permission.INTERNET" />
in your manifest
You can never get the permission to read logs through Runtime.getRuntime().
The android dev team decided to stop granting these permissions to third-party apps. Only system apps can now get them.
More details:https://code.google.com/p/acra/issues/detail?id=100
To the best of my (current) understanding, Android has no console to send the messages to so the System.out.println messages get lost. Instead, Log.x (outputing to LogCat) should be used.
Yet, in the acclaimed Pro Android 2 book, listing 8-1 does just that:
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
String page = sb.toString();
System.out.println(page);
Does System.out.println really work in Android or is it only a typo?
If the former (i.e. not a typo), what does it really do and where should I expect to find the output?
System.out.println prints to whatever is currently defined as the "standard" output PrintStream. It is possible to hook this up to point to the log stream, but really there is no good reason to use it. Use Log.x.
This is probably just a typo in the book. Nothing in that code snippet is Android specific.
That System.out.println code does work (despite what the android documentation says). I've tried it on my on my Android development set up (without changing the settings as they describe in the documentation). I've had tried on the set ups of my Android programming students, both on their Windows and Macs. And it always comes out the same way:
The following line does output to logcat by default.
System.out.println("blah blah");
Now of course, it's probably best to stick to Log.x() anyway. It's probably never a good idea to rely on undocumented features, especially in a book. This feature could be here today, and be just as well gone the next time the tools get updated.
From the android docs:
By default, the Android system sends stdout and stderr (System.out and System.err) output to /dev/null.
It also explains how to use System.out and System.err properly.
If you're using Eclipse, System.out will be displayed on the LogCat tab not in the Console.
You can also try the Log.i("MyLog", "The message here...."); also displayed on the LogCat.
Enjoy!