Search in sources :

Example 1 with OnTrayPreferenceChangeListener

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;
}
Also used : OnTrayPreferenceChangeListener(net.grandcentrix.tray.core.OnTrayPreferenceChangeListener) CountDownLatch(java.util.concurrent.CountDownLatch) Uri(android.net.Uri) HandlerThread(android.os.HandlerThread) Looper(android.os.Looper) HandlerThread(android.os.HandlerThread) Collection(java.util.Collection)

Example 2 with OnTrayPreferenceChangeListener

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());
}
Also used : TrayItem(net.grandcentrix.tray.core.TrayItem) HandlerThread(android.os.HandlerThread) ArrayList(java.util.ArrayList) Collection(java.util.Collection) OnTrayPreferenceChangeListener(net.grandcentrix.tray.core.OnTrayPreferenceChangeListener) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 3 with OnTrayPreferenceChangeListener

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;
            }
        }
    }
}
Also used : Looper(android.os.Looper) HandlerThread(android.os.HandlerThread) Handler(android.os.Handler) OnTrayPreferenceChangeListener(net.grandcentrix.tray.core.OnTrayPreferenceChangeListener) Uri(android.net.Uri) TargetApi(android.annotation.TargetApi)

Example 4 with OnTrayPreferenceChangeListener

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);
}
Also used : Collection(java.util.Collection) OnTrayPreferenceChangeListener(net.grandcentrix.tray.core.OnTrayPreferenceChangeListener)

Aggregations

OnTrayPreferenceChangeListener (net.grandcentrix.tray.core.OnTrayPreferenceChangeListener)4 HandlerThread (android.os.HandlerThread)3 Collection (java.util.Collection)3 Uri (android.net.Uri)2 Looper (android.os.Looper)2 CountDownLatch (java.util.concurrent.CountDownLatch)2 TargetApi (android.annotation.TargetApi)1 Handler (android.os.Handler)1 ArrayList (java.util.ArrayList)1 TrayItem (net.grandcentrix.tray.core.TrayItem)1