Throw exception and allow to proceed in method further - android

I was working on some validation. There is some mandatory fields and some of them are optional. For mandatory fields, I'm throwing exception, but for optional fields, I've to print warning and have to proceed further in my method. I'm not getting any way to doing warning part. Can someone help on it?
public void method(String param1, String param2){
if(param1 == null){
throw new IllegalArgumentException("mandatory field");
}
//Here for param2, I want to throw eception, but want to proceed further to next line.
//Execute my code here
}

This is not how exceptions work. There are several ways to solve it:
Just don't use exceptions and print your error instead (println() or some textfield, toast or whatever)
Place a boolean marker saying that param2 failed and throw your exception at the end of the method
m_param2 = true
//...
if (param2 == null) {
m_param2 = false
}
// you proceed here
if (!m_param2){
// throw exception
}
Use submethods for the parameter-check which always throw an exception when errors occur and catch the error in your main-method and decide what to do then.
For me case 3 does not make that much sense but that depends on how and when you want to print the message. If you have something in the parent layer (the code that runs your method) that automatically generates the error-message when an exception occurs, I would stick to my second suggestion.
In general I think that missing optional parameters are no real error case so that no exception should be thrown. The method-caller needs to pass the parameter anyhow (though it can be null, of course).

throw is a keyword which finishes the method execution you cant continue by throwing an exception you can use an interface to do what you want
public void method(String param1, String param2,Listener listener){
if(param1 == null){
listener.IllegalArgumentException("mandatory field");
return;
}
listener.IllegalArgumentException("mandatory field");
//Execute my code here
}
interface Listener{
void IllegalArgumentException(String string);
}

You can use
try{
} catch (Exception e){
// you can ignore if you want to
}finally {
//rest of your code here
}

try the below code let me know if any issues.
public void method(String param1, String param2){
if(param1 == null){
throw new IllegalArgumentException("mandatory field");
}
if(param2 == null) {
Log.d("Error", "param2 is null");
}
}

Related

java.lang.NullPointerException: Attempt to invoke interface method 'java.util.Iterator java.lang.Iterable.iterator()' when starting a notification

I noticed some of my users are getting this exception. I don't know how to reproduce it, I only have the reports on Crashlytics. Seems to be deep inside Google's code. Out of thousands who have used this code only 39 have had the exception.
Any idea what might be wrong?
Fatal Exception: java.lang.NullPointerException: Attempt to invoke interface method 'java.util.Iterator java.lang.Iterable.iterator()' on a null object reference
at android.app.ApplicationPackageManager.getUserIfProfile(ApplicationPackageManager.java:2141)
at android.app.ApplicationPackageManager.getUserBadgeForDensity(ApplicationPackageManager.java:997)
at android.app.Notification$Builder.getProfileBadgeDrawable(Notification.java:2877)
at android.app.Notification$Builder.hasThreeLines(Notification.java:3092)
at android.app.Notification$Builder.build(Notification.java:3646)
at android.support.v4.app.NotificationCompatApi21$Builder.build(NotificationCompatApi21.java:136)
at android.support.v7.app.NotificationCompat$LollipopExtender.build(NotificationCompat.java:504)
at android.support.v4.app.NotificationCompat$NotificationCompatImplApi21.build(NotificationCompat.java:835)
at android.support.v4.app.NotificationCompat$Builder.build(NotificationCompat.java:1752)
at mycode.startNotification(mycode.java:361)
Thanks.
ApplicationPackageManager.java
private UserInfo getUserIfProfile(int userHandle) {
List<UserInfo> userProfiles = getUserManager().getProfiles(UserHandle.myUserId());
for (UserInfo user : userProfiles) {
if (user.id == userHandle) {
return user;
}
}
return null;
}
and
public List<UserInfo> getProfiles(int userHandle) {
try {
return mService.getProfiles(userHandle, false /* enabledOnly */);
} catch (RemoteException re) {
Log.w(TAG, "Could not get user list", re);
return null;
}
}
So, if there is something wrong with AIDL request, or user's profile is disabled you will have NPE in ApplicationPackageManager.java code. I think it is impossible to prevent this situation, and I advise you to wrap notification creation in try{}catch block

Android: How to check for a specific exception?

How to check for a specific exception, e.g. SocketException with message "Socket closed"? We can compare strings like this:
if (exception.getMessage().equals("Socket closed"))...
but is there some more elegant method, like comparing error codes, or comparison with constant exception value?
Except if SocketException is always "Socket closed", but in docs it states that this class is a superclass for all socket exceptions, so there is more than one.
UPDATE:
I don't want to check for exception class. If I do, I would use specialized catch rather than to check tor a class explicitly:
catch (SocketException ex) { ... }
I want some more elegant method to distinct two exceptions which are instances of the same class, not by comparing strings like this:
try {
int i = 2;
if (i == 1) throw new SocketException("one");
else if (i == 2) throw new SocketException("two");
}
catch (SocketException ex) {
if (ex.getMessage().equals("one")) { ... }
}
In this particular case I throw exceptions to show what is it about, but in reality it can be code not controlled by me.
Also I noticed that exception message in one particular case method threw "Socket closed", in another different method threw "Socket is closed". So it's not so reliable to stick to the message either.
Your question has different approaches, depending on what you are trying to achieve. The simplest method for determining if you have the exception you want is to use instanceof since an Exception is a class as well, i.e.:
if (myException instanceof SocketException) {
...
}
However, you then add the requirement of the contents of the message or the possibility that the Exception thrown is actually a subclass of the Exception of interest to you. In the case of a "subclass" you can check if it is a subclass with:
if (myException instanceof SocketException &&
myException.getClass() != SocketException.class) {
// then I'm an instance of a subclass of SocketException, but not SocketExcpetion itself
}
Or conversely, only evaluate for the parent class:
if (myException instanceof SocketException &&
myException.getClass() == SocketException.class) {
// then I'm an instance of the class SocketException, and not a cubclass of SocketExcpetion!!
}
These serve as the "error codes" you seem to be looking for - the identification of the class, with certainty.
However, if you really are interested in the human-readable error contents, then the solution you have should be your implementation. That seems unlikely, but sometimes that is what is required.
You can use:
exception.getClass().getSimpleName() and compare it to SocketException
Hope this helps.

Android not waiting for DB response before finishing statement

I have an interesting problem that I've never run into in programming before. I have an onClickListener that does a lot of username and password checks (makes sure the username is proper length, not taken, etc). I'm using MobDB, and I was using a conditional statement that would return a row if the username already existed. The problem is that the Listener skips the DB and goes to the final check that, if everything works, posts a new username and password to my DB. How can I make it wait for a response from the DB before skipping to the last check?
Here is the relevant code:
usernamecheck3 = true;
MobDB.getInstance().execute(APP_KEY, null, rd, null, false, new MobDBResponseListener() {
#Override public void mobDBSuccessResponse() {
usernamecheck3 = false;
Log.e("mobdbSuccess:", "success");
}
#Override public void mobDBResponse(Vector<HashMap<String, Object[]>> row) {
}
#Override public void mobDBResponse(String jsonObj) {
/*Log.e("mobdbSuccess:", "jsonObj");
Log.e("mobdbSuccess:", jsonObj);
JSONObject mainObject;
try {
mainObject = new JSONObject(jsonObj);
// need to parse the json object.
} catch (JSONException e1) {
e1.printStackTrace();
} */
}
#Override public void mobDBFileResponse(String fileName, byte[] fileData) {
//get file name with extension and file byte array
}
#Override public void mobDBErrorResponse(Integer errValue, String errMsg) {
usernamecheck3 = false;
Log.e("doesnt", "work");
}
});
if(usernamecheck3 == false){
Toast.makeText(getApplicationContext(), "Username is taken, please choose another", Toast.LENGTH_SHORT).show();
}
Basically the check always returns true, and then logcat will say mobdbSuccess: success, which should have set the Bool to false.
Thanks.
MobDBResponseListener is executing on a different thread. What happens here is that the processing is split, while a thread is doing the query, the main thread on which you added the listener, skips right ahead to the validation. Your best bet is to place the validation inside the MobDBResponseListener, on the mobDBResponse method.
Try to debug your code and calls, the Listener may be using an async task. If so, you may do anything you please from the response method, as it will be executing in the main thread again. Otherwise, you should look at solutions that handle threaded execution like Handlers

Strange behavior in long-running XML parsing method

We have the following method to parse an XML file and display its contents accordingly:
#Background
#AfterInject
void parseXMLAndLoadContent() {
try {
URL url = new URL(URI);
xmlParser.setInput((InputStream) url.getContent());
showProgressDialog();
angeboteXML = xmlParser.parse();
if (angeboteXML != null) { // Breakpoint here
if (angeboteXML.backgroundImage != "") {
loadBitmapFromUrl(angeboteXML.backgroundImage);
}
loadAngebote();
} else
throw new Exception();
} catch (Exception exception) {
showToast();
} finally {
dismissProgressDialog();
}
}
As you can see it is supposed to show the a progress dialog (method annotated with #UiThread), then call the XML parser and handle the result.
Unfortunately, this does only work when I set a breakpoint in the line mentioned above, just after the call of parse(). Somehow, this leads to a certain grace period, that allows the parser to handle the document. If I just let it run without the breakpoint, nothing happens, not even the progress dialogue shows up and angeboteXML is null.
Since I am no Android expert - why is this happening and is there anything I can improve? As far as my understanding goes, this should be executed sequentially, i.e. after the parser is done parsing, everything else is executed. But this is somehow not the case here.
Edit 16/05/13 13:21:
Adding a Thread.sleep(1000) after parse() helps, but it seems more like a workaround than a fix.
This is the trace log of method execution:
05-16 13:19:26.168: I/AngeboteActivity(6051): Entering [void parseXMLAndLoadContent() ]
05-16 13:19:26.278: I/AngeboteXMLParser(6051): Entering [public de.sample.app.helper.AngeboteXML parse() throws org.xmlpull.v1.XmlPullParserException, java.io.IOException]
05-16 13:19:26.318: I/AngeboteXMLParser(6051): Exiting [public de.sample.app.helper.AngeboteXML parse() throws org.xmlpull.v1.XmlPullParserException, java.io.IOException], duration in ms: 35
05-16 13:19:26.318: I/AngeboteActivity(6051): Exiting [void parseXMLAndLoadContent() ], duration in ms: 147
05-16 13:19:26.318: I/AngeboteActivity(6051): Entering [void loadAngebote() ]
loadAngebote() is where a NPE is thrown, since the parser seems to be not yet finished.
Edit 16/05/13 13:29
This is how the parse() method is implemented:
public AngeboteXML parse() throws XmlPullParserException, IOException {
this.xml = new AngeboteXML();
int eventType = this.parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_TAG :
this.readStartTag(this.parser.getName());
break;
case XmlPullParser.END_TAG :
this.readEndTag(this.parser.getName());
break;
case XmlPullParser.TEXT :
this.readText(this.parser.getText());
break;
default :
break;
}
this.parser.next();
eventType = this.parser.getEventType();
}
return xml;
}
Actually, I think this is a design problem. The call to xmlParser.parse() is the task you want to execute in the background. Everything before and after that belongs in another method, which triggers this task.
I don't know how the #Background feature works, but if you would use the http://developer.android.com/reference/android/os/AsyncTask.html, there would be a onProgressUpdate (put showProgressDialog() in here) and a onPostExecute callback (put dismissProgressDialog() in here). Looking at the documentation of android annotations, I would suggest the following:
#AfterViews
void initXMLParsing() {
showProgressDialog();
parseXMLAndLoadContent();
}
#Background
void parseXMLAndLoadContent() {
try {
// ...
} catch (Exception exception) {
showToast();
} finally {
dismissProgressDialog();
}
}

Throw a custom exception from a service to an activity

I'm currently working on an XMPP app' on Android and I'm pondering about the best way to throw a different type of Exception than a RemoteException to my activity from my service.
As it seems impossible to throw another thing than a RemoteException using IPC (you can't declare to throw anything in your .aidl), I just see two solutions:
Create a listener for my activity to listen on my custom XMPP exception, which in fact will not be thrown but just sent as a usual object implementing the Parcelable protocol.
Catch my XMPPException and throw a RemoteException (with a content updated with my XMPPException) - But in that case, how could I know on my activity if it's an XMPP or a real RemoteException ? By tagging the name of the exception and parsing it on my activity ? It would be really gore.
Do you have any idea ? Did I miss something from the SDK documentation ?
Thanks.
If #1 means what I think it does, I'd use that -- have the service catch the exception and call a method on an AIDL-defined callback object created and supplied by the activity.
You can see an example of that technique in this client and service project, from one of my books.
It looks like we can throw custom exceptions derived from RemoteException. So you can have XMPPRemoteException, or just a generic MyRemoteException that will hold the original exception. Below is a demo for the second case:
Server:
try {
...
}
catch(XMPPException e) {
throw new MyRemoteException(e);
}
Client:
try {
service.someCall();
}
catch(MyRemoteException e) {
rethrow(e);
}
Helper method:
private void rethrow(MyRemoteException e) throws Exception {
if(e.innerException instanceof XMPPException)
throw (XMPPException)e.innerException;
else
throw e.innerException;
}
Exception:
public class MyRemoteException extends RemoteException {
private static final long serialVersionUID = 1L;
public Exception innerException;
public MyRemoteException() {}
public MyRemoteException(Exception innerException) {
this.innerException = innerException;
}
}
I think it is impossible to achieve "Throw a custom exception from a service to an activity".
See the resource of Parcel:
/**
* Use this function for customized exception handling.
* customized method call this method for all unknown case
* #param code exception code
* #param msg exception message
*/
public final void readException(int code, String msg) {
switch (code) {
case EX_SECURITY:
throw new SecurityException(msg);
case EX_BAD_PARCELABLE:
throw new BadParcelableException(msg);
case EX_ILLEGAL_ARGUMENT:
throw new IllegalArgumentException(msg);
case EX_NULL_POINTER:
throw new NullPointerException(msg);
case EX_ILLEGAL_STATE:
throw new IllegalStateException(msg);
}
throw new RuntimeException("Unknown exception code: " + code
+ " msg " + msg);
}
so we can know that we just can throw these five exceptions above.
for example:
If your service throw a IllegalArgumentException:
#Override
public void addImage(final int align, final byte[] imageData) throws RemoteException {
log("/// addImage ///");
if (imageData == null) {
throw new IllegalArgumentException("The second argument(image data) can not be empty!");
}
...
}
your client will can catch it:
try {
printer.addImage(0, null);
} catch (IllegalArgumentException e) {
e.printStackTrace();
}

Categories

Resources