Reputation: 27
I want to analyse an intent receiving from a broadcast. Because there could be different intents from different broadcasts. To evaluate the different broadcasts I want to use a switch case
statement like this:
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case Intent.ACTION_SCREEN_OFF:
//code for this intent
}
}
But I know it is not possible to create a switch case statement like this, so I think I need something like an integer value to identify the intents, but I can't find a method to get such a value from my intent.
Can anybody tell me how to analyse the different intents with a switch case
statement?
Edit: Works with else-if
, but I want to use switch-case
Upvotes: 0
Views: 3162
Reputation: 582
3 month ago, I answered this question. now I have a better idea than before.
Simply, you don't have to use switch statement in onReceive method. Because there is more efficient way than it. Use reflection to make each intent helper handle themselves!
see the code below:
public class SOReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {INTENT.onHandleIntent(this, intent);}
public static class INTENT {
public static void onHandleIntent(SOReceiver intentService, Intent intent) {
for (Class<?> clazz : INTENT.class.getDeclaredClasses()) {
// note: this code use getSimpleName!
if (clazz.getSimpleName().equals(intent.getAction())) {
try {
IntentInterface instance = (IntentInterface) clazz.newInstance();
instance.onReceive(intentService, intent);
} catch (Exception e) {
e.printStackTrace();
}
return;
}
}
// unexpected INTENT arrived.
}
private static interface IntentInterface {
void onReceive(SOReceiver intentService, Intent intent);
}
public static class EACH_ACTION implements IntentInterface {
// usage ex: SOReceiver.INTENT.EACH_ACTION.start(context,3.0,1);
private static final String PARAM_FOO = "PARAM_FOO";
private static final String PARAM_BAR = "PARAM_BAR";
public static void start(Context context, double foo, int bar) {
Intent intent = new Intent();
intent.setAction(EACH_ACTION.class.getSimpleName()); // necessary
intent.setClass(context, SOReceiver.class); // optional, but recommended.
intent.putExtra(PARAM_FOO,foo);
intent.putExtra(PARAM_BAR,bar);
context.sendBroadcast(intent);
// or if you want to use this as pending intent.
// PendingIntent.getBroadcast(context,0,intent,0);
}
@Override
public void onReceive(SOReceiver intentService, Intent intent) {
Bundle extras = intent.getExtras();
double foo = extras.getDouble(PARAM_FOO);
int bar = extras.getInt(PARAM_BAR);
// ... do what ever you want to do with this intent and parameters ...
}
}
}
}
this is better than older answer. it is short, easy to read and easy to add more intents.
Upvotes: 0
Reputation: 582
I want to use switch-case statement, too.
So I create custom enum class that its constructor requires intent action string like below:
(because enum can be used for switch-case statement)
enum ACTION {
INVALID("action.invalid"), // action for ignore.
FOO("action.foo"),
BAR("action.bar"),;
private final String action;
ACTION(String action) {
this.action = action;
}
public String getAction() { // to use it for intentFilter.
return action;
}
public static ACTION getEnum(String action) {
for (ACTION act : values()) {
if (act.action.equals(action)) return act;
}
return INVALID; // do not throw exception like IllegalArgumentException or else. throw exception may disturb your code refactoring.
}
// example - just broadcast
public void broadcast(Context ctx, PARAM.Abstract p) { // I will explain PARAM class later.
Intent intent = new Intent();
intent.setAction(action);
p.injectExtras(intent); // see impl below!
ctx.sendBroadcast(intent);
}
// example - use AlarmManager
public void alarm(Context ctx, Date time, PARAM.Abstract p) {
Intent intent = new Intent();
intent.setAction(action);
p.injectExtras(intent); // see impl below!
AlarmManager alarmManager = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(ctx, 0, intent, 0);
alarmManager.set(AlarmManager.RTC, time.getTime(), pendingIntent);
}
// of course, you can use ctx.startService, or else.
}
use example:
// trigger it.
ACTION.FOO.broadcast(context,new PARAM.Abstract());
...
// receive & handle it.
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
ACTION anEnum = ACTION.getEnum(action);
switch (anEnum) {
case INVALID: // it can be occured by old version's legacy alarm.
Log.w("INVALID action occured:"+action);
break;
case FOO:
// do something for FOO
break;
case BAR:
// do something for FOO
break;
defalut:
Log.d("Unimplement! action:"+action);
break;
}
}
...
// and I recommend below, when register broadcast receiver.
// create this method below of onReceive.
private IntentFilter getIntentFilter() {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION.FOO.getAction());
filter.addAction(ACTION.BAR.getAction());
return filter;
}
...
// register your receiver like this
BroadcastReceiver my = new MyBroadcastReceiver();
registerReceiver(my, my.getIntentFilter());
explain PARMA.Abstrat
Using enum to broadcast is handy.
It reduces work likes typing codes(} else if(action.equals("blahblah") {
) and declaring actions(static final ACTION_FOO="action.foo"
).
but.. when you need to put some extras to send something to other component, you can find out there is no way to do like ACTION.FOO.broadcastWithParam(p);
. even if you implemented broadcastWithParam()
on FOO
you can't access method broadcastWithParam()
. because that is how enum works.(see this thread for detail)
so we need to do it something other way.
In my case, I decide to use class (PARAM
).
declare:
class PARAM {
public static class Abstract {
protected void injectExtras(Intent intent){
// do nothing for action don't need to extas...
}
}
public static class FOO extends Abstract { // this is for ACTION.FOO
public static final String P1_KEY="p1";
public static final String P2_KEY="p2";
String p1;
int p2;
public FOO(String p1, int p2){
this.p1 =p1;
this.p2 =p2;
}
@Override
protected void injectExtras(Intent intent){
intent.putExtra(P1_KEY,this.p1);
intent.putExtra(P2_KEY,this.p2);
}
}
public static class BAR extends Abstract{ // this is for ACTION.BAR
...
}
}
use example:
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
ACTION anEnum = ACTION.getEnum(action);
switch (anEnum) {
case FOO:
Bundle extras = intent.getExtras();
String p1 = extras.getString(PARAM.FOO.P1_KEY);
int p2 = extras.getString(PARAM.FOO.P2_KEY);
// do something with p1 & p2;
break;
}
}
Finally,
I use 'ACTION&
PARAM` as inner class of Service, BroadcastReceiver or else.
example:
public class MyIntentService extends IntentService {
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
ACTION anEnum = ACTION.getEnum(action);
switch (anEnum) {
case INVALID: // it can be occured by old version's legacy alarm.
Log.w("INVALID action occured:"+action);
break;
case FOO:
// do something for FOO
break;
case BAR:
// do something for FOO
break;
defalut:
Log.d("Unimplement! action:"+action);
break;
}
}
}
public static enum ACTION {...}
public static class PARAM {...}
}
Upvotes: 2
Reputation: 602
All Intent.ACTION_* fields are String constant.
You cannot use switch with String until JDK 7 android use JDK 6 or 5 to compile. So you can't use that method on Android
But you can use else if
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF) {
// Do
} else if (intent.getAction().equals(Intent.ANYTINGS) {
//do
}
Upvotes: 1