public abstract class

PostMessageServiceConnection

extends java.lang.Object

implements PostMessageBackend

 java.lang.Object

↳androidx.browser.customtabs.PostMessageServiceConnection

Gradle dependencies

compile group: 'androidx.browser', name: 'browser', version: '1.8.0'

  • groupId: androidx.browser
  • artifactId: browser
  • version: 1.8.0

Artifact androidx.browser:browser:1.8.0 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.browser:browser com.android.support:customtabs

Androidx class mapping:

androidx.browser.customtabs.PostMessageServiceConnection android.support.customtabs.PostMessageServiceConnection

Overview

A for Custom Tabs providers to use while connecting to a PostMessageService on the client side. TODO(peconn): Make this not abstract with API change.

Summary

Constructors
publicPostMessageServiceConnection(CustomTabsSessionToken session)

Methods
public booleanbindSessionToPostMessageService(Context appContext)

See PostMessageServiceConnection.bindSessionToPostMessageService(Context, String).

public booleanbindSessionToPostMessageService(Context context, java.lang.String packageName)

Binds the browser side to the client app through the given PostMessageService name.

public voidcleanup(Context context)

Cleans up any dependencies that this handler might have.

public final booleannotifyMessageChannelReady(Bundle extras)

Records that the message channel has been created and notifies the client.

public voidonDisconnectChannel(Context appContext)

public final booleanonNotifyMessageChannelReady(Bundle extras)

public final booleanonPostMessage(java.lang.String message, Bundle extras)

public voidonPostMessageServiceConnected()

Called when the PostMessageService connection is established.

public voidonPostMessageServiceDisconnected()

Called when the connection is lost with the PostMessageService.

public final voidonServiceConnected(ComponentName name, IBinder service)

public final voidonServiceDisconnected(ComponentName name)

public final booleanpostMessage(java.lang.String message, Bundle extras)

Posts a message to the client.

public voidsetPackageName(java.lang.String packageName)

Sets the package name unique to the session.

public voidunbindFromContext(Context context)

Unbinds this service connection from the given context.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructors

public PostMessageServiceConnection(CustomTabsSessionToken session)

Methods

public void setPackageName(java.lang.String packageName)

Sets the package name unique to the session.

Parameters:

packageName: The package name for the client app for the owning session.

public boolean bindSessionToPostMessageService(Context context, java.lang.String packageName)

Binds the browser side to the client app through the given PostMessageService name. After this, this PostMessageServiceConnection can be used for sending postMessage related communication back to the client.

Parameters:

context: A context to bind to the service.
packageName: The name of the package to be bound to.

Returns:

Whether the binding was successful.

public boolean bindSessionToPostMessageService(Context appContext)

See PostMessageServiceConnection.bindSessionToPostMessageService(Context, String). Attempts to bind with the package name set during initialization.

public void unbindFromContext(Context context)

Unbinds this service connection from the given context.

Parameters:

context: The context to be unbound from.

public final void onServiceConnected(ComponentName name, IBinder service)

public final void onServiceDisconnected(ComponentName name)

public final boolean onNotifyMessageChannelReady(Bundle extras)

public final boolean notifyMessageChannelReady(Bundle extras)

Records that the message channel has been created and notifies the client. This method should be called when the browser binds to the client side PostMessageService and also readies a connection to the web frame.

Parameters:

extras: Unused.

Returns:

Whether the notification was sent successfully.

public final boolean onPostMessage(java.lang.String message, Bundle extras)

public final boolean postMessage(java.lang.String message, Bundle extras)

Posts a message to the client. This should be called when a tab controlled by related CustomTabsSession has sent a postMessage. If postMessage() is called from a single thread, then the messages will be posted in the same order.

Parameters:

message: The message sent.
extras: Reserved for future use.

Returns:

Whether the postMessage was sent to the remote successfully.

public void onDisconnectChannel(Context appContext)

public void onPostMessageServiceConnected()

Called when the PostMessageService connection is established.

public void onPostMessageServiceDisconnected()

Called when the connection is lost with the PostMessageService.

public void cleanup(Context context)

Cleans up any dependencies that this handler might have.

Parameters:

context: Context to use for unbinding if necessary.

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.browser.customtabs;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.customtabs.ICustomTabsCallback;
import android.support.customtabs.IPostMessageService;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;

/**
 * A {@link ServiceConnection} for Custom Tabs providers to use while connecting to a
 * {@link PostMessageService} on the client side.
 *
 * TODO(peconn): Make this not abstract with API change.
 */
@SuppressWarnings("HiddenSuperclass")
public abstract class PostMessageServiceConnection
        implements PostMessageBackend, ServiceConnection {
    private static final String TAG = "PostMessageServConn";

    private final Object mLock = new Object();
    private final ICustomTabsCallback mSessionBinder;
    @Nullable private IPostMessageService mService;
    @Nullable private String mPackageName;
    // Indicates that a message channel has been opened. We're ready to post messages once this is
    // true and we've connected to the {@link PostMessageService}.
    private boolean mMessageChannelCreated;

    public PostMessageServiceConnection(@NonNull CustomTabsSessionToken session) {
        IBinder binder = session.getCallbackBinder();
        if (binder == null) {
            throw new IllegalArgumentException("Provided session must have binder.");
        }
        mSessionBinder = ICustomTabsCallback.Stub.asInterface(binder);
    }

    /**
     * Sets the package name unique to the session.
     * @param packageName The package name for the client app for the owning session.
     *
     */
    @RestrictTo(RestrictTo.Scope.LIBRARY)
    public void setPackageName(@NonNull String packageName) {
        mPackageName = packageName;
    }

    /**
     * Binds the browser side to the client app through the given {@link PostMessageService} name.
     * After this, this {@link PostMessageServiceConnection} can be used for sending postMessage
     * related communication back to the client.
     * @param context A context to bind to the service.
     * @param packageName The name of the package to be bound to.
     * @return Whether the binding was successful.
     */
    public boolean bindSessionToPostMessageService(@NonNull Context context,
            @NonNull String packageName) {
        Intent intent = new Intent();
        intent.setClassName(packageName, PostMessageService.class.getName());
        boolean success = context.bindService(intent, this, Context.BIND_AUTO_CREATE);
        if (!success) {
            Log.w(TAG, "Could not bind to PostMessageService in client.");
        }
        return success;
    }

    /**
     * See
     * {@link PostMessageServiceConnection#bindSessionToPostMessageService(Context, String)}.
     * Attempts to bind with the package name set during initialization.
     *
     */
    @RestrictTo(RestrictTo.Scope.LIBRARY)
    public boolean bindSessionToPostMessageService(@NonNull Context appContext) {
        if (mPackageName == null) {
            throw new IllegalStateException("setPackageName must be called before "
                    + "bindSessionToPostMessageService.");
        }
        return bindSessionToPostMessageService(appContext, mPackageName);
    }

    private boolean isBoundToService() {
        return mService != null;
    }

    /**
     * Unbinds this service connection from the given context.
     * @param context The context to be unbound from.
     */
    public void unbindFromContext(@NonNull Context context) {
        if (isBoundToService()) {
            context.unbindService(this);
            mService = null;
        }
    }

    @Override
    public final void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder service) {
        mService = IPostMessageService.Stub.asInterface(service);
        onPostMessageServiceConnected();
    }

    @Override
    public final void onServiceDisconnected(@NonNull ComponentName name) {
        mService = null;
        onPostMessageServiceDisconnected();
    }

    /**
     */
    @RestrictTo(RestrictTo.Scope.LIBRARY)
    @Override
    public final boolean onNotifyMessageChannelReady(@Nullable Bundle extras) {
        return notifyMessageChannelReady(extras);
    }

    /**
     * Records that the message channel has been created and notifies the client. This method
     * should be called when the browser binds to the client side {@link PostMessageService} and
     * also readies a connection to the web frame.
     * @param extras Unused.
     * @return Whether the notification was sent successfully.
     */
    public final boolean notifyMessageChannelReady(@Nullable Bundle extras) {
        mMessageChannelCreated = true;
        return notifyMessageChannelReadyInternal(extras);
    }

    /**
     * Notifies the client that the postMessage channel requested with
     * {@link CustomTabsService#requestPostMessageChannel(
     * CustomTabsSessionToken, android.net.Uri)} is ready. This method should be
     * called when the browser binds to the client side {@link PostMessageService} and also readies
     * a connection to the web frame.
     *
     * @param extras Reserved for future use.
     * @return Whether the notification was sent to the remote successfully.
     */
    @SuppressWarnings("NullAway")  // onMessageChannelReady accepts null extras.
    private boolean notifyMessageChannelReadyInternal(@Nullable Bundle extras) {
        if (mService == null) return false;
        synchronized (mLock) {
            try {
                mService.onMessageChannelReady(mSessionBinder, extras);
            } catch (RemoteException e) {
                return false;
            }
        }
        return true;
    }

    /**
     */
    @RestrictTo(RestrictTo.Scope.LIBRARY)
    @Override
    public final boolean onPostMessage(@NonNull String message, @Nullable Bundle extras) {
        return postMessage(message, extras);
    }

    /**
     * Posts a message to the client. This should be called when a tab controlled by related
     * {@link CustomTabsSession} has sent a postMessage. If postMessage() is called from a single
     * thread, then the messages will be posted in the same order.
     *
     * @param message The message sent.
     * @param extras Reserved for future use.
     * @return Whether the postMessage was sent to the remote successfully.
     */
    @SuppressWarnings("NullAway")  // onPostMessage accepts null extras.
    public final boolean postMessage(@NonNull String message, @Nullable Bundle extras) {
        if (mService == null) return false;
        synchronized (mLock) {
            try {
                mService.onPostMessage(mSessionBinder, message, extras);
            } catch (RemoteException e) {
                return false;
            }
        }
        return true;
    }

    /**
     */
    @RestrictTo(RestrictTo.Scope.LIBRARY)
    @Override
    public void onDisconnectChannel(@NonNull Context appContext) {
        unbindFromContext(appContext);
    }

    /**
     * Called when the {@link PostMessageService} connection is established.
     */
    public void onPostMessageServiceConnected() {
        if (mMessageChannelCreated) notifyMessageChannelReadyInternal(null);
    }

    /**
     * Called when the connection is lost with the {@link PostMessageService}.
     */
    public void onPostMessageServiceDisconnected() {}

    /**
     * Cleans up any dependencies that this handler might have.
     * @param context Context to use for unbinding if necessary.
     *
     */
    @RestrictTo(RestrictTo.Scope.LIBRARY)
    public void cleanup(@NonNull Context context) {
        if (isBoundToService()) unbindFromContext(context);
    }
}