public abstract class

SliceViewManagerBase

extends SliceViewManager

 java.lang.Object

androidx.slice.SliceViewManager

↳androidx.slice.SliceViewManagerBase

Gradle dependencies

compile group: 'androidx.slice', name: 'slice-view', version: '1.1.0-alpha02'

  • groupId: androidx.slice
  • artifactId: slice-view
  • version: 1.1.0-alpha02

Artifact androidx.slice:slice-view:1.1.0-alpha02 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.slice:slice-view com.android.support:slices-view

Summary

Fields
protected final ContextmContext

Methods
public abstract voidregisterSliceCallback(Uri uri, java.util.concurrent.Executor executor, SliceViewManager.SliceCallback callback)

Adds a callback to a specific slice uri.

public abstract voidregisterSliceCallback(Uri uri, SliceViewManager.SliceCallback callback)

Adds a callback to a specific slice uri.

public abstract voidunregisterSliceCallback(Uri uri, SliceViewManager.SliceCallback callback)

Removes a callback for a specific slice uri.

from SliceViewManagerbindSlice, bindSlice, getInstance, getSliceDescendants, mapIntentToUri, pinSlice, unpinSlice
from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Fields

protected final Context mContext

Methods

public abstract void registerSliceCallback(Uri uri, SliceViewManager.SliceCallback callback)

Adds a callback to a specific slice uri.

This is a convenience method that performs a few slice actions at once. It will put the slice in a pinned state since there is a callback attached. It will also listen for content changes, when a content change is observed, the android system will bind the new slice and provide it to all registered SliceViewManager.SliceCallbacks.

This will not trigger a bindSlice immediately, it will only perform a bind and pass it to the callback after a change occurs. To avoid race conditions and missing data, callers should call bindSlice immediately after calling registerSliceCallback so that it has the current slice.

Parameters:

uri: The uri of the slice being listened to.
callback: The listener that should receive the callbacks.

See also: SliceProvider.onSlicePinned(Uri)

public abstract void registerSliceCallback(Uri uri, java.util.concurrent.Executor executor, SliceViewManager.SliceCallback callback)

Adds a callback to a specific slice uri.

This is a convenience that performs a few slice actions at once. It will put the slice in a pinned state since there is a callback attached. It will also listen for content changes, when a content change observes, the android system will bind the new slice and provide it to all registered SliceViewManager.SliceCallbacks.

Parameters:

uri: The uri of the slice being listened to.
callback: The listener that should receive the callbacks.

See also: SliceProvider.onSlicePinned(Uri)

public abstract void unregisterSliceCallback(Uri uri, SliceViewManager.SliceCallback callback)

Removes a callback for a specific slice uri.

Removes the app from the pinned state (if there are no other apps/callbacks pinning it) in addition to removing the callback.

Parameters:

uri: The uri of the slice being listened to
callback: The listener that should no longer receive callbacks.

See also: SliceViewManager.registerSliceCallback(Uri, SliceViewManager.SliceCallback)

Source

/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.slice;

import static androidx.slice.widget.SliceLiveData.SUPPORTED_SPECS;

import android.content.ContentProviderClient;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.util.ArrayMap;
import android.util.Pair;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;

import java.util.concurrent.Executor;

/**
 * @hide
 */
@RestrictTo(RestrictTo.Scope.LIBRARY)
@RequiresApi(19)
public abstract class SliceViewManagerBase extends SliceViewManager {
    private final ArrayMap<Pair<Uri, SliceCallback>, SliceListenerImpl> mListenerLookup =
            new ArrayMap<>();
    protected final Context mContext;

    SliceViewManagerBase(Context context) {
        mContext = context;
    }

    @Override
    public void registerSliceCallback(@NonNull Uri uri, @NonNull SliceCallback callback) {
        final Handler h = new Handler(Looper.getMainLooper());
        registerSliceCallback(uri, new Executor() {
            @Override
            public void execute(@NonNull Runnable command) {
                h.post(command);
            }
        }, callback);
    }

    @Override
    public void registerSliceCallback(@NonNull Uri uri, @NonNull Executor executor,
            @NonNull SliceCallback callback) {
        getListener(uri, callback, new SliceListenerImpl(uri, executor, callback)).startListening();
    }

    @Override
    public void unregisterSliceCallback(@NonNull Uri uri, @NonNull SliceCallback callback) {
        synchronized (mListenerLookup) {
            SliceListenerImpl impl = mListenerLookup.remove(new Pair<>(uri, callback));
            if (impl != null) impl.stopListening();
        }
    }


    private SliceListenerImpl getListener(Uri uri, SliceCallback callback,
            SliceListenerImpl listener) {
        Pair<Uri, SliceCallback> key = new Pair<>(uri, callback);
        synchronized (mListenerLookup) {
            SliceListenerImpl oldImpl = mListenerLookup.put(key, listener);
            if (oldImpl != null) {
                oldImpl.stopListening();
            }
        }
        return listener;
    }

    private class SliceListenerImpl {

        Uri mUri;
        final Executor mExecutor;
        final SliceCallback mCallback;
        private boolean mPinned;

        SliceListenerImpl(Uri uri, Executor executor, SliceCallback callback) {
            mUri = uri;
            mExecutor = executor;
            mCallback = callback;
        }

        void startListening() {
            ContentProviderClient provider =
                    mContext.getContentResolver().acquireContentProviderClient(mUri);
            if (provider != null) {
                provider.release();
                mContext.getContentResolver().registerContentObserver(mUri, true, mObserver);
                tryPin();
            }
        }

        void tryPin() {
            if (!mPinned) {
                try {
                    pinSlice(mUri);
                    mPinned = true;
                } catch (SecurityException e) {
                    // No permission currently.
                }
            }
        }

        void stopListening() {
            mContext.getContentResolver().unregisterContentObserver(mObserver);
            if (mPinned) {
                unpinSlice(mUri);
                mPinned = false;
            }
        }

        final Runnable mUpdateSlice = new Runnable() {
            @Override
            public void run() {
                tryPin();
                final Slice s = Slice.bindSlice(mContext, mUri, SUPPORTED_SPECS);
                mExecutor.execute(new Runnable() {
                    @Override
                    public void run() {
                        mCallback.onSliceUpdated(s);
                    }
                });
            }
        };

        private final ContentObserver mObserver = new ContentObserver(
                new Handler(Looper.getMainLooper())) {
            @Override
            @SuppressWarnings("deprecation") /* AsyncTask */
            public void onChange(boolean selfChange) {
                android.os.AsyncTask.execute(mUpdateSlice);
            }
        };
    }
}