use of net.grandcentrix.tray.core.OnTrayPreferenceChangeListener in project tray by grandcentrix.
the class ChangedListenerTest method checkChangeListener.
private ContentProviderStorage checkChangeListener(boolean registerWithLooper, final OnTrayPreferenceChangeListener otherListener) throws Exception {
final ContentProviderStorage userStorage = new ContentProviderStorage(getProviderMockContext(), "testChanged", TrayStorage.Type.USER);
final CountDownLatch listenerCalledLatch = new CountDownLatch(1);
final boolean[] listenerCalled = { false };
final Looper[] looperRegisteredOn = { null };
final OnTrayPreferenceChangeListener listener = new OnTrayPreferenceChangeListener() {
@Override
public void onTrayPreferenceChanged(final Collection<TrayItem> items) {
// check if called on the correct looper if one is set.
assertEquals(looperRegisteredOn[0], Looper.myLooper());
listenerCalled[0] = true;
listenerCalledLatch.countDown();
}
};
final CountDownLatch registerLatch = new CountDownLatch(1);
if (registerWithLooper) {
// registers in a thread with a looper
new HandlerThread("register") {
@Override
protected void onLooperPrepared() {
super.onLooperPrepared();
looperRegisteredOn[0] = Looper.myLooper();
userStorage.registerOnTrayPreferenceChangeListener(listener);
if (otherListener != null) {
userStorage.registerOnTrayPreferenceChangeListener(otherListener);
}
registerLatch.countDown();
}
}.start();
} else {
// registers in a thread without a looper
new Thread(new Runnable() {
@Override
public void run() {
userStorage.registerOnTrayPreferenceChangeListener(listener);
registerLatch.countDown();
}
}).start();
}
registerLatch.await(1000, TimeUnit.MILLISECONDS);
assertNotNull(userStorage.mObserver);
assertNotNull(userStorage.mObserverThread);
assertFalse(listenerCalled[0]);
final TrayUri trayUri = new TrayUri(getProviderMockContext());
final Uri uri = trayUri.get();
if (registerWithLooper) {
// if not a looper thread the handler in the onChange method does not fire
new HandlerThread("change") {
@Override
protected void onLooperPrepared() {
super.onLooperPrepared();
// in a perfect world I could change a value in the storage an it will call the
// listener. But this is andorid and testing is hard. Even harder with threading.
// The hardest thing here is the Isolated context, and the dependency to the Looper
// to get the change from the content provider.
//
// tl;dr the ContentObserver does not work in a ProviderTestCase2 so I call the
// listener myself instead of changing data.
//
// wasted hours so far: 12
// userStorage.put("the", "change");
userStorage.mObserver.onChange(false, uri);
}
}.start();
} else {
new Thread(new Runnable() {
@Override
public void run() {
// see explanation above
// userStorage.put("the", "change");
userStorage.mObserver.onChange(false, uri);
}
}).start();
}
listenerCalledLatch.await(3000, TimeUnit.MILLISECONDS);
assertTrue(listenerCalled[0]);
userStorage.unregisterOnTrayPreferenceChangeListener(listener);
return userStorage;
}
use of net.grandcentrix.tray.core.OnTrayPreferenceChangeListener in project tray by grandcentrix.
the class ChangedListenerTest method testApiLevel15OnChange.
public void testApiLevel15OnChange() throws Exception {
final CountDownLatch latch = new CountDownLatch(// first time called in checkChangeListener() second time in this test
2);
final ArrayList<TrayItem> changed = new ArrayList<>();
final OnTrayPreferenceChangeListener listener = new OnTrayPreferenceChangeListener() {
@Override
public void onTrayPreferenceChanged(final Collection<TrayItem> items) {
changed.addAll(items);
latch.countDown();
}
};
final ContentProviderStorage storage = checkChangeListener(true, listener);
storage.put("some", "value");
storage.put("foo", "bar");
new HandlerThread("change") {
@Override
protected void onLooperPrepared() {
super.onLooperPrepared();
storage.mObserver.onChange(false);
}
}.start();
latch.await(3000, TimeUnit.MILLISECONDS);
assertEquals(2, changed.size());
}
use of net.grandcentrix.tray.core.OnTrayPreferenceChangeListener in project tray by grandcentrix.
the class ContentProviderStorage method registerOnTrayPreferenceChangeListener.
/**
* registers a listener for changed data which gets called asynchronously when a change from
* the {@link TrayContentProvider} was detected
* <p>
* sdk version 15 is only partially supported. the listener will provide all data for this
* module and not only the changed ones because {@link ContentObserver#onChange(boolean, Uri)}
* was introduced in sdk version 16
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public synchronized void registerOnTrayPreferenceChangeListener(@NonNull final OnTrayPreferenceChangeListener listener) {
// noinspection ConstantConditions
if (listener == null) {
return;
}
// save a handler associated with the calling looper to call the callback on the same thread
// noinspection ConstantConditions
Handler handler = null;
final Looper looper = Looper.myLooper();
if (looper != null) {
handler = new Handler(looper);
}
//noinspection ConstantConditions
mListeners.put(listener, handler);
final Collection<OnTrayPreferenceChangeListener> listeners = mListeners.keySet();
if (listeners.size() == 1) {
// registering a TrayContentObserver requires a LooperThread
mObserverThread = new HandlerThread("observer") {
@Override
protected void onLooperPrepared() {
super.onLooperPrepared();
mObserver = new TrayContentObserver(new Handler(getLooper()));
// register observer
final Uri observingUri = mTrayUri.builder().setType(getType()).setModule(getModuleName()).build();
mContext.getContentResolver().registerContentObserver(observingUri, true, mObserver);
mRegisteredContentObserver = true;
}
};
mObserverThread.start();
// cannot use Thread.join(); because the Looper of the HandlerThread runs forever until killed
while (true) {
if (mRegisteredContentObserver) {
mRegisteredContentObserver = false;
break;
}
}
}
}
use of net.grandcentrix.tray.core.OnTrayPreferenceChangeListener in project tray by grandcentrix.
the class ChangedListenerTest method testUnregister.
public void testUnregister() throws Exception {
final OnTrayPreferenceChangeListener listener = new OnTrayPreferenceChangeListener() {
@Override
public void onTrayPreferenceChanged(final Collection<TrayItem> items) {
}
};
final ContentProviderStorage userStorage = checkChangeListener(true, listener);
assertEquals(1, userStorage.mListeners.size());
// unregister null should do nothing
userStorage.unregisterOnTrayPreferenceChangeListener(null);
assertEquals(1, userStorage.mListeners.size());
userStorage.unregisterOnTrayPreferenceChangeListener(listener);
assertEquals(0, userStorage.mListeners.size());
assertNull(userStorage.mObserver);
assertNull(userStorage.mObserverThread);
}
Aggregations