I'm trying to develop a simple app using Wifi Direct. The problem is I can't get a list of available peers using onPeersAvailable method. I tried the solutions mentioned here and here but no luck.There is nothing at logs, tried using Toast instead of log but nothing showed up on the screen either. Here is my Main and BroadCastReceiver classes.
Main Class:
public class MainActivity extends AppCompatActivity {
private final String TAG = this.getClass().toString();
WifiP2pManager mManager;
WifiP2pManager.Channel mChannel;
BroadcastReceiver mReceiver;
IntentFilter mIntentFilter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(this, getMainLooper(), null);
mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
Button btn_discover = (Button) findViewById(R.id.btn_discover);
btn_discover.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
/*Toast.makeText(getApplicationContext(), "Discovery is a success.",
Toast.LENGTH_SHORT).show();*/
//startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
}
#Override
public void onFailure(int reasonCode) {
Toast.makeText(getApplicationContext(), "Discovery is a failure "+reasonCode,
Toast.LENGTH_SHORT).show();
}
});
}
});
}
/* register the broadcast receiver with the intent values to be matched */
#Override
protected void onResume() {
super.onResume();
registerReceiver(mReceiver, mIntentFilter);
}
/* unregister the broadcast receiver */
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}}
BroadCastReceiver class:
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
private final String LOG_TAG = this.toString();
private WifiP2pManager mManager;
private WifiP2pManager.Channel mChannel;
private MainActivity mActivity;
public WiFiDirectBroadcastReceiver(WifiP2pManager manager, WifiP2pManager.Channel channel,
MainActivity activity) {
super();
this.mManager = manager;
this.mChannel = channel;
this.mActivity = activity;
}
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
Log.i(LOG_TAG, "Wifi Direct is enabled");
} else {
Log.i(LOG_TAG, "Wifi Direct is not enabled");
}
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
// request available peers from the wifi p2p manager. This is an
// asynchronous call and the calling activity is notified with a
// callback on PeerListListener.onPeersAvailable()
if (mManager != null) {
mManager.requestPeers(mChannel, new WifiP2pManager.PeerListListener() {
#Override
public void onPeersAvailable(WifiP2pDeviceList wifiP2pDeviceList) {
Log.i(LOG_TAG, "Found some peers!!! "+wifiP2pDeviceList.getDeviceList().size());
}
});
}
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
// Respond to new connection or disconnections
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
// Respond to this device's wifi state changing
}
}}
I am sure my device (2012 Nexus 7 running Android 4.4.4) supports Wifi Direct.
I think the issue is because you are creating new "PeerListListener" inside the "WiFiDirectBroadcastReceiver".
Try to add it to your main activity instead:
public class MainActivity extends AppCompatActivity implements WifiP2pManager.PeerListListener
And then add new method to you main activity to listen to available peers:
#Override
public void onPeersAvailable(WifiP2pDeviceList peerList) {
Log.i(LOG_TAG, "Found some peers!!! " + peerList.getDeviceList().size());
}
Note: Don't forget to create new listener variable instead "WiFiDirectBroadcastReceiver" and pass the main activity as a reference to it.
Hope this helps.
Related
I'm having problems with android 6, with my WifiDirect connection. After connecting WIFI direct and pushing the backbutton to my app. The app leaks the intentreceiver
public class WifiDirectController
extends ServerController
implements WifiP2pManager.ConnectionInfoListener,
WifiP2pManager.ChannelListener,
WiFiDirectBroadcastReceiver.WiFiDirectBroadcastListener,
WifiDirectServer.WifiDirectServerListener {
private static final String TAG = "WP2P.Controller";
private WifiP2pManager mManager;
private WifiP2pManager.Channel mChannel;
private WifiP2pDevice mDevice;
private BroadcastReceiver mReceiver;
private boolean isWifiP2pEnabled = false;
private boolean isDiscovering = false;
private boolean isConnected = false;
private boolean retryChannel = false;
//added by Frank
private boolean isReceiverRegistered = false;
private final IntentFilter mIntentFilter = new IntentFilter();
private Handler mHandler;
private WifiDirectServer serverThread = null;
public WifiDirectController(ServerListener listener) {
super(listener);
//mManager = (WifiP2pManager) mListener.getSystemService(Context.WIFI_P2P_SERVICE);
mManager = (WifiP2pManager) mListener.getApplicationContext().getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(listener.getApplicationContext(), mListener.getMainLooper(), this);
// Indicates a change in the Wi-Fi P2P status.
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
// Indicates the state of Wi-Fi P2P connectivity has changed.
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
// Indicates this device's details have changed.
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
// Indicates that discovery has started or stopped
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);
mHandler = new Handler();
}
#Override
public void onStart()
{
Log.d(TAG, "onStart() called");
}
#Override
public void onResume() {
Log.d(TAG, "onResume() called");
Log.e(TAG, "FRANK onResume() called");
mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
if (!isReceiverRegistered) {
mListener.registerReceiver(mReceiver, mIntentFilter);
isReceiverRegistered = true;
}
}
#Override
public void onPause()
{
Log.d(TAG, "onPause() called");
mListener.unregisterReceiver(mReceiver);
isReceiverRegistered = false;
stopDiscovery();
}
#Override
public void onStop()
{
Log.d(TAG, "onStop() called");
//added frank
if (isReceiverRegistered) {
mListener.unregisterReceiver(mReceiver);
isReceiverRegistered = false;
}
//
cancelDisconnect();
stopServer();
}
#Override
public void restart()
{
Log.d(TAG, "restart() called");
Log.e(TAG, "FRANK onRestart() called");
cancelDisconnect();
stopServer();
startDiscovery();
}
private boolean startServer()
{
Log.d(TAG, " = startServer() called");
Log.e(TAG, "FRANK startServer() called");
this.serverThread = new WifiDirectServer(this);
this.serverThread.start();
return true;
}
ActivityThread: Activity com.android.settings.SubSettings has leaked IntentReceiver android.net.wifi.WifiManager$1#61ae52a that was originally registered here. Are you missing a call to unregisterReceiver()?
android.app.IntentReceiverLeaked: Activity com.android.settings.SubSettings has leaked IntentReceiver android.net.wifi.WifiManager$1#61ae52a that was originally registered here. Are you missing a call to unregisterReceiver()?
You must use a method to check if the receiver is registered, this is because when you press back button, the activity is destroyed, so the variables come back to it's original values, for that reason in the Resume method the variable isReceiverRegistered is always false, and it tries to register the receiver again.
You could unregister the receiver in the OnPause method instead of
OnStop method.
Or you can store the value of the variable overriding
onSaveInstanceState method and recoverit in onRestoreInstanceState
method.
Or you can use a ViewModel to persist the variable's values.
Or you can try using a class to manage your receivers. slinden77
gave a possible solution to this, in this thread
public class ReceiverManager {
private static List<BroadcastReceiver> receivers = new ArrayList<BroadcastReceiver>();
private static ReceiverManager ref;
private Context context;
private ReceiverManager(Context context){
this.context = context;
}
public static synchronized ReceiverManager init(Context context) {
if (ref == null) ref = new ReceiverManager(context);
return ref;
}
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter intentFilter){
receivers.add(receiver);
Intent intent = context.registerReceiver(receiver, intentFilter);
Log.i(getClass().getSimpleName(), "registered receiver: "+receiver+" with filter: "+intentFilter);
Log.i(getClass().getSimpleName(), "receiver Intent: "+intent);
return intent;
}
public boolean isReceiverRegistered(BroadcastReceiver receiver){
boolean registered = receivers.contains(receiver);
Log.i(getClass().getSimpleName(), "is receiver "+receiver+" registered? "+registered);
return registered;
}
public void unregisterReceiver(BroadcastReceiver receiver){
if (isReceiverRegistered(receiver)){
receivers.remove(receiver);
context.unregisterReceiver(receiver);
Log.i(getClass().getSimpleName(), "unregistered receiver: "+receiver);
}
}
}
I hope it helps you
I have no prior experience with app development and am now supposed to create an app in android studio that connects to a sensor by WiFi-direct. I have read up on WiFi-direct and tried to follow the guides https://developer.android.com/guide/topics/connectivity/wifip2p.html and https://stuff.mit.edu/afs/sipb/project/android/docs/training/connect-devices-wirelessly/wifi-direct.html but when using their code I have still no clue how to move forward. I have also looked at several demo apps for WiFi direct.
My code looks like this at the moment.
Broadcast reciever:
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
private WifiP2pManager mManager;
private WifiP2pManager.Channel mChannel;
private MainActivity mActivity;
public WiFiDirectBroadcastReceiver(WifiP2pManager manager, WifiP2pManager.Channel channel,
MainActivity activity) {
super();
this.mManager = manager;
this.mChannel = channel;
this.mActivity = activity;
}
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
// Check to see if Wi-Fi is enabled and notify appropriate activity
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
mActivity.setIsWifiP2pEnabled(true);
} else {
mActivity.setIsWifiP2pEnabled(false);
}
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
// Call WifiP2pManager.requestPeers() to get a list of current peers
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
// Respond to new connection or disconnections
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
// Respond to this device's wifi state changing
}
}
}
MainActivity:
public class MainActivity extends AppCompatActivity {
WifiP2pManager mManager;
WifiP2pManager.Channel mChannel;
private boolean isWifiP2pEnabled = false;
BroadcastReceiver mReceiver;
IntentFilter mIntentFilter;
public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled) {
this.isWifiP2pEnabled = isWifiP2pEnabled;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(this, getMainLooper(), null);
mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
}
/* register the broadcast receiver with the intent values to be matched */
#Override
protected void onResume() {
super.onResume();
mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
registerReceiver(mReceiver, mIntentFilter);
}
/* unregister the broadcast receiver */
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
}
The next part in the guide is that I should try to discover peers. Where should I implement this code?
mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
// Code for when the discovery initiation is successful goes here.
// No services have actually been discovered yet, so this method
// can often be left blank. Code for peer discovery goes in the
// onReceive method, detailed below.
}
#Override
public void onFailure(int reasonCode) {
// Code for when the discovery initiation fails goes here.
// Alert the user that something went wrong.
}
});
My final product should be a button that when I press it I should search for peers and be able to connect to one. The sensor will boot in WiFi direct. Does anyone know where I can find more info on how to proceed or have tips on what classes I need and such?
Thank you!
The way it works is by:
Calling discoverPeers when tapping on the button
Next, in your WiFiDirectBroadcastReceiver -> WIFI_P2P_PEERS_CHANGED_ACTION condition, request the list of available peers like this: mManager.requestPeers(mChannel, peerListListener);
Then, you have to implement WifiP2pManager.PeerListListener in your activity or fragment because the discovered peers will return into this method:
#Override
public void onPeersAvailable(WifiP2pDeviceList peerList) {}
Once you have the list of peers, you can connect to any peer using
mManager.connect(mChannel, config, new ActionListener() {});
I believe following https://developer.android.com/guide/topics/connectivity/wifip2p.html is good enough to get the api working.
Goodluck.
I'm trying to make an Android app that will scan for a certain Bluetooth device as a background service. Once the phone is within a certain range of the Bluetooth device, measured by reading the RSSI, the background service will start an Activity displayed to the user. If the phone is moved out of range of the Bluetooth device, (after the RSSI value is beyond a certain threshold,) the Activity should be killed.
Here is the code for the background service:
public class BeaconScanService extends Service implements BluetoothAdapter.LeScanCallback {
private Service self = this;
public static final String UNLOCK = "unlock";
public static final String STATUS = "status";
public static final String SIGNAL = "signal";
public static final String GET_SIGNAL = "get_signal";
//desired device to find
private static final String targetMAC = "E1:BE:A8:1A:8B:A0";
//class to handle saving RSSI values and detecting Bluetooth proximity
private proxDetector proxy;
//boolean to determine if phone is in BT range
static boolean inProx = false;
private BluetoothAdapter mBluetoothAdapter;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
//Proximity Detector
proxy = new proxDetector();
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
/*
* We need to enforce that Bluetooth is first enabled, and take the
* user to settings to enable it if they have not done so.
*/
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
//Bluetooth is disabled
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
enableBtIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(enableBtIntent);
}
/*
* Check for Bluetooth LE Support. In production, our manifest entry will keep this
* from installing on these devices, but this will allow test devices or other
* sideloads to report whether or not the feature exists.
*/
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "No LE Support.", Toast.LENGTH_SHORT).show();
return START_STICKY;
}
//Begin scanning for LE devices
startScan();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
//Cancel any scans in progress
mHandler.removeCallbacks(mStopRunnable);
mHandler.removeCallbacks(mStartRunnable);
mBluetoothAdapter.stopLeScan(this);
}
private Runnable mStopRunnable = new Runnable() {
#Override
public void run() {
stopScan();
}
};
private Runnable mStartRunnable = new Runnable() {
#Override
public void run() {
startScan();
}
};
private void startScan() {
Toast.makeText(this, "Scanning", Toast.LENGTH_SHORT).show();
//Scan for Bluetooth device with specified MAC
mBluetoothAdapter.startLeScan(this);
mHandler.postDelayed(mStopRunnable, 5000);
}
private void stopScan() {
Toast.makeText(this, "Not Scanning", Toast.LENGTH_SHORT).show();
mBluetoothAdapter.stopLeScan(this);
mHandler.postDelayed(mStartRunnable, 2500);
}
/* BluetoothAdapter.LeScanCallback */
#Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
/*
* Create a new beacon and pass it up to the main thread
*/
Toast.makeText(self, "OnLeScan", Toast.LENGTH_SHORT).show();
BT_Beacon beacon = new BT_Beacon(device.getAddress(), rssi);
mHandler.sendMessage(Message.obtain(null, 0, beacon));
}
/*
* We have a Handler to process scan results on the main thread
*/
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
Toast.makeText(self, "Handlering", Toast.LENGTH_SHORT).show();
BT_Beacon beacon = (BT_Beacon) msg.obj;
if(beacon.getAddress().equals(targetMAC)){//Only look for target device
Toast.makeText(self, String.format("%ddBm", beacon.getSignal()), Toast.LENGTH_SHORT).show();
//HANDLE PROXIMITY DETECTION
Intent i1 = new Intent(UNLOCK);
proxy.processProx(beacon.getSignal());
Intent i2 = new Intent(SIGNAL);
i2.putExtra(GET_SIGNAL, proxy.prox);
sendBroadcast(i2);
if(proxy.crossedLine()){
i1.putExtra(STATUS, 1);
sendBroadcast(i1);
inProx = true;
Intent i = new Intent(self,MyActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}else{
i1.putExtra(STATUS, 0);
sendBroadcast(i1);
inProx = false;
}
}
}
};
}
Ultimately I want this background service to be started on boot, but for testing purposes, I am able to create or destroy this service from an Activity that should also display the RSSI value:
public class MainActivity extends Activity implements OnClickListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnScan = (Button) findViewById(R.id.btnScan);
Button btnUnscan = (Button) findViewById(R.id.btnUnscan);
btnScan.setOnClickListener(this);
btnUnscan.setOnClickListener(this);
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(mReceiver, new IntentFilter(BeaconScanService.SIGNAL));
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnScan:
Intent i = new Intent(this,BeaconScanService.class);
startService(i);
break;
case R.id.btnUnscan:
Intent i = new Intent(this,BeaconScanService.class);
stopService(i);
break;
}
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(bundle != null) {
int sig = bundle.getInt(BeaconScanService.GET_SIGNAL);
TextView rssiView = (TextView) findViewById(R.id.text_rssi);
rssiView.setText(String.format("%ddBm", sig));
}
}
};
}
This is the layout for for MainActivity:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MainActivity">
<Button
android:id="#+id/btnScan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Scan"/>
<Button
android:id="#+id/btnUnscan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop Scan"
android:layout_below="#+id/btnScan"/>
<TextView
android:id="#+id/text_rssi"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceListItem"
android:text="dBm"
android:layout_below="#+id/btnUnscan"/>
</RelativeLayout>
in the activity that is started and ended by the BeaconScanService, the BroadcastReceiver is registered like this:
#Override
protected void onResume() {
super.onResume();
registerReceiver(beaconScanReceiver, new IntentFilter(BeaconScanService.UNLOCK));
}
and the BroadcastReceiver looks like this:
private final BroadcastReceiver beaconScanReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(bundle != null) {
int status = bundle.getInt(BeaconScanService.STATUS);
if(status == 0) {
finish();
}
}
}
};
When I run this code, I can start and stop the BeaconScanService fine, and I know the service is scanning for the Bluetooth device due to debug Toasts being displayed. As far as I can tell, the code breaks down somewhere in the Handler of the service. No RSSI value is displayed in the TextView, and MyActivity is not started when the phone is brought close enough to the Bluetooth device.
I'm not too familiar with the interprocess communication aspects of Android programming, so I'm probably doing something wrong there. Any thoughts?
I am working with google chat application
When chatting if network fails, I have to notify user that network disconnected and if network connected again i have to notify network connected in the same activity.But not worked out
Following is the code which I written:
public class GTChat extends ListActivity
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
private BroadcastReceiver mConnReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
NetworkInfo info = (NetworkInfo)intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if (info.getState().equals(NetworkInfo.State.CONNECTED))
{
Toast.makeText(getApplicationContext(), "Network connected",Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(getApplicationContext(), "Network not connected",Toast.LENGTH_LONG).show();
}
}
};
protected void onPause()
{
unregisterReceiver(mConnReceiver);
super.onPause();
}
protected void onResume()
{
registerReceiver(mConnReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
super.onResume();
}
call the super.onResume()/super.onPause() before to register/unregistering receiver.
protected void onPause()
{
super.onPause();
unregisterReceiver(mConnReceiver);
}
protected void onResume()
{
super.onResume();
registerReceiver(mConnReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
I have an Android Activity that needs to catch two different broadcasts. My current approach is to have a single BroadcastReceiver within the Activity and catch both the broadcasts with it:
public class MyActivity extends Activity {
private MyActivity.BroadcastListener mBroadcastListener;
private boolean mIsActivityPaused = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout);
// Create the broadcast listener and register the filters
mIsActivityPaused = false;
mBroadcastListener = new BroadcastListener();
IntentFilter filter = new IntentFilter();
filter.addAction(Params.INTENT_REFRESH);
filter.addAction(Params.INTENT_UPDATE);
registerReceiver(mBroadcastListener, filter);
}
#Override
protected void onResume() {
super.onResume();
mIsActivityPaused = false;
}
#Override
protected void onPause() {
super.onPause();
mIsActivityPaused = true;
}
#Override
protected void onDestroy() {
unregisterReceiver(mBroadcastListener);
super.onDestroy();
}
private void refresh() {
// refresh
}
private void update() {
// update
}
private class BroadcastListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Params.INTENT_REFRESH && !mIsActivityPaused)) {
refresh();
} else if (intent.getAction().equals(Params.INTENT_UPDATE)) {
update();
}
}
}
}
I want to execute refresh() only if my Activity is visible on the screen, but I want to catch INTENT_UPDATE and execute update() during the entire lifetime of the Activity, regardless of whether the Activity is visible or not.
I didn't find any way to unregister only one of the two filters that I register in onCreate, so I use a flag to enable or disable the action to be executed when the INTENT_REFRESH broadcast is caught, depending on the state of the Activity.
The question is: is this the correct approach?
Or, would it be better to have two separate BroadcastReceivers as follows:
public class MyActivity extends Activity {
private MyActivity.BroadcastListenerRefresh mBroadcastListenerRefresh;
private MyActivity.BroadcastListenerUpdate mBroadcastListenerUpdate;
private boolean mIsBroadcastListenerRefreshRegistered = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Create the broadcast listeners
mBroadcastListenerRefresh = new BroadcastListenerRefresh();
mBroadcastListenerUpdate = new BroadcastListenerUpdate();
registerReceiver(mBroadcastListenerRefresh, new IntentFilter(Params.INTENT_REFRESH));
registerReceiver(mBroadcastListenerUpdate, new IntentFilter(Params.INTENT_UPDATE));
}
#Override
protected void onResume() {
super.onResume();
if (mBroadcastListenerRefresh != null && !mIsBroadcastListenerRefreshRegistered) {
registerReceiver(mBroadcastListenerRefresh, new IntentFilter(Params.INTENT_REFRESH));
mIsBroadcastListenerRefreshRegistered = true;
}
}
#Override
protected void onPause() {
super.onPause();
if (mBroadcastListenerRefresh != null && mIsBroadcastListenerRefreshRegistered) {
unregisterReceiver(mBroadcastListenerRefresh);
mIsBroadcastListenerRefreshRegistered = false;
}
}
#Override
protected void onDestroy() {
unregisterReceiver(mBroadcastListenerRefresh);
unregisterReceiver(mBroadcastListenerUpdate);
super.onDestroy();
}
private void refresh() {
// refresh
}
private void update() {
// update
}
private class BroadcastListenerRefresh extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Params.INTENT_REFRESH)) {
refresh();
}
}
}
private class BroadcastListenerUpdate extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Params.INTENT_UPDATE)) {
update();
}
}
}
}
And which one has better performance?
instead, you may provide two different intent filters:
filter for refresh only
IntentFilter filterRefresh = new IntentFilter(Params.INTENT_REFRESH);
filter for refresh and update
IntentFilter filterRefreshUpdate = new IntentFilter();
filterRefreshUpdate.addAction(Params.INTENT_REFRESH);
filterRefreshUpdate.addAction(Params.INTENT_UPDATE);
now you may switch between intent filters by registering and un-registering the desired one but your receiver's implementation would be same
For every action , create IntentFilter and register it.
#Override
protected void onResume() {
super.onResume();
BroadcastListener receiver = new BroadcastListener();
// Register the filter for listening broadcast.
IntentFilter filterRefresh = new IntentFilter(Params.INTENT_REFRESH);
IntentFilter filterUpdate = new IntentFilter(Params.INTENT_UPDATE);
registerReceiver(receiver, filterRefresh);
registerReceiver(receiver, filterUpdate);
}
private class BroadcastListener extends BroadcastReceiver {
public void onReceive(Context ctx, Intent intent) {
if (intent.getAction().equals(Params.INTENT_UPDATE)) {
update();
} else if(intent.getAction().equals(Params.INTENT_REFRESH)) {
refresh();
}
}
}
Using KOTLIN you can do it inline:
broadcastReceiver = NukeBroadcastReceiver()
registerReceiver(broadcastReceiver, IntentFilter().apply {
addAction(ACTION_DESTROY_EVERYTHING)
addAction(ACTION_RESTART_WORLD)
})