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. Some questions about ApiDemo.java

1. Basically the ApiDemo activity just calls itself recursively, is it
counter-intuitive to efficient running on mobile device?

2. The following code in getData():
        PackageManager pm = getPackageManager();
        List<ResolveInfo> list = pm.queryIntentActivities(mainIntent,
0);

        if (null == list)
            return myData;
...
Can it be moved to somewhere for efficency purpose? Since it gets
called again and again but just gets same results.

3. Consider the code in getDate():
        Map<String, Boolean> entries = new HashMap<String, Boolean>();
...
Why use Hashmap? isn't it overskilled?

Again, since it is the demo code provided by Google, I think it is
worthy to study it in detail.
--~--~---------~--~----~------------~-------~--~----~

2. Some questions about intents and Notepad example

Since Notepad example is the first classic sample provided by Google,
I think it is worth to study it in close detail.

1. Is it possible for an intent receiver receiving multiple eligible
intents at the same time? If so, what are the priorities associated
with those intents?
Is it possible for an activity receiving multiple eligible intents at
the same time? If so, what are the priorities associated with those
intents?

2. Refer to NotePad/NoteEditor.java/onCreateOptionsMenu() comments. Do
we really need to query system for all activities that implement
ALTERNATIVE_ACTION on the data, and add a menu item for each one that
is found?

3. Where in the code showing the title-editor activity pop-ups a
floated window?

4. In com.google.provider/NotePad.java:

    public static final class Notes implements BaseColumns {
        /**
         * The content:// style URL for this table
         */
        public static final Uri CONTENT_URI
                = Uri.parse("content://com.google.provider.NotePad/
notes");

   where is the "notes" used? What is the purpose of this NotePad.java
file?
--~--~---------~--~----~------------~-------~--~----~

3. Good to join your group 鈥?A t hought : work hard, pay your taxes and smile

4. Notepadv2 - please update the tutorials

5. 2 xml files in one java file

6. BUG: terrible one

7. How to do reverse geocoding ??