DefaultXYZ
DefaultXYZ

Reputation: 549

How to set broadcast listener interface in fragment?

I have service, which gets data from API and sends this data to BroadcastReceiver class. Also, I create interface OnReceiveListener, which used in Activity. Look at the code here:

Activity:

public class StartActivity extends AppCompatActivity
    implements MyBroadcastReceiver.OnReceiveListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_start);

    MyBroadcastReceiver receiver = new MyBroadcastReceiver();
    receiver.setOnReceiveListener(this);
    LocalBroadcastManager.getInstance(this).registerReceiver(receiver,
            new IntentFilter(MyBroadcastReceiver.START));
    ...
}

@Override
public void onReceive(Intent intent) {
    // Do smth here
}
}

MyBroadcastReceiver:

public class MyBroadcastReceiver extends BroadcastReceiver {
public static final String START = "com.example.myapp.START";
public static final String GET_LINKS = "com.example.myapp.GET_LINKS";

private OnReceiveListener onReceiveListener = null;

public interface OnReceiveListener {
    void onReceive(Intent intent);
}

public void setOnReceiveListener(Context context) {
    this.onReceiveListener = (OnReceiveListener) context;
}

@Override
public void onReceive(Context context, Intent intent) {
    if(onReceiveListener != null) {
        onReceiveListener.onReceive(intent);
    }
}
}

Service isn't important on this question.

---- Question ----

So, what's problem: I want to use this receiver in fragment, but when it sets context - I get exception "enable to cast". What I should to do on this case?

Here is my code in fragment:

public class MainFragment extends Fragment
    implements MyBroadcastReceiver.OnReceiveListener {

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
    myBroadcastReceiver.setOnReceiveListener(getContext());
    LocalBroadcastManager.getInstance(getContext()).registerReceiver(myBroadcastReceiver,
            new IntentFilter(MyBroadcastReceiver.GET_LINKS));
}

@Override
public void onReceive(Intent intent) {
    // Do smth here
}
}

Upvotes: 0

Views: 1520

Answers (3)

Md. Ikramul Murad
Md. Ikramul Murad

Reputation: 199

After searching for hours for the appropriate way to implement such a solution to this problem, I've found a way finally. It is based on RussHWolf's answer. The complete solution with code is below:

In this way, a setListener() method is exposed so that Fragment or Activity can set the listener by sending an instance of IStatusChangeListener.

public class StatusChangeReceiver extends BroadcastReceiver {
    private IStatusChangeListener listener;

    public void setListener(IStatusChangeListener listener) {
        this.listener = listener;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        if (NetworkUtil.isNetworkConnected()) {
            listener.onConnected();
        } else {
            listener.onDisconnected();
        }
    }
}

This is the interface:

public interface IStatusChangeListener {
    void onConnected(String status);
    void onDisonnected(String status);
}

Now, it is required to have an instance of IStatusChangeListener interface instead of implementing the IStatusChangeListener interface. And then, pass this instance of IStatusChangeListener to setListener() method.

public class MainFragment extends Fragment { //Not implementing the interface

    private IStatusChangeListener listener = new IStatusChangeListener() {
        @Override
        void onConnected(String status) {
            //some log here
        }

        @Override
        void onDisonnected(String status) {
            //some log here
        }
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        StatusChangeReceiver r = new StatusChangeReceiver();
        r.setListener(listener); // pass the IStatusChangeListener instance
        LocalBroadcastManager.getInstance(getContext()).registerReceiver(r, new IntentFilter("connectionStatus"));
    }
}

Note: Always use LocalBroadcastManager if you register BroadcastReceiver from Fragment.

Upvotes: 0

Jolson Da Costa
Jolson Da Costa

Reputation: 1105

you don't need to dynamically register the receiver. i believe you must have registered it in manifest using <receiver> tag.

this is not required:

LocalBroadcastManager.getInstance(getContext()).registerReceiver(myBroadcastReceiver, new IntentFilter(MyBroadcastReceiver.GET_LINKS));

and about callback registering listener, instead of using getContext() use MainFragment.this like this:

myBroadcastReceiver.setOnReceiveListener(MainFragment.this);

Upvotes: 0

RussHWolf
RussHWolf

Reputation: 3664

Your MainFragment class implements your OnReceiveListener interface, not its Context as returned by getContext(). Instead of passing a Context object into setOnReceiveListener(), try directly passing an OnReceiveListener instance. Then your fragment and activity can both call setOnReceiveListener(this).

Upvotes: 0

Related Questions