Wednesday, August 13, 2014

Solution/Precaution to avoid android.os.TransactionTooLargeException

Exception: :mad:

 java.lang.RuntimeException: android.os.TransactionTooLargeException  
 at android.accounts.AccountManager.addAccountExplicitly(AccountManager.java:568)  

Reason: ;))

The Binder transaction failed because it was too large.
During a remote procedure call, the arguments and the return value of the call are transferred as Parcel objects stored in the Binder transaction buffer. If the arguments or the return value are too large to fit in the transaction buffer, then the call will fail and TransactionTooLargeException will be thrown.

Possibility Cases: :-w 

There are two possible outcomes when a remote procedure call throws TransactionTooLargeException.

  • Either the client was unable to send its request to the service (most likely if the arguments were too large to fit in the transaction buffer).
  • The service was unable to send its response back to the client (most likely if the return value was too large to fit in the transaction buffer).
It is not possible to tell which of these outcomes actually occurred. The client should assume that a partial failure occurred.

Assumption: :-?

While adding account to AccountManager. Adds an account directly to the AccountManager with the help of service call.
When there is a huge amount of data getting exchanged between a service and an application, we will get android.os.TransactionTooLargeException.

Solution/Precaution to avoid android.os.TransactionTooLargeException *-:)

We don't have direct solution but we can take precaution to avoid exception.
  1. Try to keep all transactions relatively small.
  2. Do not exchange huge data (roughly not greater than 512KB) between services and application because the Binder transaction buffer has a limited fixed size, currently 1Mb, which is shared by all transactions in progress for the process. 


Thanks for reading :) 
Whether this post is helpful?

Have something to add to this post? If you have any other quick thoughts/hints that you think people will find useful? Share it in the comments and feedback are welcome...

Wednesday, August 6, 2014

Solution for ClientProtocolException Caused by CircularRedirectException.

Exception occurred while hitting URL:X(:((

 org.apache.http.client.ClientProtocolException   
 07-28 04:26:53.349: W/System.err(1276): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:557)  
 07-28 04:26:53.349: W/System.err(1276): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)  
 07-28 04:26:53.349: W/System.err(1276): at com.loopj.android.http.AsyncHttpRequest.makeRequest(AsyncHttpRequest.java:78)  
 07-28 04:26:53.349: W/System.err(1276): at com.loopj.android.http.AsyncHttpRequest.makeRequestWithRetries(AsyncHttpRequest.java:102)  
 07-28 04:26:53.349: W/System.err(1276): at com.loopj.android.http.AsyncHttpRequest.run(AsyncHttpRequest.java:58)  
 07-28 04:26:53.349: W/System.err(1276): at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:390)  
 07-28 04:26:53.349: W/System.err(1276): at java.util.concurrent.FutureTask.run(FutureTask.java:234)  
 07-28 04:26:53.349: W/System.err(1276): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)  
 07-28 04:26:53.349: W/System.err(1276): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)  
 07-28 04:26:53.349: W/System.err(1276): at java.lang.Thread.run(Thread.java:841)  
 07-28 04:26:53.349: W/System.err(1276): Caused by: org.apache.http.client.CircularRedirectException: Circular redirect to 'redirectURI'  
 07-28 04:26:53.353: W/System.err(1276): at org.apache.http.impl.client.DefaultRedirectHandler.getLocationURI(DefaultRedirectHandler.java:173)  
 07-28 04:26:53.353: W/System.err(1276): at org.apache.http.impl.client.DefaultRequestDirector.handleResponse(DefaultRequestDirector.java:923)  
 07-28 04:26:53.353: W/System.err(1276): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:475)  
 07-28 04:26:53.353: W/System.err(1276): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)  


Details / Information about the Exception: :-?


ProtocolException : Signals that an HTTP protocol violation has occurred. For example a malformed status line or headers, a missing message body, etc.
When RedirectHandler determines the location request is expected to be redirected to given the response from the target server and the current request execution context.

public static final String ALLOW_CIRCULAR_REDIRECTS = "http.protocol.allow-circular-redirects";
Defines whether circular redirects (redirects to the same location) should be allowed. The HTTP spec is not sufficiently clear whether circular redirects are permitted, therefore optionally they can be enabled

When the redirection and the parameter of "http.protocol.allow-circular-redirects" is false it works for the first time and from the second time it throws  CircularRedirectException("Circular redirect to '" + redirectURI + "'")

We may get doubt, why first time we aren't getting the exception and allowed but not the second time? *confused*

Let look getLocationURI method of DefaultRedirectHandler.java class, we can found the code snippet as follows.


 if (redirectLocations.contains(redirectURI)) {  
      throw new CircularRedirectException("Circular redirect to '" + redirectURI + "'");  
 } else {  
      redirectLocations.add(redirectURI);  
 }  

When first time we hit, the redirectLocations object is null and it will initializes
 RedirectLocations redirectLocations = (RedirectLocations) context.getAttribute(REDIRECT_LOCATIONS);  
 if (redirectLocations == null) {  
      redirectLocations = new RedirectLocations();  
      context.setAttribute(REDIRECT_LOCATIONS, redirectLocations);  
 }  

So, the redirectURI wont be available in the redirectLocations object. When we hit the second time, the redirectURI is existing in the redirectLocations object. So, the apache throwing CircularRedirectException.

Solutions: :-bd

Here we have 2 solutions, either one of them we can use.
1. getHttpClient().getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);

2. extend DefaultRedirectHandler and modify getLocationURI method.




Thanks for reading :) 
Whether this post is helpful?

Have something to add to this post? If you have any other quick thoughts/hints that you think people will find useful? Share it in the comments / feedback's are welcome. :-h