I am new to android development. In the overriden onCreate() method of my activity, I perform some operations. For ex. check if SharedPreference is already available and then route to other activity. How do I perform exception handling on this onCreate() method. Is it the right way to wrap the contents in a try catch and display the error dialog on exception?
If the exceptions are not handled properly, in my case the onCreate() method, the app crashes with message:
Unfortunately your application stopped working
On searching in the internet, I found that UncaughtExceptionHandler could be used to handle it. Any sample implementation and how to call it from all my activities would be helpful.
THat's the wrong way to go about it. Instead, go into your logcat. Read the stack trace of the exception. Figure out what you did wrong. Fix it. Just catching exceptions is a horrible practice unless you're catching a specific exception for a specific reason- its very unlikely your app is in a state where it can continue correctly. Don't be lazy, track down your bug and fix it.
With something like this you can catch a generic Exception in your onCreate() method:
#Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
try {
// do whatever you need
} catch (Exception e) {
e.printStackTrace();
}
}
Exception catching can be used with many goals. An interesting one is to catch particular expected exceptions to fix some problems (for example setting a generic value into a variable otherwise null after occurring an error).
The general purpose however is to avoid that an error causes a problem or in the worst case a crash of your application. Depending oh what kind of software you are developing, a crash may represents a little problem (like in an Android app), a very big one (like in airplane's softwares or power plants' softwares).
We can identify two kind of exceptions.
The first type are those exceptions specific to definite problems. They have to be declared into methods signature, so you are encouraged or obbligated to manage these exceptions and their relative problems. These exceptions represent an error that should probably occur during particular code execution, like a parsing error, or an input output error. For this type of problems we have particular exceptions, to catch and easily manage them (for example as previously said to init a variable with a default value after an error).
The second type of those exception represents instead some generic problems that can occur during program execution. They are a big and generic set and generally their probability of occurring is low. For this reason you are not obbligated to manage them. The main example of this type is the general Exception class.
So an catching an Exception is not the right approach to solve a bug, as suggested by Gabe Sechan.
Catching a generic Exception in the main() Java method can be a way, for example, to show a default human readable error to the user if nothing else is available.
Or could be a way to keep the failing of the current operation reducing crash probability.
Now, in Android we can't act directly on the main() method. onCreate() method is executed and exited so catching here a generic Exception has no much sense. Obviously it depends also on what you do in your onCreate() method and what you want to do if an error occurs. You could do some strange stuff (is very defined what you should do in the onCreate() method) and you could need to manage a big set of problems only showing an error, so it has more sense catch only a generic Exception than a lot of particular exceptions to make the same thing in each catch block.
If you want to achieve this goal (a message showed for all the errors occurred during onCreate() execution, made Activity by Activity) this is the right approach.
If instead what you want to achieve is to intercept all of the errors that are generated during all of your app execution, a good approach could be the UncaughtExceptionHandler, that act similarly to catch a generic Excepetion into a Java main() method. At this level an interesting approach is described here.
For more infos about exceptions you can read this and this.
Related
I am developing an Android app (It doesn't matter though) using RxJava2, and in some singleton there are some PublishProcessors.
And there are a lot of .onNext() calls on these PublishProcessors all over the project.
Now in order to debug, I need to know, on every .onNext() called, which line in my project invoked this .onNext().
Is there a way in RxJava(2) that I can achieve this?
I think you can use Frames tab in Debug menu.
For example, in this case, MainActivity line 18 trigger onNext
Ah, thanks to #PhanVanLinh, I found a solution that worked for me.
(Actually it has pretty much nothing to do with RxJava...)
You just need to print the stacktrace using Thread.currentThread.stackTrace and print it to your own string inside doOnNext(), but remember to do it before .observeOn() so that the thread won't switch, it must stay at the original thread that called .onNext(), otherwise you won't get meaningful information.
Then you will know which line that called .onNext().
it took me three days to narrow my problem with this memory leak and I can't find anyone else describing this issue anywhere. That's why I would like to ask if someone could confirm I haven't just missed something. I've also submitted a bug report but the reason I'm asking here on SO (besides letting others know) is that I would like you to let me know of other Views and their attributes causing such problems so I can avoid them.
My problem is as follows:
(1.) create a simple Android application (e.g. the SkeletonApp sample application)
(2.) add the following at the end of onCreate() to cause memory allocation:
Log.i(this.toString(), ">>> onCreate()");
auxList = new ArrayList<int[]>();
for(int i = 0; i < 20; i++) {
auxList.add(new int[250000]);
}
Log.i(this.toString(), "<<< onCreate()");
(3.) (optional - just for convenience) override the following methods:
#Override
protected void onDestroy() {
Log.i(this.toString(), ">>> onDestroy()");
super.onDestroy();
}
#Override
protected void finalize() throws Throwable {
Log.i(this.toString(), ">>> finalize() !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
super.finalize();
}
(4.) run the application and rotate the screen several times (pressing left CTRL+F11) - everything should work for now
(5.) in the layout (skeleton_activity.xml) add:
<TextView
android:id="#+id/textViewDebug"
android:layout_width="30dp"
android:layout_height="32dp"
android:textIsSelectable="true"
/>
(6.) repeat point (4.) - the logCat reveals that the Activity is destroyed after rotation but never finalized causing OutOfMemory error after several rotations
(7.) removing the textIsSelectable attribute or setting it to false as well as removing the id attribute (even while keeping textIsSelectable="true") prevents the issue.
Thanks for you comments!
PS: I'm new here and have no rights to add new tags. Could someone with enough points add a "textisselectable" tag to this question? Thanks
Check the Android Docs for use cases with finalize. Finalize is expensive, and is probably what is causing your memory leak, not the value on your text field.
Android Object
Note that objects that override finalize are significantly more expensive than objects that don't. Finalizers may be run a long time after the object is no longer reachable, depending on memory pressure, so it's a bad idea to rely on them for cleanup. Note also that finalizers are run on a single VM-wide finalizer thread, so doing blocking work in a finalizer is a bad idea. A finalizer is usually only necessary for a class that has a native peer and needs to call a native method to destroy that peer. Even then, it's better to provide an explicit close method (and implement Closeable), and insist that callers manually dispose of instances. This works well for something like files, but less well for something like a BigInteger where typical calling code would have to deal with lots of temporaries. Unfortunately, code that creates lots of temporaries is the worst kind of code from the point of view of the single finalizer thread.
Ok, I got an answer to my bug report stating that it can't be reproduced with the newest version of Android (I tested it on two devices running ICS). So I guess I'll just have to believe them as I don't have any newer device and it doesn't seem to bother anyone anyway. It's just a memory leak after all... ;-)
I am still fairly new to programming, so there are some things I learn from observing but do not fully understand. The Try-Catch is one of these things. From what I have researched, the try statement allows me to define a block of code to be tested for errors, and the catch statement allows me to define a block of code to be executed if an error occurs in the try block.
I get that. And I have tried to use Try-Catch in situations where I was receiving exception errors that crashed my applications. The Try-Catch seemed to prevent (stop) the crashing. But here is my question, is it OK to have an application that constantly catches an exception error?
For example, I am working with EditText widget. I want the input values for the EditText to represent currency, so I applied android:inputType="numberDecimal". The issue I learned with this is that this attribute allows any number of values after the decimal. This is when I came up with an idea of updating the EditText programmically with the proper format, using something like DecimalFormat.
I am not posting my entire code, but here is the piece that I am curious about.
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
DecimalFormat format = new DecimalFormat("0.00");
if (etBill.getText().toString() != null &&
etBill.getText().toString().length() > 0) {
try {
doubleBill = Double.parseDouble(etBill.getText().toString());
strFormatted = format.format(doubleBill);
Log.d(TAG, "unformatted(" + doubleBill + ")" +
" // formatted(" + strFormatted + ")");
//etBill.setText("$" + strFormatted, TextView.BufferType.EDITABLE);
etBill.setText("$" + strFormatted);
} catch (NumberFormatException nfe) {
Log.e(TAG, "FloatingPointParser.parseDouble error");
}
} else {
// values in editText were deleted; hardcode value
doubleBill = 0.0;
strFormatted = format.format(doubleBill);
}
}
And here is the exception error I catch every single time I input a value into my EditText widget.
So my question is, is the Try-Catch a method for me to correct my errors? Is it OK to catch exception errors, such as this NumberFormapException through the life of an application running? Am I using this right? Thanks in advance!
NumberFormatException is a runtime exception and you are catching it correctly. However, instead of just printing something to let you know you have caught it, you should either handle it by re-running through your code or pass the exception up the stack. For example, if a user inputs a number and then this exception is caught, you could prompt them to re-enter a new number. If the number that is throwing this exception is not provided by a user, but by your code, then it indicates you have a logic error somewhere and should fix that to prevent this exception from being thrown in the first place.
In general the exception mechanism should be used for exceptional circumstances - something that usually shouldn't happen. If you have an exception that's being thrown every time you enter a value, that's sort of abusing the mechanism. Usually there's a better way that doesn't involve exceptions. In some cases though, the exception mechanism is the cleanest way of dealing with the situation.
Here's a quote from Effective Java: Programming Language Guide by Josh Bloch:
"Use exceptions only for exceptional conditions. That is, do not use exceptions for control flow, such as catching NoSuchElementException when calling Iterator.next() instead of first checking Iterator.hasNext()."
Exception handling is not only an art but the subject of much discussion/debate. I will try to address the broader points without incurring anyone's wrath.
There are two kinds of exceptions--fault exceptions and contingency exceptions. Fault exceptions are unrecoverable like being unable to connect to a web service that is supposed to be there for your app to function. You log those in your catch block and rethrow to let them bubble to some fault handler. Contingency exceptions are what you described with the number format issue--stuff you can recover from. In this case, you handle things completely in the catch block. You allow the app to recover by prompting for a new input, for example.
By the way, none of that is my own. That strategy comes from Barry Ruzek.
Then there is the issue where people dislike using exceptions for flow control--for good reason. In your case, that would mean using a regular expression in an if statement, for example, to test number format rather than using a potential exception-generating operation. You generally don't want to use exceptions for normal control flow, but you also need to be careful not to let ideology trump a simple solution. There is a balance you will learn with experience.
So you should recover from the exception in your catch block. Or use a different non-exceptional mechanism entirely to manage control flow.
Hope that helps.
Using Try catch in programing is fair enough. But handling errors is different issue. Try catch is just to way catch erronious conditions which can occur in ur program but u may wish to catch it or leave its up to you. Simple example is age is not allowed as floating point number but height is allowed both floating point and decimal number.
I was going through following tutorial: http://www.dreamincode.net/forums/topic/190013-creating-simple-file-chooser/#viewSource
Inside the FileChooser class there is one exception beeing supressed, since there is nothing within the catch clause. So I decided to add following statement to the catch clause:
Log.e(ACTIVITY_SERVICE, e.getCause().toString());
For some reason this always causes the app to crash (NullPointerException). When I don't do any logging, except for a a simple syso print, then I don't get any exception and the app does't crash either. Then it works fine. I'm new to the whole Android Framework and just want to understand why this is happening.
Thanks to Ingo's and CommonsWare's hints I came to the conclusion, that following line caused the exception:
EDIT:
In fact it was the start of the foreach loop, which iterates over all subdirectories and files of a given directory. I didn't know, that this would cause a NPE, if the list you want to iterate on is actually null. For some reason I thought that the loop would be automatically skipped in this case.
I think it is possible to replace the Java package name in Force Close window in Android with a more readable application name. I cannot find any information how to do it or recall where I saw it, however. I tried to search on Google and SO without luck. I have labels for both activity and application tags in my Manifest.
Is it possible to setup a custom application name in FC window, and if it is, how to do it?
There is a way to set a global exception handler, which will catch any exception which is caused on that thread. So you set it in your main activity and it will apply to every subactivity.
But! Don't ever do that to suppress exceptions and simply show a dialog because it looks nicer (I would even affirm that this would be the most dumb idea of all you can have since you're disabling a basic feature which is there to help you to fix exceptional behavior). It's not what the handler is there for! Usually the handler invokes the previous default handler to preserve the default exception handling. It only wants the crash info.
I wrote that because of this answer. No offence! It's only a big fat warning to attempt to force wrong behavior.
final UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
// get the crash info
defaultHandler.uncaughtException(thread, ex);
}
});
This currently isn't possible without modifying code at the system level. What you may have seen, however, is a custom error handler by an application. If you surround the bulk of your application code with a large try / catch block, you could pop up your own dialog informing the user of an error (with the application name and text of your choosing, of course). This would have to be done for each separate activity though, and its much better practice to simply avoid FCs altogether (hire a test group?).