I want to print something in console, so that I can debug it. But for some reason, nothing prints in my Android application.
How do I debug then?
public class HelloWebview extends Activity {
WebView webview;
private static final String LOG_TAG = "WebViewDemo";
private class HelloWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webview = (WebView) findViewById(R.id.webview);
webview.setWebViewClient(new HelloWebViewClient());
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebChromeClient(new MyWebChromeClient());
webview.loadUrl("http://example.com/");
System.out.println("I am here");
}
Correction:
On the emulator and most devices System.out.println gets redirected to LogCat and printed using Log.i(). This may not be true on very old or custom Android versions.
Original:
There is no console to send the messages to so the System.out.println messages get lost. In the same way this happens when you run a "traditional" Java application with javaw.
Instead, you can use the Android Log class:
Log.d("MyApp","I am here");
You can then view the log either in the Logcat view in Eclipse, or by running the following command:
adb logcat
It's good to get in to the habit of looking at logcat output as that is also where the Stack Traces of any uncaught Exceptions are displayed.
The first Entry to every logging call is the log tag which identifies the source of the log message. This is helpful as you can filter the output of the log to show just your messages. To make sure that you're consistent with your log tag it's probably best to define it once as a static final String somewhere.
Log.d(MyActivity.LOG_TAG,"Application started");
There are five one-letter methods in Log corresponding to the following levels:
e() - Error
w() - Warning
i() - Information
d() - Debug
v() - Verbose
wtf() - What a Terrible Failure
The documentation says the following about the levels:
Verbose should never be compiled into an application except during development. Debug logs are compiled in but stripped at runtime. Error, warning and info logs are always kept.
Use the Log class. Output visible with LogCat
Yes it does. If you're using the emulator, it will show in the Logcat view under the System.out tag. Write something and try it in your emulator.
Of course, to see the result in logcat, you should set the Log level at least to "Info" (Log level in logcat); otherwise, as it happened to me, you won't see your output.
if you really need System.out.println to work(eg. it's called from third party library). you can simply use reflection to change out field in System.class:
try{
Field outField = System.class.getDeclaredField("out");
Field modifiersField = Field.class.getDeclaredField("accessFlags");
modifiersField.setAccessible(true);
modifiersField.set(outField, outField.getModifiers() & ~Modifier.FINAL);
outField.setAccessible(true);
outField.set(null, new PrintStream(new RedirectLogOutputStream());
}catch(NoSuchFieldException e){
e.printStackTrace();
}catch(IllegalAccessException e){
e.printStackTrace();
}
RedirectLogOutputStream class:
public class RedirectLogOutputStream extends OutputStream{
private String mCache;
#Override
public void write(int b) throws IOException{
if(mCache == null) mCache = "";
if(((char) b) == '\n'){
Log.i("redirect from system.out", mCache);
mCache = "";
}else{
mCache += (char) b;
}
}
}
it is not displayed in your application... it is under your emulator's logcat
System.out.println("...") is displayed on the Android Monitor in Android Studio
There is no place on your phone that you can read the System.out.println();
Instead, if you want to see the result of something either look at your logcat/console window or make a Toast or a Snackbar (if you're on a newer device) appear on the device's screen with the message :)
That's what i do when i have to check for example where it goes in a switch case code! Have fun coding! :)
I'll leave this for further visitors as for me it was something about the main thread being unable to System.out.println.
public class LogUtil {
private static String log = "";
private static boolean started = false;
public static void print(String s) {
//Start the thread unless it's already running
if(!started) {
start();
}
//Append a String to the log
log += s;
}
public static void println(String s) {
//Start the thread unless it's already running
if(!started) {
start();
}
//Append a String to the log with a newline.
//NOTE: Change to print(s + "\n") if you don't want it to trim the last newline.
log += (s.endsWith("\n") )? s : (s + "\n");
}
private static void start() {
//Creates a new Thread responsible for showing the logs.
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while(true) {
//Execute 100 times per second to save CPU cycles.
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//If the log variable has any contents...
if(!log.isEmpty()) {
//...print it and clear the log variable for new data.
System.out.print(log);
log = "";
}
}
}
});
thread.start();
started = true;
}
}
Usage: LogUtil.println("This is a string");
I dont having fancy IDE to use LogCat as I use a mobile IDE.
I had to use various other methods and I have the classes and utilties for you to use if you need.
class jav.android.Msg. Has a collection of static methods.
A: methods for printing android TOASTS.
B: methods for popping up a dialog box.
Each method requires a valid Context. You can set the default context.
A more ambitious way, An Android Console. You instantiate a handle to the console in your app, which fires up the console(if it is installed), and you can write to the console. I recently updated the console to implement reading input from the console. Which doesnt return until the input is recieved, like a regular console.
A: Download and install Android Console( get it from me)
B: A java file is shipped with it(jav.android.console.IConsole). Place it at the appropriate directory. It contains the methods to operate Android Console.
C: Call the constructor which completes the initialization.
D: read<*> and write the console.
There is still work to do. Namely, since OnServiceConnected is not called immediately, You cannot use IConsole in the same function you instantiated it.
Before creating Android Console, I created Console Dialog, which was a dialog operating in the same app to resemble a console. Pro: no need to wait on OnServiceConnected to use it. Con: When app crashes, you dont get the message that crashed the app.
Since Android Console is a seperate app in a seperate process, if your app crashes, you definately get to see the error. Furthermore IConsole sets an uncaught exception handler in your app incase you are not keen in exception handling. It pretty much prints the stack traces and exception messages to Android Console. Finally, if Android Console crashes, it sends its stacktrace and exceptions to you and you can choose an app to read it. Actually, AndroidConsole is not required to crash.
Edit Extras
I noticed that my while APK Builder has no LogCat; AIDE does. Then I realized a pro of using my Android Console anyhow.
Android Console is design to take up only a portion of the screen, so you can see both your app, and data emitted from your app to the console. This is not possible with AIDE. So I I want to touch the screen and see coordinates, Android Console makes this easy.
Android Console is designed to pop up when you write to it.
Android Console will hide when you backpress.
Solution that worked for me:
Under Logcat. (To show Logcat if not already shown. Click View menu-->Tool Windows-->Logcat). It is shown as System.out not as System.out.println as you might expect it. Rebuild the app if you have not already.
In the picture, highlighted yellow shows the System.out and output "Hello again".
Recently I noticed the same issue in Android Studio 3.3. I closed the other Android studio projects and Logcat started working. The accepted answer above is not logical at all.
Related
I am working on stripe-terminal-android-app, to connect to BBPOS 2X Reader device,
wanted to click-item from list,(recyclerView).
I am trying to do:
when list of devices appears(readers), I am checking if readers.size()==1, then click first-device from list,else show recyclerView();
I have very less experience in Android(coming from JS, PY), :)
After going through debugger to understand flow of program-running, I used F8 key, or stepOver the functions one by one,
and where value is assigned to convert in displayble-format in adapter as here.
public ReaderAdapter(#NotNull DiscoveryViewModel viewModel) {
super();
this.viewModel = viewModel;
if (viewModel.readers.getValue() == null) {
readers = new ArrayList<>();
} else {
readers = viewModel.readers.getValue();
if(readers.size() == 1){
Log.e(TAG, "readers.size() is 1 "+ readers.size());
}
}
}
then in ReaderHolder-file, values are bind() as
void bind(#NotNull Reader reader) {
binding.setItem(reader);
binding.setHandler(clickListener);
binding.executePendingBindings();
}
}
I tried assigining button and manually clicking when only-one device appears, by clicing on reader[0], can't do that by findViewById inside Adapter file, to call onClick() method manually,
I tired another StackOverflow's answer but didn't understood, from here.
Main fragment is discovery-fragment,
how can I click first-device by checking readers.size()==1, then click onClick()?
my final-goal is to automate, whole stripe-terminal-payment process on android.
extra-info:
I am fetching data from python-odoo server, then using url, will open app through browser, (done this part), then device will be selected automatically as everytime-no any devices will be present except one,
so will automatically select that from recyclerView, then proceed.
I have asked for help in detailed way on GitHub-issues, and started learning Android's concepts for this app(by customizing stripe's demo app, which works great, but I wanted to avoid manually clicking/selection of devices).
I have this idea, that anytime an unhandled exception occurs in my JavaFX program, that instead of relying on console output, I can display an alert to the user. I am thinking that perhaps I can capture the output from System.err to use. Here is what I have tried thus far.
PrintStream myStream = new PrintStream(System.err) {
#Override
public void println(String s) {
super.println(s);
Log.debugLog(s); //this function logs to a file and displays an alert to user
}
};
System.setErr(myStream);
This code segment works if I replace System.err with System.out, and System.setErr to System.setOut. However that is capturing System.out, not System.err. I suppose the better question would be, what exact function does System.err call when displaying an error to the console? So that may override it. Any tips are appreciated.
I think you have the wrong approach. If you want to display an alert to the user when there is an unhandled Exception, you can do that by setting a DefaultUncaughtExceptionHandler:
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
// show alert to user
e.printStackTrace();
// do whatever you want with the Exception e
});
You can create a JavaFX Alert customized to show an exception stack trace along with a brief message. This link shows the code for the below.
First of all: There is no exception thrown when this problem occurs.
My app is currently running in Google Plays closed alpha program. When I test the app using an emulator provided by Android Studio or using my own Galaxy A5, everything works fine and as expected.
Now I'm getting reports of my alpha testers, that their app is closing after they close the VideoAd. After investigating a while, I realized all devices used by google while performing Pre-Launch-Tests, had the same problem (visible by the video provided by Google).
Since there is no exception thrown, I have absolutely no idea how to debug this behaviour.
Following is the code of the onRewarded method (the other methods of the listener don't contain any code):
#Override
public void onRewarded(RewardItem rewardItem) {
int amount = calculateAdReward(rewardItem.getAmount());
updateCoins(amount);
rewardedAmount = amount;
rewarded = true;
}
rewardedAmount and rewarded are private fields used to instantiate a fragment in the activitys onResume-method:
#Override
protected void onResume() {
super.onResume();
mAdVideo.resume(this);
if(rewarded){
loadFragment(RewardFragment.newInstance(rewardedAmount);
rewardedAmount = 0;
rewarded = false;
}
}
My goal is to display a fragment after the user has been rewarded which holds the rewarded amount. My first attempt was as followed:
#Override
public void onRewarded(RewardItem rewardItem) {
int amount = calculateAdReward(rewardItem.getAmount());
updateCoins(amount);
loadFragment(RewardFragment.newInstance(amount));
}
which failed, since I tried to instantiate a fragment after saveInstanceState was called.
So after a bit of research, I solved my problem.
What I learned:
Never perform transactions inside the activity's lifecycle methods (onResume,...) since there is a possibility that the activity hasn't fully resumed when you reach your transaction code.
Instead, perform transactions in the onPostResume method. When this method is called, it is guaranteed your activity and all it's fragments have been fully resumed and it is "save" to perform a transaction.
On a side note: Don't perform transactions in those methods if you don't absolutely have to.
I often use Toast.makeText().show() to display messages to the user of my Android app. These can be instructions what to do next or error messages. As part of my JUnit tests, I would like to include assertions that these messages appear when expected. How do I go about doing this?
I do it by using Robotium framework, and calling this immediately after the toast is shown:
TextView toastTextView = solo.getText(0);
if(toastTextView != null){
String toastText = toastTextView.getText().toString();
assertEquals(toastText, "Your expected text here");
}
//wait for Toast to close
solo.waitForDialogToClose(5000);
Since originally asking this question, I have found the following solution which works well for me:
public static void waitForToast(Solo solo, String message) {
Assert.assertTrue(solo.waitForDialogToOpen(TIME_OUT));
Assert.assertTrue(solo.searchText(message));
}
A similar question was asked here for two times and never there was any answer. Or the answer was: "it is impossible!" Sorry, it is possible too much:
try{
...
// the line that causes the error
LinearLayout cell = (LinearLayout) inflater.inflate(R.layout.channels_list_cell, column);
...
}
catch(Throwable e){
Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show(); < breakpoint here!
}
At the breakpoint e is null. How can I seek for the error, please? Very possibly it is not the problem of java or Android, but of the Eclipse debugger, that itself needs debugging badly. But what have I to do, except changing to a different IDE? Any ideas? Beforehand grateful.
I have tried Throwable, Exception, RuntimeException. The result is the same.
An attempt to step over breakpoint causes NullPointerException, so, e seems really null at that moment already. Where could it be lost?
Edit:
I bring my gratitude to everybody and +1 to every answerer. It was an Eclipse bug. After restart Eclipse the Exception is not null anymore, it is a normal RuntimeException: Binary XML file line #15: You must supply a layout_width attribute. It would be another problem to be solved, but that one is solved.
If the exception you caught was a NullPointerException, the getMessage() method returns "null" which may be confusing. I know that this has sometimes confused me!
In the debugger, you should be able to select e and see a type and its fields. Also, another way to debug when things get really confusing is to go
e.printStackTrace();
(note - I'm not an Android guru so if this works differently on Android somebody please comment!)
Have you verified whether e is actually null or not? I.e. by adding something like if (e == null) Log.d("Exception is null"). I would then check if the log statement gets triggered both during normal execution and while debugging. If the results are different between the two, it would indicate a VM bug (unlikely, but possible). If the message doesn't get triggered in either case, then it's likely a debugger issue.
A few thoughts on further things you can try to debug the issue:
Try something like jdb and see if you get the same behaviour
You could get a dump of the jdwp communications between the debugger and the device, and see what's going on at that level. Maybe use wireshark or tcpdump and grab the data going over the usb bus to the device.
You could try adding some debug statements to dalvik itself. E.g. grab a copy of AOSP and build an emulator image, and then add some debugging statements to dalvik to try and track down what's going on.
You could attempt to do some sort of scripted jdwp session with the device
You could look at the bytecode (baksmali/dexdump/dedexer), to see if anything looks funny
Android does not always throws exception in a Throwable. It actually drives all the exceptions to the catLog. There you will find details of your exceptions even if in the catch block your exception is null.
You can easily access the catlog console from eclipse and filter to view the errors only
UPDATE:
Your breakpoint should be inside the catch block
I know this question was posted a while ago, and many times too! I fell into this trap yesterday and I thought I'll post what I found.
Problem definition: I used the following code
public class myAppActivity extends Activity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try { -- lots of code -- }
catch (Exception ex) {
Log.e ("eTutorPrism Error", "Caught this exception " + ex);
ex.printStackTrace();
}
}
}
Symptom was that 'ex' was always null and resume will give NullPointerException, although the actual exception was an IllegalArgumentException in a call made into another class from the code above.
ISSUE: onCreate() code does not display the exception caught. instead it shows exception = null.
Solution: do NOT use too much processing in onCreate(). Move as much as possible to another thread. So I changed the code to look like the following. voila, it works!!! I can see the actual exception displayed in the Logcat.
public class eTutorPrismAppActivity extends Activity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
eTutorPrismTest myTest = new eTutorPrismTest (getApplicationContext());
myTest.start();
}
}
class eTutorPrismTest extends Thread
{
private Context m_AppContext = null;
public eTutorPrismTest (Context appContext)
{
m_AppContext = appContext;
}
public void run ()
{
-- lots of code that needs appContext --
}
}
I am unsure of what causes this -- it could be an Eclipse bug as stated earlier. Regardless of the cause, I did find a workaround that seems to work. I hope it is useful to others as well.
After the exception is caught, assign it to another variable. The assigned variable should contain the correct Exception in the debugger.
SpecificException assignedVar = null;
try {
...
}
catch (SpecificException exc) {
assignedVar = exc; // <-- exc comes up null in the debugger, but assignedVar will be the correct object.
}
Hope this works for others as a workaround.