Broadcast Receiver as Inner Class in Android

Is it possible to define a broadcast receiver as an inner class in manifest file?

Yes, it is possible.

The receiver android:name attribute should look like .path.to.class.MyClass$MyInnerClass

BroadcastReceiver inner class not trigger

If you want dynamic register/unregister then register on onResume and unregister on onPause(). If you want to do it statically, register it on manifest and make your nested class static so manifest can instantiate it.

BroadcastReceiver as inner class

... because the system would have to instantiate a large Activity object to just have instanitated a recevier instance?

Yup, just like any other non-static inner class. It has to get an instance of the outer class from somewhere (e.g. by instantiating or by some other mechanism) before it can create an instances of the (non-static) inner class.

Global broadcast receivers that are invoked from intents in the manifest file that would be be instantiated automatically by the system have no such outer instance to use to create an instance of the broadcast receiver non-static inner class. This is independent of what the outer class is, Activity or not.

However, if you are using a receiver as part of working with an activity, you can manually instantiate a broadcast receiver yourself in the activity (while one of the activity callbacks, you have an instance of the outer class to work with: this) and then register/unregister it as appropriate:

public class MyActivity extends Activity {

private BroadcastReceiver myBroadcastReceiver =
new BroadcastReceiver() {
@Override
public void onReceive(...) {
...
}
});

...

public void onResume() {
super.onResume();
....
registerReceiver(myBroadcastReceiver, intentFilter);
}

public void onPause() {
super.onPause();
...
unregisterReceiver(myBroadcastReceiver);
}
...
}

Receive broadcast in MainActivity with non static inner class

I'm afraid you can't make the receiver as an inner class, because when the receiver is statically instantiated, the "holder" class has to be instantiated as well. The activity instance is only created when it is meant to be active, and that's why you got the exception.

If you want the receiver to interact with the activity (by calling non-static methods in the activity class), I suggest that you should make the receiver a non-static one. This means that you need to register an instance of the receiver in OnCreate() and unregister it in OnDestroy().

For a better design, the activity instance should be passed into the receiver via its constructor as an interface, so that the receiver does not get access to the whole activity object, but is only able to access the functionality.

Manifest should have:

<receiver android:name=".NotificationBroadcast" android:enabled="false" />

An interface for the interaction (IWorker.java for example):

public interface IWorker {
public void doThis();
public void doThat();
}

The receiver (a class on its own) takes the IWorker and does something when a broadcast is received:

public class NotificationReceiver extends BroadcastReceiver {
public static final string ACTION1 = "com.yourpackage.action1";
public static final string ACTION2 = "com.yourpackage.action2";

private IWorker worker;

public NotificationReceiver() {
}

public NotificationReceiver(IWorker worker) {
this.worker = worker;
}

@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION1)) {
worker.doThis();
} else if (intent.getAction().equals(ACTION2)) {
worker.doThat();
}
}
}

And the activity takes care of the receiver on its life cycle:

public class MyActivity extends Activity implements IWorker {
private NotificationReceiver receiver;

@override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// create the receiver
receiver = new NotificationReceiver(this);

IntentFilter filter = new IntentFilter();
filter.addAction(NotificationReceiver.ACTION1);
filter.addAction(NotificationReceiver.ACTION2);

// register it
registerReceiver(receiver, filter);
}

@override
protected void onDestroy() {
super.onDestroy();

if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
}
}

@override
public void doThis() {
System.out.println("Doing this...");
}

@override
public void doThat() {
System.out.println("Doing that...");
}
}

P.S. The above codes are for reference only, they're not tested and may not compile.

Android Broadcast Receiver as inner static class Passing a String

Move this line of code:

public void Logic(String result){// Do something...}

inside your class ScanResultReceiver and it will work for sure. Your code should look like this:

public static class ScanResultReceiver extends BroadcastReceiver {
public ScanResultReceiver() {
//empty constructor
}

@Override
public void onReceive(Context context, Intent intent) {...
// data here captured fine!
// Here I want to send my data to MainActivity Logic(result)
Logic(result);
}

public void Logic(String result){/* ... */}
}

broadcast receiver as inner class

As per your updated question, the problem is that you use the wrong Toast.makeText() method.

You want to use this one as follows:

Toast.makeText(context, msgs[i], Toast.LENGTH_SHORT).show();

The version of makeText() Nyou were using expects a string resource ID.



Related Topics



Leave a reply



Submit