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. How can I call methods in Activity from an event listener of a custom Adapter?

Hi everyone,

I have created a ListView and a custom Adapter with ImageButton widget
in each row. I set the ImageButton OnClick Listener in getView method
to trigger each ImageButton's OnClick event of each ListView row.
Everything goes well, but I have no idea how to call Activity methods
from ImageButtons' OnClickListener handler.

I initial my ListView as following code

in MyActivity class:

protected void onCreate(Bundle savedInstanceState) {
          MyListAdapter myListAdapter = new MyListAdapter
( MyActivity.this,
                                R.layout.list_row,
                                myList );
          myListView.setAdapter(myListAdapter);
}

in MyListAdapter  class:

public View getView(int position, View convertView, ViewGroup parent)
{
  LayoutInflater inflate = LayoutInflater.from( context );
  View v = inflate.inflate( rowResID, parent, false);
  ImageButton button1 = (ImageButton)v.findViewById( R.id.button1 );

   button1.setOnClickListener(new View.OnClickListener() {
              public void onClick(View view) {

                     //How to call MyActivity class methods from
here??

              }
    });
}

Thank you for your kindly help in advance.

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

2. device to device broadcasts possible via wi-fi?

Does anyone know of a way to broadcast a message via Wi-Fi from one
Android device to all of its neighbors that are within Wi-Fi range?
If not, does anyone know if this type of functionality is planned for
a future release?

Thanks for any insights.

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

3. CHEAP MONCLER JACKET, GSTAR JEANS, COOGI JEANS, EVISU JEANS, POLO T-SHIRT, ARMANI...

4. question about orientation sensor

5. is an AppWidget Configuration Activity required?

6. How to make a SQL database accessable from a ContentProvider?

7. Cant a service talk to other service