Edit 2: a possible solution for a widget is:
Save a timestamp
to the SharedPreferences
(for each action if you need it) once your action is completed.
Once the onReceive
is called again check the timestamp
for your preferred millis
delta and only run the action again if the delta is long enough.
Edit1: the answer below does not work for widgets, I'll leave it for anyone looking for the "regular" case
I've tried quite a few things (including using a Handler
and Reflection
), finally I've come up with the following solution: when you receive a message you do not want to get again, unregister
(that specific action) and register
when the action is done. the BroadcastReceiver
is below and here is the full example project
package com.exmplae.testbroadcastreceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
public class SelfRegisteringBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "SelfRegisteringBR";
public static final String TEST_ACTION1 = "TEST_ACTION1";
public static final String TEST_ACTION2 = "TEST_ACTION2";
private final ArrayList<String> registeredActions = new ArrayList<>();
private final ILogListener logListener;
private final Object registeringLock = new Object();
public static IntentFilter getIntentFilter() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TEST_ACTION1);
intentFilter.addAction(TEST_ACTION2);
return intentFilter;
}
public SelfRegisteringBroadcastReceiver(ILogListener logListener) {
this.logListener = logListener;
registeredActions.add(TEST_ACTION1);
registeredActions.add(TEST_ACTION2);
}
private void register(Context context, String action) {
synchronized (registeringLock) {
if (!registeredActions.contains(action)) {
registeredActions.add(action);
context.unregisterReceiver(this);
register(context);
}
}
}
private void register(Context context) {
IntentFilter intentFilter = new IntentFilter();
for (String action : registeredActions) {
intentFilter.addAction(action);
}
context.registerReceiver(this, intentFilter);
}
private void unregister(Context context, String action) {
synchronized (registeringLock) {
if (registeredActions.contains(action)) {
registeredActions.remove(action);
context.unregisterReceiver(this);
register(context);
}
}
}
@Override
public void onReceive(Context context, Intent intent) {
logListener.d(TAG, "onReceive");
if (intent == null) {
logListener.e(TAG, "intent = null");
return;
}
String action = intent.getAction();
if (action == null) {
logListener.e(TAG, "action = null");
return;
}
//noinspection IfCanBeSwitch
if (action.equals(TEST_ACTION1)) {
doAction1(context, TEST_ACTION1);
} else if (action.equals(TEST_ACTION2)) {
doAction2();
} else {
logListener.e(TAG, "Received unknown action: " + action);
}
}
private void doAction1(final Context context, final String actionName) {
logListener.d(TAG, "doAction1 start (and unregister)");
unregister(context, actionName);
Observable.just(true).delay(10, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Boolean>() {
@Override
public void onSubscribe(Disposable d) {
logListener.d(TAG, "doAction1 - onSubscribe");
}
@Override
public void onNext(Boolean aBoolean) {
logListener.d(TAG, "doAction1 - onNext");
}
@Override
public void onError(Throwable e) {
logListener.e(TAG, "doAction1 - onError");
}
@Override
public void onComplete() {
logListener.d(TAG, "doAction1 - onComplete (and register)");
register(context, actionName);
}
});
logListener.d(TAG, "doAction1 end");
}
private void doAction2() {
logListener.d(TAG, "doAction2 start");
Observable.just(true).delay(3, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Boolean>() {
@Override
public void onSubscribe(Disposable d) {
logListener.d(TAG, "doAction2 - onSubscribe");
}
@Override
public void onNext(Boolean aBoolean) {
logListener.d(TAG, "doAction2 - onNext");
}
@Override
public void onError(Throwable e) {
logListener.e(TAG, "doAction2 - onError");
}
@Override
public void onComplete() {
logListener.d(TAG, "doAction2 - onComplete");
}
});
logListener.d(TAG, "doAction2 end");
}
}