As enums aren't primitive types, what's the most effective way to pass an enum through an aidl interface in Android? Is there a way to convert the enum to an ordinal first?
-
Take a look at Charlie Collins' comment. That's completely true: avoid enums as much as possible. – Cristian Feb 08 '11 at 20:51
-
@Cristian that needs to be taken with a grain of salt. enums are good design. there's a reason why android doesn't remove enums from the language. – Jeffrey Blattman Aug 08 '13 at 16:47
-
That's true dude. However, I think they didn't move it because it's not that easy. They still use `javac` before dexing the bytecode. Anyway... I love enums, and use them when they make things clear and elegant. – Cristian Aug 08 '13 at 20:14
-
1Enums are perfectly fine in app code. Framework authors operate under a different set of constraints. (Compare, for instance, how MFC avoids virtuals in many of its core classes.) For Android specifically, early tests showed that enums consumed significantly more memory than constants, so the framework avoids them. YMMV. In fact, your mileage *will* vary, so do the right thing for your app rather than just doing what everybody else is doing. – Ian Ni-Lewis May 26 '16 at 16:56
-
1Somewhere in the deep web, Google gave us the go-ahead to use enums in Android code. Somewhere in the neighborhood of 600 bytes for an enum. And phones have come a long way since Android 1.0. Go for it. – Robin Davies Apr 21 '19 at 02:27
3 Answers
I simply use
String enumString = myEnum.name()
(with MyEnum as enum and myEnum as value) to get the String representation and then
MyEnum myEnum = MyEnum.valueOf(enumString)
to reconstruct the enum from the String representation.
Using Ordinals may be a wee bit faster but if I may add Enums later, this is more likely to break old code.
//Edit: As I don't like to have String as return type, I now implemented Parcellable like mentioned here: Passing enum or object through an intent (the best solution)
import android.os.Parcel; import android.os.Parcelable;
enum InitResponse implements Parcelable {
// Everything is fine.
SUCCESS,
// Something else
FOO;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(final Parcel dest, final int flags) {
dest.writeString(name());
}
public static final Creator<InitResponse> CREATOR = new Creator<InitResponse>() {
@Override
public InitResponse createFromParcel(final Parcel source) {
return InitResponse.valueOf(source.readString());
}
@Override
public InitResponse[] newArray(final int size) {
return new InitResponse[size];
}
};
}
-
1I now ended up combinding this approach with the Parcellable-Implementation from http://stackoverflow.com/questions/2836256/passing-enum-or-object-through-an-intent-the-best-solution resulting in the edited code above. – domenukk May 22 '12 at 19:49
Non primitive types, other than
String
, require a directional indicator. Directional indicators includein
,out
andinout
.
Take a look at the official documentation for that: http://developer.android.com/guide/developing/tools/aidl.html#aidlsyntax
Also, you can consider passing the String or ordinal representation of the enum and translate it back when needed. This is taken from the Effective Java 2nd edition:
// Implementing a fromString method on an enum type
private static final Map<String, Operation> stringToEnum = new HashMap<String, Operation>();
static { // Initialize map from constant name to enum constant
for (Operation op : values())
stringToEnum.put(op.toString(), op);
} // Returns Operation for string, or null if string is invalid
public static Operation fromString(String symbol) {
return stringToEnum.get(symbol);
}
In the case above, Operation
is an enum
.
To get the ordinal of an enum consider this example:
public enum Badges{
GOLD, SILVER, BRONZE;
}
// somewhere else:
int ordinal = Badges.SILVER.ordinal();// this should be 1

- 198,401
- 62
- 356
- 264
-
1You should also consider avoiding enums entirely (in an Android project), if you can help it. http://developer.android.com/guide/practices/design/performance.html#avoid_enums – Charlie Collins Feb 08 '11 at 20:47
-
Unfortunately I don't have the option of avoiding enums; this is a collaborative project. Can I extract the ordinal of an enum value? – Phillip Feb 09 '11 at 00:04
-
6@CharlieCollins [That](http://stackoverflow.com/questions/5143256/why-was-avoid-enums-where-you-only-need-ints-removed-from-androids-performanc) advice has been taken back. – Sandeep Datta Jan 20 '12 at 09:37
Yes, you can pass enums through AIDL, but you do have to implement Parcelable on the enum type.
1: A Parcelable implementation.
public enum RepeatMode implements Parcelable {
NoRepeat,
RepeatAll,
RepeatTrack,
;
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(toInteger());
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<RepeatMode> CREATOR = new Creator<RepeatMode>() {
@Override
public RepeatMode createFromParcel(Parcel in) {
return RepeatMode.fromInteger(in.readInt());
}
@Override
public RepeatMode[] newArray(int size) {
return new RepeatMode[size];
}
};
public int toInteger() { return this.ordinal(); }
public static RepeatMode fromInteger(int value)
{
return values()[value];
}
}
An import:
RepeatMode.aidl: package com.cyberdyne.media;
parcelable RepeatMode;
And remember to mark enum arguments as in arguments.
Kind of obvious when you think about it. But I'm betting Google doesn't use a whole lot of enums in IBinder interfaces. I do it though. (Thank you Android studio for providing "Implement Parcelable", which doesn't work entirely for enums, but makes things relatively easy).
Discursus on Android enums:
Best practice recommendations against enums in Android were withdrawn many moons ago. You're trading about 200 bytes of executable for horrible horrible code. Phones have come a long way since Android 1.0. It's a no-brainer. Use enums. (Or use the insane Kotlin-driven attribute system that Google uses. Good luck with that.)
Official Java Lore dating back to the Original Java language spec discourages the use of naked ordinal(). The reasoning: maintainers in the deep future may unwittingly re-order the ordinals and break stuff. Frankly, I think that's pompous Java bogosity. I struggled with this for a long time, and after much soul-searching, I caved in.
public enum Badges {
GOLD,SILVER, BRONZE; // Must match @array/badge_states
public int toInteger() { return this.ordinal(); }
public static Badges fromInteger(int value) { return values()[value]);
}
If nothing else, it marks the class as one that probably persists integers. And a comment never hurts, and it makes the receiving end of marshalled enums a bit prettier (and just a tiny bit safer).

- 1,067
- 1
- 13
- 29

- 7,547
- 1
- 35
- 50