RemoteCallbackList.getBroadcastItem(int) sometimes returns null

by Streets Of Boston » Fri, 13 Mar 2009 09:08:11 GMT


Sponsored Links
 Hi,

I found out that RemoteCallbackList.getBroadcastItem(int) sometimes
returns null.  I have this code in my Service and it raises a null-
pointer exception:

...
    // instance variable of my Service
    final RemoteCallbackList<IProgressCallback> mCallbacks
            = new RemoteCallbackList<IProgressCallback>();


...
...
public boolean sendProgressCallback(String imgUri, int albumId, int
progressBytes, int progressPercent) {
        final QueuedImageUpload qiu = getUploadingImage(imgUri, albumId);
        if (qiu == null)
            return true;

        qiu.setSizeUploaded(progressBytes);

        final int totalSizePercent = mQueues.calculateRemainingSizePercent();
        final int N = mCallbacks.beginBroadcast();
        try {
                for (int i = 0; i < N; i++) {
                        try {
                                if 
(!mCallbacks.getBroadcastItem(i).progressChanged(qiu.getID(),
imgUri, albumId, progressPercent, totalSizePercent)) {
                                        return false;
                                }
                        } catch (RemoteException e) {
                                // The RemoteCallbackList will take care of 
removing
                                // the dead object for us.
                        }
                }
        }
        finally {
                mCallbacks.finishBroadcast();
        }
        return true;
}

This line is the one throwing a nullpointer exception:
"if (!mCallbacks.getBroadcastItem(i).progressChanged(qiu.getID(),
imgUri, albumId, progressPercent, totalSizePercent))"

- The mCallbacks is never null. It is declared as final.
- The local 'qui' stack-variable is never null. It is guarded by a
null-pointer check.

That only leads me to conclude that the call getBroadcastItem(i)
returns null. However, the documentation states that this method never
returns null. Is this a bug in Android?

This problem only happens on occasion (I can not reproduce it
consistently), but it happens often enough to be of concern for my
app.

BTW, someone else reported the same problem a while ago:




RemoteCallbackList.getBroadcastItem(int) sometimes returns null

by Streets Of Boston » Fri, 13 Mar 2009 11:08:48 GMT


 mmmmmmmm.... you mean that the value of 'N 'could be larger than the
actual elements accessed by getBroadcastItem(i), i.e. HashMap changes
while looping over the 'N' items...?

For now, i'm check for null and just ignore it. The problem is that it
is very hard to reproduce. It happens on rare occasions, but often
enough to be problematic.

This line has only 3 points in which it could throw a null-pointer
exception (the stack-trace reports the NPE on this line, not inside
progressChanged(...)):
- mCallbacks is null: Not possible. It is declared final and refers to
an instance.
- qiu is null: Not possible. It is a stack-variable and it has been
guarded against null value.
- getBroadcastItem(i): The only one left...

I thought that beginBroadcast() would lock the callback-list for
modification and finishBroadcast() would unlock it again. This way, N
should always be the number of items in this HashMap you were
mentioning. Am i correct in this.

I'll let you know if i can figure out which values for 'i' are
problematic :-)

Thanks for your help.

On Mar 12, 9:27pm, Dianne Hackborn <hack...@android.com> wrote:
--~--~---------~--~----~------------~-------~--~----~


Sponsored Links


RemoteCallbackList.getBroadcastItem(int) sometimes returns null

by Streets Of Boston » Fri, 13 Mar 2009 22:27:37 GMT


 Ah, thanks.

Either way, it means that the number of items in the list accessed by
getBroadcastItem is always equal to N.
The problem remains: How can getBroadcastItem(int) return null?




--~--~---------~--~----~------------~-------~--~----~



RemoteCallbackList.getBroadcastItem(int) sometimes returns null

by Streets Of Boston » Sat, 14 Mar 2009 01:56:08 GMT


 Ah, now i get it! :-)

Indeed, sendProgressCallback can be called from multiple threads. And
with your earlier explanation that the beginBroadcast does not do
locking (only a brief internal lock), it may explain the problem. In
other words, RemoteCallbackList is not thread-safe across multiple
calls to it.

I should put the broadcast code inside a 'synchronized(mCallbacks)
{ ... }' block or surround it with a ReentrantLock.
Or create mCallbacks instances for each possible thread and have my
listeners register with each of them.

Thank you very much for your help.
Have a great weekend!




--~--~---------~--~----~------------~-------~--~----~



RemoteCallbackList.getBroadcastItem(int) sometimes returns null

by Streets Of Boston » Sat, 14 Mar 2009 03:50:14 GMT


 las, this one is not a one-way interface. It expects a boolean back:
False = cancel upload of image, True = continue uploading image. It
allows the (remote) client to cancel uploads forcefully. Luckily, the
client receiving the call-back can return this answer really fast.

The client is not the same process. It is a different app (Activity)
in a different process.

What is your opinion, in terms of speed/performance: One 'mCallbacks'
instance for the Service, sending this callback to its clients, inside
a synchronized(...) block or having each a 'mCallbacks' for each
thread (max 3)? Which one would be better?
The client is always remote (other process).

Thanks!
On Mar 13, 2:29pm, Dianne Hackborn <hack...@android.com> wrote:
--~--~---------~--~----~------------~-------~--~----~



Other Threads

1. WAP Push Support

HI All

Doing some investigating and having troubles find specifics or how to
raise issues.

I send WAP push message to handsets yet have been testing the android
handsets yet they are not recieving them. All versions of Android are
affected. Other devices platforms dont have any issues "WinMo, Symbiam
list goes on"

Wierd thing I have tested it on a an HTC running Android with Sense UI
and messages are recieved.

What I would like to know if possible is anything happening to these
messages or ...

Could the device be intercepting it and trying to interprt in another
applicatiuon?
Could the device be recieving these messages yet not know what to do
with them discard them?

I have tried the dirreferent versions of WAP yet none work.

Is there a module inside android not turned on. How would I request a
change for android "if thats even possible"

Thanks

-- 

2. Loading a layout from XML inside of a derived class

Ugh, now I feel bad.  I swear I googled BEFORE asking, but after
understanding my question in a different way after posting here I did
some research and found the following post:

http://www.curious-creature.org/2009/03/01/android-layout-tricks-3-optimize-part-1/

This is exactly what I'm trying to do and answers all my questions.  I
figured I'd reply to my own post for archival purposes!

Thanks!




-- 

3. How to determine if Activity is on screen

4. AccountManager.getAuthToken() problem with more than one app

5. Debugging in Android Open Source

6. Loading a layout from XML inside of a derived class

7. How to determine if Activity is on screen