AIDL with Map generating broken Java

599 views
Skip to first unread message

randyv2

unread,
Oct 31, 2011, 9:52:48 PM10/31/11
to Android Developers
I have an AIDL written as follows:

interface IGameInterfaceResult {
void success(out Map result);
}

In the generated .java file, I see this being generated:

_arg0 = new java.util.Map();

This leads to my project having errors because Map can't be
instantiated. This seems like a bug in the AIDL tool, but my googling
hasn't resulted in anything useful regarding this error. Does anybody
have suggestions on what I should try doing to resolve this problem?

Mark Murphy

unread,
Nov 2, 2011, 7:42:57 AM11/2/11
to android-d...@googlegroups.com
Try switching to:

Map success();

It may be that Map does not support out properly. I have never used
the out keyword in AIDL, as it leads to scary programming (relying on
side-effects applied to parameters).

> --
> You received this message because you are subscribed to the Google
> Groups "Android Developers" group.
> To post to this group, send email to android-d...@googlegroups.com
> To unsubscribe from this group, send email to
> android-develop...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/android-developers?hl=en
>

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_Android Programming Tutorials_ Version 4.0 Available!

Streets Of Boston

unread,
Nov 2, 2011, 9:37:09 AM11/2/11
to android-d...@googlegroups.com
What if you use Bundle instead (which is basically a Map implementation that implements Parcelable as well).

randyv2

unread,
Nov 2, 2011, 1:45:58 PM11/2/11
to Android Developers
I'm using this as a way to implement a callback from my service, so
I'm using the interface as a way to pass data from the service to the
callback. Making the change you've suggested wouldn't work in this
case. That said, if you've got a suggestion for a different approach
to this problem I'd love to hear it.
> Mark Murphy (a Commons Guy)http://commonsware.com|http://github.com/commonsguyhttp://commonsware.com/blog|http://twitter.com/commonsguy

randyv2

unread,
Nov 2, 2011, 1:46:49 PM11/2/11
to Android Developers
Looks like the Bundle type works just fine. Since AIDL already
imposes a Parcelable restriction on the elements contained in a Map,
the extra requirements of a Bundle aren't a problem, and the interface
will work for what I need. Thanks!

On Nov 2, 6:37 am, Streets Of Boston <flyingdutc...@gmail.com> wrote:
> What if you use *Bundle *instead (which is basically a Map implementation

Mark Murphy

unread,
Nov 2, 2011, 1:53:37 PM11/2/11
to android-d...@googlegroups.com
On Wed, Nov 2, 2011 at 1:45 PM, randyv2 <randyt...@gmail.com> wrote:
> I'm using this as a way to implement a callback from my service, so
> I'm using the interface as a way to pass data from the service to the
> callback.

Um, I'll be surprised if what you propose here is stable. I don't
think out parameters are designed for long-term use, just for a single
call (which is equivalent to returning the value). The primary
advantage of out parameters is that you can have more than one.

If you want to implement a callback, then you should implement a callback:

-- define an AIDL interface for the callback
-- have your method take an instance of that callback as a regular
(in) parameter
-- create a .Stub implementation of the callback in the client and
supply an instance of it when calling the service's exposed method
-- the service receives the proxy as the parameter to its method
implementation and can use that as needed

The RemoteClientEx and RemoteServiceEx examples in this directory
demonstrate this:

https://github.com/commonsguy/cw-advandroid/tree/master/AdvServices

--

randyv2

unread,
Nov 2, 2011, 3:26:41 PM11/2/11
to Android Developers
On Nov 2, 10:53 am, Mark Murphy <mmur...@commonsware.com> wrote:
> Um, I'll be surprised if what you propose here is stable. I don't
> think out parameters are designed for long-term use, just for a single
> call (which is equivalent to returning the value). The primary
> advantage of out parameters is that you can have more than one.
>
> If you want to implement a callback, then you should implement a callback:
>
> -- define an AIDL interface for the callback
> -- have your method take an instance of that callback as a regular
> (in) parameter
> -- create a .Stub implementation of the callback in the client and
> supply an instance of it when calling the service's exposed method
> -- the service receives the proxy as the parameter to its method
> implementation and can use that as needed
>
> The RemoteClientEx and RemoteServiceEx examples in this directory
> demonstrate this:
>
> https://github.com/commonsguy/cw-advandroid/tree/master/AdvServices

Thanks for the detailed response!

My original post doesn't contain enough context as this is a larger
issue, so I'll fill in the details now. Would it horrify you to know
that the link you provided is what I was using as a reference when I
started walking down this road? ;) Full disclosure: This is my first
Android app; I come from an iPhone background, so this is all very new
to me.

I have the following:

1. IGameInterface.aidl - This is the equivalent of IScript.aidl in the
sample code. It has one method: void doStuff(IGameInterfaceResult
callback).
2. IGameInterfaceResult.aidl - This is where the definition of the
interface for the callback goes. As in my original post, it has one
method: void success(Bundle).
3. GameService.java - Ignoring the poor naming convention for a
moment, this is a subclass of Service and functions as BshService.java
does in the sample code. It contains code like the following:

public class GameService extends Service {
private final IGameInterface.Stub binder = new IGameInterface.Stub()
{
public void doStuff(final IGameInterfaceResult callback) {
Bundle coolStuff = makeCoolStuff();
callback.success(coolStuff);
}
};
}

My (admittedly weak) understanding is that this is okay. Given the
extra context, does this still sound unstable to you?

Mark Murphy

unread,
Nov 2, 2011, 3:37:18 PM11/2/11
to android-d...@googlegroups.com
On Wed, Nov 2, 2011 at 3:26 PM, randyv2 <randyt...@gmail.com> wrote:
> Would it horrify you to know
> that the link you provided is what I was using as a reference when I
> started walking down this road? ;)

That depends. Did you buy the book? :-)

> 1. IGameInterface.aidl - This is the equivalent of IScript.aidl in the
> sample code.  It has one method: void doStuff(IGameInterfaceResult
> callback).
> 2. IGameInterfaceResult.aidl - This is where the definition of the
> interface for the callback goes. As in my original post, it has one
> method: void success(Bundle).

Where the Bundle is an out parameter?

> 3. GameService.java - Ignoring the poor naming convention for a
> moment, this is a subclass of Service and functions as BshService.java
> does in the sample code. It contains code like the following:
>
> public class GameService extends Service {
>  private final IGameInterface.Stub binder = new IGameInterface.Stub()
> {
>    public void doStuff(final IGameInterfaceResult callback) {
>      Bundle coolStuff = makeCoolStuff();
>      callback.success(coolStuff);
>    }
>  };
> }

That doesn't need an out parameter. That's an in parameter -- you are
passing the data *to* the callback. And, since in is the default
direction, you don't need the keyword at all.

Rolling back to my sample, I do the same thing you do, minus the out:

interface IScriptResult {
void success(String result);
void failure(String error);
}

From your original post on this thread, you have:

interface IGameInterfaceResult {
void success(out Map result);
}

I misunderstood your situation, which is why the Map success()
approach won't work. But, you might try:

interface IGameInterfaceResult {
void success(Map result);
}

since you don't need the out, and the out is technically wrong in this
case as I understand it. It may be that "out Map" doesn't work,
generating the flawed code you found.

Even if you're using Bundle successfully, I'd drop the out. You'd use
out if the *callback* were trying to pass data in success() back to
the *service*.

--

randyv2

unread,
Nov 2, 2011, 3:49:26 PM11/2/11
to Android Developers


On Nov 2, 12:37 pm, Mark Murphy <mmur...@commonsware.com> wrote:
> On Wed, Nov 2, 2011 at 3:26 PM, randyv2 <randythech...@gmail.com> wrote:
> > Would it horrify you to know
> > that the link you provided is what I was using as a reference when I
> > started walking down this road? ;)
>
> That depends. Did you buy the book? :-)

Not yet, but it's quickly becoming apparent that I should :) Where's
that company credit card...

> > 1. IGameInterface.aidl - This is the equivalent of IScript.aidl in the
> > sample code.  It has one method: void doStuff(IGameInterfaceResult
> > callback).
> > 2. IGameInterfaceResult.aidl - This is where the definition of the
> > interface for the callback goes. As in my original post, it has one
> > method: void success(Bundle).
>
> Where the Bundle is an out parameter?

Yes, it is currently defined as an out parameter (but see below).

> I misunderstood your situation, which is why the Map success()
> approach won't work. But, you might try:
>
> interface IGameInterfaceResult {
>        void success(Map result);
>
> }
>
> since you don't need the out, and the out is technically wrong in this
> case as I understand it. It may be that "out Map" doesn't work,
> generating the flawed code you found.
>
> Even if you're using Bundle successfully, I'd drop the out. You'd use
> out if the *callback* were trying to pass data in success() back to
> the *service*.

I misunderstood the directions that "in" and "out" mean, and had them
reversed. It looks like the correct thing for me to do is change the
"out" to an "in" (AIDL complains without a default set, as both Bundle
and Map can be passed "in", "out", or "inout", and it wants you to
tell it exactly what it is you want).

Thanks for such a thorough response! It's been very elucidating.

> --
> Mark Murphy (a Commons Guy)http://commonsware.com|http://github.com/commonsguyhttp://commonsware.com/blog|http://twitter.com/commonsguy

Mark Murphy

unread,
Nov 2, 2011, 3:52:48 PM11/2/11
to android-d...@googlegroups.com
On Wed, Nov 2, 2011 at 3:49 PM, randyv2 <randyt...@gmail.com> wrote:
> I misunderstood the directions that "in" and "out" mean, and had them
> reversed.  It looks like the correct thing for me to do is change the
> "out" to an "in" (AIDL complains without a default set, as both Bundle
> and Map can be passed "in", "out", or "inout", and it wants you to
> tell it exactly what it is you want).

Ah, yeah, the "in" default is only for primitives and Strings. My apologies.

> Thanks for such a thorough response!  It's been very elucidating.

Happy I could help. Besides, that's the first time I've seen
"elucidating" used on teh Internets in quite some time... :-)

--

Reply all
Reply to author
Forward
0 new messages