mirror of https://github.com/NekoX-Dev/NekoX.git
Make custom tabs follow app theme
This commit is contained in:
parent
2699e46c96
commit
b1770331f8
|
@ -51,6 +51,7 @@ repositories {
|
|||
|
||||
dependencies {
|
||||
|
||||
implementation "androidx.browser:browser:1.3.0"
|
||||
implementation 'androidx.core:core-ktx:1.5.0-alpha05'
|
||||
implementation 'androidx.palette:palette-ktx:1.0.0'
|
||||
implementation 'androidx.viewpager:viewpager:1.0.0'
|
||||
|
|
|
@ -19,6 +19,13 @@ import android.net.Uri;
|
|||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.browser.customtabs.CustomTabColorSchemeParams;
|
||||
import androidx.browser.customtabs.CustomTabsCallback;
|
||||
import androidx.browser.customtabs.CustomTabsClient;
|
||||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
import androidx.browser.customtabs.CustomTabsServiceConnection;
|
||||
import androidx.browser.customtabs.CustomTabsSession;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ApplicationLoader;
|
||||
import org.telegram.messenger.BuildVars;
|
||||
|
@ -30,11 +37,6 @@ import org.telegram.messenger.R;
|
|||
import org.telegram.messenger.ShareBroadcastReceiver;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.messenger.support.customtabs.CustomTabsCallback;
|
||||
import org.telegram.messenger.support.customtabs.CustomTabsClient;
|
||||
import org.telegram.messenger.support.customtabs.CustomTabsIntent;
|
||||
import org.telegram.messenger.support.customtabs.CustomTabsServiceConnection;
|
||||
import org.telegram.messenger.support.customtabs.CustomTabsSession;
|
||||
import org.telegram.messenger.support.customtabsclient.shared.CustomTabsHelper;
|
||||
import org.telegram.messenger.support.customtabsclient.shared.ServiceConnection;
|
||||
import org.telegram.messenger.support.customtabsclient.shared.ServiceConnectionCallback;
|
||||
|
@ -295,11 +297,21 @@ public class Browser {
|
|||
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(getSession());
|
||||
builder.addMenuItem(LocaleController.getString("CopyLink", R.string.CopyLink), copy);
|
||||
|
||||
builder.setToolbarColor(Theme.getColor(Theme.key_actionBarBrowser));
|
||||
boolean dark = false;
|
||||
if (Theme.getActiveTheme().isDark()) {
|
||||
dark = true;
|
||||
} else if (AndroidUtilities.computePerceivedBrightness(Theme.getColor(Theme.key_windowBackgroundWhite)) < 0.721f) {
|
||||
dark = true;
|
||||
}
|
||||
builder.setColorScheme(dark ? CustomTabsIntent.COLOR_SCHEME_DARK : CustomTabsIntent.COLOR_SCHEME_LIGHT);
|
||||
CustomTabColorSchemeParams params = new CustomTabColorSchemeParams.Builder()
|
||||
.setToolbarColor(Theme.getColor(Theme.key_actionBarBrowser))
|
||||
.build();
|
||||
builder.setDefaultColorSchemeParams(params);
|
||||
builder.setShowTitle(true);
|
||||
builder.setActionButton(BitmapFactory.decodeResource(context.getResources(), R.drawable.abc_ic_menu_share_mtrl_alpha), LocaleController.getString("ShareFile", R.string.ShareFile), PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 0, share, 0), true);
|
||||
CustomTabsIntent intent = builder.build();
|
||||
intent.setUseNewTask();
|
||||
intent.intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.launchUrl(context, uri);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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 org.telegram.messenger.support.customtabs;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* A callback class for custom tabs client to get messages regarding events in their custom tabs.
|
||||
*/
|
||||
public class CustomTabsCallback {
|
||||
/**
|
||||
* Sent when the tab has started loading a page.
|
||||
*/
|
||||
public static final int NAVIGATION_STARTED = 1;
|
||||
|
||||
/**
|
||||
* Sent when the tab has finished loading a page.
|
||||
*/
|
||||
public static final int NAVIGATION_FINISHED = 2;
|
||||
|
||||
/**
|
||||
* Sent when the tab couldn't finish loading due to a failure.
|
||||
*/
|
||||
public static final int NAVIGATION_FAILED = 3;
|
||||
|
||||
/**
|
||||
* Sent when loading was aborted by a user action before it finishes like clicking on a link
|
||||
* or refreshing the page.
|
||||
*/
|
||||
public static final int NAVIGATION_ABORTED = 4;
|
||||
|
||||
/**
|
||||
* Sent when the tab becomes visible.
|
||||
*/
|
||||
public static final int TAB_SHOWN = 5;
|
||||
|
||||
/**
|
||||
* Sent when the tab becomes hidden.
|
||||
*/
|
||||
public static final int TAB_HIDDEN = 6;
|
||||
|
||||
/**
|
||||
* To be called when a navigation event happens.
|
||||
*
|
||||
* @param navigationEvent The code corresponding to the navigation event.
|
||||
* @param extras Reserved for future use.
|
||||
*/
|
||||
public void onNavigationEvent(int navigationEvent, Bundle extras) {}
|
||||
|
||||
/**
|
||||
* Unsupported callbacks that may be provided by the implementation.
|
||||
*
|
||||
* <p>
|
||||
* <strong>Note:</strong>Clients should <strong>never</strong> rely on this callback to be
|
||||
* called and/or to have a defined behavior, as it is entirely implementation-defined and not
|
||||
* supported.
|
||||
*
|
||||
* <p> This can be used by implementations to add extra callbacks, for testing or experimental
|
||||
* purposes.
|
||||
*
|
||||
* @param callbackName Name of the extra callback.
|
||||
* @param args Arguments for the calback
|
||||
*/
|
||||
public void extraCallback(String callbackName, Bundle args) {}
|
||||
|
||||
/**
|
||||
* Called when {@link CustomTabsSession} has requested a postMessage channel through
|
||||
* {@link CustomTabsService#requestPostMessageChannel(
|
||||
* CustomTabsSessionToken, android.net.Uri)} and the channel
|
||||
* is ready for sending and receiving messages on both ends.
|
||||
*
|
||||
* @param extras Reserved for future use.
|
||||
*/
|
||||
public void onMessageChannelReady(Bundle extras) {}
|
||||
|
||||
/**
|
||||
* Called when a tab controlled by this {@link CustomTabsSession} has sent a postMessage.
|
||||
* If postMessage() is called from a single thread, then the messages will be posted in the
|
||||
* same order. When received on the client side, it is the client's responsibility to preserve
|
||||
* the ordering further.
|
||||
*
|
||||
* @param message The message sent.
|
||||
* @param extras Reserved for future use.
|
||||
*/
|
||||
public void onPostMessage(String message, Bundle extras) {}
|
||||
}
|
|
@ -1,245 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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 org.telegram.messenger.support.customtabs;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CustomTabsClient {
|
||||
private final ICustomTabsService mService;
|
||||
private final ComponentName mServiceComponentName;
|
||||
|
||||
CustomTabsClient(ICustomTabsService service, ComponentName componentName) {
|
||||
mService = service;
|
||||
mServiceComponentName = componentName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind to a {@link CustomTabsService} using the given package name and
|
||||
* {@link ServiceConnection}.
|
||||
* @param context {@link Context} to use while calling
|
||||
* {@link Context#bindService(Intent, ServiceConnection, int)}
|
||||
* @param packageName Package name to set on the {@link Intent} for binding.
|
||||
* @param connection {@link CustomTabsServiceConnection} to use when binding. This will
|
||||
* return a {@link CustomTabsClient} on
|
||||
* {@link CustomTabsServiceConnection
|
||||
* #onCustomTabsServiceConnected(ComponentName, CustomTabsClient)}
|
||||
* @return Whether the binding was successful.
|
||||
*/
|
||||
public static boolean bindCustomTabsService(Context context,
|
||||
String packageName, CustomTabsServiceConnection connection) {
|
||||
Intent intent = new Intent(CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION);
|
||||
if (!TextUtils.isEmpty(packageName)) intent.setPackage(packageName);
|
||||
return context.bindService(intent, connection,
|
||||
Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred package to use for Custom Tabs, preferring the default VIEW handler.
|
||||
*
|
||||
* @see #getPackageName(Context, List<String>, boolean)
|
||||
*/
|
||||
public static String getPackageName(Context context, @Nullable List<String> packages) {
|
||||
return getPackageName(context, packages, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred package to use for Custom Tabs.
|
||||
*
|
||||
* The preferred package name is the default VIEW intent handler as long as it supports Custom
|
||||
* Tabs. To modify this preferred behavior, set <code>ignoreDefault</code> to true and give a
|
||||
* non empty list of package names in <code>packages</code>.
|
||||
*
|
||||
* @param context {@link Context} to use for querying the packages.
|
||||
* @param packages Ordered list of packages to test for Custom Tabs support, in
|
||||
* decreasing order of priority.
|
||||
* @param ignoreDefault If set, the default VIEW handler won't get priority over other browsers.
|
||||
* @return The preferred package name for handling Custom Tabs, or <code>null</code>.
|
||||
*/
|
||||
public static String getPackageName(
|
||||
Context context, @Nullable List<String> packages, boolean ignoreDefault) {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
|
||||
List<String> packageNames = packages == null ? new ArrayList<String>() : packages;
|
||||
Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"));
|
||||
|
||||
if (!ignoreDefault) {
|
||||
ResolveInfo defaultViewHandlerInfo = pm.resolveActivity(activityIntent, 0);
|
||||
if (defaultViewHandlerInfo != null) {
|
||||
String packageName = defaultViewHandlerInfo.activityInfo.packageName;
|
||||
packageNames = new ArrayList<>(packageNames.size() + 1);
|
||||
packageNames.add(packageName);
|
||||
if (packages != null) packageNames.addAll(packages);
|
||||
}
|
||||
}
|
||||
|
||||
Intent serviceIntent = new Intent(CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION);
|
||||
for (String packageName : packageNames) {
|
||||
serviceIntent.setPackage(packageName);
|
||||
if (pm.resolveService(serviceIntent, 0) != null) return packageName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the Custom Tabs warmup service, and initializes the browser.
|
||||
*
|
||||
* This convenience method connects to the service, and immediately warms up the Custom Tabs
|
||||
* implementation. Since service connection is asynchronous, the return code is not the return
|
||||
* code of warmup.
|
||||
* This call is optional, and clients are encouraged to connect to the service, call
|
||||
* <code>warmup()</code> and create a session. In this case, calling this method is not
|
||||
* necessary.
|
||||
*
|
||||
* @param context {@link Context} to use to connect to the remote service.
|
||||
* @param packageName Package name of the target implementation.
|
||||
* @return Whether the binding was successful.
|
||||
*/
|
||||
public static boolean connectAndInitialize(Context context, String packageName) {
|
||||
if (packageName == null) return false;
|
||||
final Context applicationContext = context.getApplicationContext();
|
||||
CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
|
||||
@Override
|
||||
public final void onCustomTabsServiceConnected(
|
||||
ComponentName name, CustomTabsClient client) {
|
||||
client.warmup(0);
|
||||
// Unbinding immediately makes the target process "Empty", provided that it is
|
||||
// not used by anyone else, and doesn't contain any Activity. This makes it
|
||||
// likely to get killed, but is preferable to keeping the connection around.
|
||||
applicationContext.unbindService(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onServiceDisconnected(ComponentName componentName) { }
|
||||
};
|
||||
try {
|
||||
return bindCustomTabsService(applicationContext, packageName, connection);
|
||||
} catch (SecurityException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Warm up the browser process.
|
||||
*
|
||||
* Allows the browser application to pre-initialize itself in the background. Significantly
|
||||
* speeds up URL opening in the browser. This is asynchronous and can be called several times.
|
||||
*
|
||||
* @param flags Reserved for future use.
|
||||
* @return Whether the warmup was successful.
|
||||
*/
|
||||
public boolean warmup(long flags) {
|
||||
try {
|
||||
return mService.warmup(flags);
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new session through an ICustomTabsService with the optional callback. This session
|
||||
* can be used to associate any related communication through the service with an intent and
|
||||
* then later with a Custom Tab. The client can then send later service calls or intents to
|
||||
* through same session-intent-Custom Tab association.
|
||||
* @param callback The callback through which the client will receive updates about the created
|
||||
* session. Can be null. All the callbacks will be received on the UI thread.
|
||||
* @return The session object that was created as a result of the transaction. The client can
|
||||
* use this to relay session specific calls.
|
||||
* Null on error.
|
||||
*/
|
||||
public CustomTabsSession newSession(final CustomTabsCallback callback) {
|
||||
ICustomTabsCallback.Stub wrapper = new ICustomTabsCallback.Stub() {
|
||||
private Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
@Override
|
||||
public void onNavigationEvent(final int navigationEvent, final Bundle extras) {
|
||||
if (callback == null) return;
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onNavigationEvent(navigationEvent, extras);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void extraCallback(final String callbackName, final Bundle args)
|
||||
throws RemoteException {
|
||||
if (callback == null) return;
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.extraCallback(callbackName, args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageChannelReady(final Bundle extras)
|
||||
throws RemoteException {
|
||||
if (callback == null) return;
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onMessageChannelReady(extras);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostMessage(final String message, final Bundle extras)
|
||||
throws RemoteException {
|
||||
if (callback == null) return;
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onPostMessage(message, extras);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
if (!mService.newSession(wrapper)) return null;
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
return new CustomTabsSession(mService, wrapper, mServiceComponentName);
|
||||
}
|
||||
|
||||
public Bundle extraCommand(String commandName, Bundle args) {
|
||||
try {
|
||||
return mService.extraCommand(commandName, args);
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,566 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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 org.telegram.messenger.support.customtabs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.AnimRes;
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.ActivityOptionsCompat;
|
||||
import androidx.core.app.BundleCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Class holding the {@link Intent} and start bundle for a Custom Tabs Activity.
|
||||
*
|
||||
* <p>
|
||||
* <strong>Note:</strong> The constants below are public for the browser implementation's benefit.
|
||||
* You are strongly encouraged to use {@link CustomTabsIntent.Builder}.</p>
|
||||
*/
|
||||
public final class CustomTabsIntent {
|
||||
|
||||
/**
|
||||
* Indicates that the user explicitly opted out of Custom Tabs in the calling application.
|
||||
* <p>
|
||||
* If an application provides a mechanism for users to opt out of Custom Tabs, this extra should
|
||||
* be provided with {@link Intent#FLAG_ACTIVITY_NEW_TASK} to ensure the browser does not attempt
|
||||
* to trigger any Custom Tab-like experiences as a result of the VIEW intent.
|
||||
* <p>
|
||||
* If this extra is present with {@link Intent#FLAG_ACTIVITY_NEW_TASK}, all Custom Tabs
|
||||
* customizations will be ignored.
|
||||
*/
|
||||
private static final String EXTRA_USER_OPT_OUT_FROM_CUSTOM_TABS =
|
||||
"android.support.customtabs.extra.user_opt_out";
|
||||
|
||||
/**
|
||||
* Extra used to match the session. This has to be included in the intent to open in
|
||||
* a custom tab. This is the same IBinder that gets passed to ICustomTabsService#newSession.
|
||||
* Null if there is no need to match any service side sessions with the intent.
|
||||
*/
|
||||
public static final String EXTRA_SESSION = "android.support.customtabs.extra.SESSION";
|
||||
|
||||
/**
|
||||
* Extra that changes the background color for the toolbar. colorRes is an int that specifies a
|
||||
* {@link Color}, not a resource id.
|
||||
*/
|
||||
public static final String EXTRA_TOOLBAR_COLOR =
|
||||
"android.support.customtabs.extra.TOOLBAR_COLOR";
|
||||
|
||||
/**
|
||||
* Boolean extra that enables the url bar to hide as the user scrolls down the page
|
||||
*/
|
||||
public static final String EXTRA_ENABLE_URLBAR_HIDING =
|
||||
"android.support.customtabs.extra.ENABLE_URLBAR_HIDING";
|
||||
|
||||
/**
|
||||
* Extra bitmap that specifies the icon of the back button on the toolbar. If the client chooses
|
||||
* not to customize it, a default close button will be used.
|
||||
*/
|
||||
public static final String EXTRA_CLOSE_BUTTON_ICON =
|
||||
"android.support.customtabs.extra.CLOSE_BUTTON_ICON";
|
||||
|
||||
/**
|
||||
* Extra (int) that specifies state for showing the page title. Default is {@link #NO_TITLE}.
|
||||
*/
|
||||
public static final String EXTRA_TITLE_VISIBILITY_STATE =
|
||||
"android.support.customtabs.extra.TITLE_VISIBILITY";
|
||||
|
||||
/**
|
||||
* Don't show any title. Shows only the domain.
|
||||
*/
|
||||
public static final int NO_TITLE = 0;
|
||||
|
||||
/**
|
||||
* Shows the page title and the domain.
|
||||
*/
|
||||
public static final int SHOW_PAGE_TITLE = 1;
|
||||
|
||||
/**
|
||||
* Bundle used for adding a custom action button to the custom tab toolbar. The client should
|
||||
* provide a description, an icon {@link Bitmap} and a {@link PendingIntent} for the button.
|
||||
* All three keys must be present.
|
||||
*/
|
||||
public static final String EXTRA_ACTION_BUTTON_BUNDLE =
|
||||
"android.support.customtabs.extra.ACTION_BUTTON_BUNDLE";
|
||||
|
||||
/**
|
||||
* List<Bundle> used for adding items to the top and bottom toolbars. The client should
|
||||
* provide an ID, a description, an icon {@link Bitmap} for each item. They may also provide a
|
||||
* {@link PendingIntent} if the item is a button.
|
||||
*/
|
||||
public static final String EXTRA_TOOLBAR_ITEMS =
|
||||
"android.support.customtabs.extra.TOOLBAR_ITEMS";
|
||||
|
||||
/**
|
||||
* Extra that changes the background color for the secondary toolbar. The value should be an
|
||||
* int that specifies a {@link Color}, not a resource id.
|
||||
*/
|
||||
public static final String EXTRA_SECONDARY_TOOLBAR_COLOR =
|
||||
"android.support.customtabs.extra.SECONDARY_TOOLBAR_COLOR";
|
||||
|
||||
/**
|
||||
* Key that specifies the {@link Bitmap} to be used as the image source for the action button.
|
||||
* The icon should't be more than 24dp in height (No padding needed. The button itself will be
|
||||
* 48dp in height) and have a width/height ratio of less than 2.
|
||||
*/
|
||||
public static final String KEY_ICON = "android.support.customtabs.customaction.ICON";
|
||||
|
||||
/**
|
||||
* Key that specifies the content description for the custom action button.
|
||||
*/
|
||||
public static final String KEY_DESCRIPTION =
|
||||
"android.support.customtabs.customaction.DESCRIPTION";
|
||||
|
||||
/**
|
||||
* Key that specifies the PendingIntent to launch when the action button or menu item was
|
||||
* clicked. The custom tab will be calling {@link PendingIntent#send()} on clicks after adding
|
||||
* the url as data. The client app can call {@link Intent#getDataString()} to get the url.
|
||||
*/
|
||||
public static final String KEY_PENDING_INTENT =
|
||||
"android.support.customtabs.customaction.PENDING_INTENT";
|
||||
|
||||
/**
|
||||
* Extra boolean that specifies whether the custom action button should be tinted. Default is
|
||||
* false and the action button will not be tinted.
|
||||
*/
|
||||
public static final String EXTRA_TINT_ACTION_BUTTON =
|
||||
"android.support.customtabs.extra.TINT_ACTION_BUTTON";
|
||||
|
||||
/**
|
||||
* Use an {@code ArrayList<Bundle>} for specifying menu related params. There should be a
|
||||
* separate {@link Bundle} for each custom menu item.
|
||||
*/
|
||||
public static final String EXTRA_MENU_ITEMS = "android.support.customtabs.extra.MENU_ITEMS";
|
||||
|
||||
/**
|
||||
* Key for specifying the title of a menu item.
|
||||
*/
|
||||
public static final String KEY_MENU_ITEM_TITLE =
|
||||
"android.support.customtabs.customaction.MENU_ITEM_TITLE";
|
||||
|
||||
/**
|
||||
* Bundle constructed out of {@link ActivityOptionsCompat} that will be running when the
|
||||
* {@link Activity} that holds the custom tab gets finished. A similar ActivityOptions
|
||||
* for creation should be constructed and given to the startActivity() call that
|
||||
* launches the custom tab.
|
||||
*/
|
||||
public static final String EXTRA_EXIT_ANIMATION_BUNDLE =
|
||||
"android.support.customtabs.extra.EXIT_ANIMATION_BUNDLE";
|
||||
|
||||
/**
|
||||
* Boolean extra that specifies whether a default share button will be shown in the menu.
|
||||
*/
|
||||
public static final String EXTRA_DEFAULT_SHARE_MENU_ITEM =
|
||||
"android.support.customtabs.extra.SHARE_MENU_ITEM";
|
||||
|
||||
/**
|
||||
* Extra that specifies the {@link RemoteViews} showing on the secondary toolbar. If this extra
|
||||
* is set, the other secondary toolbar configurations will be overriden. The height of the
|
||||
* {@link RemoteViews} should not exceed 56dp.
|
||||
* @see CustomTabsIntent.Builder#setSecondaryToolbarViews(RemoteViews, int[], PendingIntent).
|
||||
*/
|
||||
public static final String EXTRA_REMOTEVIEWS =
|
||||
"android.support.customtabs.extra.EXTRA_REMOTEVIEWS";
|
||||
|
||||
/**
|
||||
* Extra that specifies an array of {@link View} ids. When these {@link View}s are clicked, a
|
||||
* {@link PendingIntent} will be sent, carrying the current url of the custom tab as data.
|
||||
* <p>
|
||||
* Note that Custom Tabs will override the default onClick behavior of the listed {@link View}s.
|
||||
* If you do not care about the current url, you can safely ignore this extra and use
|
||||
* {@link RemoteViews#setOnClickPendingIntent(int, PendingIntent)} instead.
|
||||
* @see CustomTabsIntent.Builder#setSecondaryToolbarViews(RemoteViews, int[], PendingIntent).
|
||||
*/
|
||||
public static final String EXTRA_REMOTEVIEWS_VIEW_IDS =
|
||||
"android.support.customtabs.extra.EXTRA_REMOTEVIEWS_VIEW_IDS";
|
||||
|
||||
/**
|
||||
* Extra that specifies the {@link PendingIntent} to be sent when the user clicks on the
|
||||
* {@link View}s that is listed by {@link #EXTRA_REMOTEVIEWS_VIEW_IDS}.
|
||||
* <p>
|
||||
* Note when this {@link PendingIntent} is triggered, it will have the current url as data
|
||||
* field, also the id of the clicked {@link View}, specified by
|
||||
* {@link #EXTRA_REMOTEVIEWS_CLICKED_ID}.
|
||||
* @see CustomTabsIntent.Builder#setSecondaryToolbarViews(RemoteViews, int[], PendingIntent).
|
||||
*/
|
||||
public static final String EXTRA_REMOTEVIEWS_PENDINGINTENT =
|
||||
"android.support.customtabs.extra.EXTRA_REMOTEVIEWS_PENDINGINTENT";
|
||||
|
||||
/**
|
||||
* Extra that specifies which {@link View} has been clicked. This extra will be put to the
|
||||
* {@link PendingIntent} sent from Custom Tabs when a view in the {@link RemoteViews} is clicked
|
||||
* @see CustomTabsIntent.Builder#setSecondaryToolbarViews(RemoteViews, int[], PendingIntent).
|
||||
*/
|
||||
public static final String EXTRA_REMOTEVIEWS_CLICKED_ID =
|
||||
"android.support.customtabs.extra.EXTRA_REMOTEVIEWS_CLICKED_ID";
|
||||
|
||||
/**
|
||||
* Extra that specifies whether Instant Apps is enabled.
|
||||
*/
|
||||
public static final String EXTRA_ENABLE_INSTANT_APPS =
|
||||
"android.support.customtabs.extra.EXTRA_ENABLE_INSTANT_APPS";
|
||||
|
||||
/**
|
||||
* Key that specifies the unique ID for an action button. To make a button to show on the
|
||||
* toolbar, use {@link #TOOLBAR_ACTION_BUTTON_ID} as its ID.
|
||||
*/
|
||||
public static final String KEY_ID = "android.support.customtabs.customaction.ID";
|
||||
|
||||
/**
|
||||
* The ID allocated to the custom action button that is shown on the toolbar.
|
||||
*/
|
||||
public static final int TOOLBAR_ACTION_BUTTON_ID = 0;
|
||||
|
||||
/**
|
||||
* The maximum allowed number of toolbar items.
|
||||
*/
|
||||
private static final int MAX_TOOLBAR_ITEMS = 5;
|
||||
|
||||
/**
|
||||
* An {@link Intent} used to start the Custom Tabs Activity.
|
||||
*/
|
||||
@NonNull public final Intent intent;
|
||||
|
||||
/**
|
||||
* A {@link Bundle} containing the start animation for the Custom Tabs Activity.
|
||||
*/
|
||||
@Nullable public final Bundle startAnimationBundle;
|
||||
|
||||
/**
|
||||
* Convenience method to launch a Custom Tabs Activity.
|
||||
* @param context The source Context.
|
||||
* @param url The URL to load in the Custom Tab.
|
||||
*/
|
||||
public void launchUrl(Context context, Uri url) {
|
||||
intent.setData(url);
|
||||
ContextCompat.startActivity(context, intent, startAnimationBundle);
|
||||
}
|
||||
|
||||
private CustomTabsIntent(Intent intent, Bundle startAnimationBundle) {
|
||||
this.intent = intent;
|
||||
this.startAnimationBundle = startAnimationBundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder class for {@link CustomTabsIntent} objects.
|
||||
*/
|
||||
public static final class Builder {
|
||||
private final Intent mIntent = new Intent(Intent.ACTION_VIEW);
|
||||
private ArrayList<Bundle> mMenuItems = null;
|
||||
private Bundle mStartAnimationBundle = null;
|
||||
private ArrayList<Bundle> mActionButtons = null;
|
||||
private boolean mInstantAppsEnabled = true;
|
||||
|
||||
/**
|
||||
* Creates a {@link CustomTabsIntent.Builder} object associated with no
|
||||
* {@link CustomTabsSession}.
|
||||
*/
|
||||
public Builder() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link CustomTabsIntent.Builder} object associated with a given
|
||||
* {@link CustomTabsSession}.
|
||||
*
|
||||
* Guarantees that the {@link Intent} will be sent to the same component as the one the
|
||||
* session is associated with.
|
||||
*
|
||||
* @param session The session to associate this Builder with.
|
||||
*/
|
||||
public Builder(@Nullable CustomTabsSession session) {
|
||||
if (session != null) mIntent.setPackage(session.getComponentName().getPackageName());
|
||||
Bundle bundle = new Bundle();
|
||||
BundleCompat.putBinder(
|
||||
bundle, EXTRA_SESSION, session == null ? null : session.getBinder());
|
||||
mIntent.putExtras(bundle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the toolbar color.
|
||||
*
|
||||
* @param color {@link Color}
|
||||
*/
|
||||
public Builder setToolbarColor(@ColorInt int color) {
|
||||
mIntent.putExtra(EXTRA_TOOLBAR_COLOR, color);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the url bar to hide as the user scrolls down on the page.
|
||||
*/
|
||||
public Builder enableUrlBarHiding() {
|
||||
mIntent.putExtra(EXTRA_ENABLE_URLBAR_HIDING, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Close button icon for the custom tab.
|
||||
*
|
||||
* @param icon The icon {@link Bitmap}
|
||||
*/
|
||||
public Builder setCloseButtonIcon(@NonNull Bitmap icon) {
|
||||
mIntent.putExtra(EXTRA_CLOSE_BUTTON_ICON, icon);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the title should be shown in the custom tab.
|
||||
*
|
||||
* @param showTitle Whether the title should be shown.
|
||||
*/
|
||||
public Builder setShowTitle(boolean showTitle) {
|
||||
mIntent.putExtra(EXTRA_TITLE_VISIBILITY_STATE,
|
||||
showTitle ? SHOW_PAGE_TITLE : NO_TITLE);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a menu item.
|
||||
*
|
||||
* @param label Menu label.
|
||||
* @param pendingIntent Pending intent delivered when the menu item is clicked.
|
||||
*/
|
||||
public Builder addMenuItem(@NonNull String label, @NonNull PendingIntent pendingIntent) {
|
||||
if (mMenuItems == null) mMenuItems = new ArrayList<>();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(KEY_MENU_ITEM_TITLE, label);
|
||||
bundle.putParcelable(KEY_PENDING_INTENT, pendingIntent);
|
||||
mMenuItems.add(bundle);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a default share item to the menu.
|
||||
*/
|
||||
public Builder addDefaultShareMenuItem() {
|
||||
mIntent.putExtra(EXTRA_DEFAULT_SHARE_MENU_ITEM, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the action button that is displayed in the Toolbar.
|
||||
* <p>
|
||||
* This is equivalent to calling
|
||||
* {@link CustomTabsIntent.Builder#addToolbarItem(int, Bitmap, String, PendingIntent)}
|
||||
* with {@link #TOOLBAR_ACTION_BUTTON_ID} as id.
|
||||
*
|
||||
* @param icon The icon.
|
||||
* @param description The description for the button. To be used for accessibility.
|
||||
* @param pendingIntent pending intent delivered when the button is clicked.
|
||||
* @param shouldTint Whether the action button should be tinted.
|
||||
*
|
||||
* @see CustomTabsIntent.Builder#addToolbarItem(int, Bitmap, String, PendingIntent)
|
||||
*/
|
||||
public Builder setActionButton(@NonNull Bitmap icon, @NonNull String description,
|
||||
@NonNull PendingIntent pendingIntent, boolean shouldTint) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt(KEY_ID, TOOLBAR_ACTION_BUTTON_ID);
|
||||
bundle.putParcelable(KEY_ICON, icon);
|
||||
bundle.putString(KEY_DESCRIPTION, description);
|
||||
bundle.putParcelable(KEY_PENDING_INTENT, pendingIntent);
|
||||
mIntent.putExtra(EXTRA_ACTION_BUTTON_BUNDLE, bundle);
|
||||
mIntent.putExtra(EXTRA_TINT_ACTION_BUTTON, shouldTint);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the action button that is displayed in the Toolbar with default tinting behavior.
|
||||
*
|
||||
* @see CustomTabsIntent.Builder#setActionButton(
|
||||
* Bitmap, String, PendingIntent, boolean)
|
||||
*/
|
||||
public Builder setActionButton(@NonNull Bitmap icon, @NonNull String description,
|
||||
@NonNull PendingIntent pendingIntent) {
|
||||
return setActionButton(icon, description, pendingIntent, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an action button to the custom tab. Multiple buttons can be added via this method.
|
||||
* If the given id equals {@link #TOOLBAR_ACTION_BUTTON_ID}, the button will be placed on
|
||||
* the toolbar; if the bitmap is too wide, it will be put to the bottom bar instead. If
|
||||
* the id is not {@link #TOOLBAR_ACTION_BUTTON_ID}, it will be directly put on secondary
|
||||
* toolbar. The maximum number of allowed toolbar items in a single intent is
|
||||
* {@link CustomTabsIntent#getMaxToolbarItems()}. Throws an
|
||||
* {@link IllegalStateException} when that number is exceeded per intent.
|
||||
*
|
||||
* @param id The unique id of the action button. This should be non-negative.
|
||||
* @param icon The icon.
|
||||
* @param description The description for the button. To be used for accessibility.
|
||||
* @param pendingIntent The pending intent delivered when the button is clicked.
|
||||
*
|
||||
* @see CustomTabsIntent#getMaxToolbarItems()
|
||||
* @deprecated Use
|
||||
* CustomTabsIntent.Builder#setSecondaryToolbarViews(RemoteViews, int[], PendingIntent).
|
||||
*/
|
||||
@Deprecated
|
||||
public Builder addToolbarItem(int id, @NonNull Bitmap icon, @NonNull String description,
|
||||
PendingIntent pendingIntent) throws IllegalStateException {
|
||||
if (mActionButtons == null) {
|
||||
mActionButtons = new ArrayList<>();
|
||||
}
|
||||
if (mActionButtons.size() >= MAX_TOOLBAR_ITEMS) {
|
||||
throw new IllegalStateException(
|
||||
"Exceeded maximum toolbar item count of " + MAX_TOOLBAR_ITEMS);
|
||||
}
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt(KEY_ID, id);
|
||||
bundle.putParcelable(KEY_ICON, icon);
|
||||
bundle.putString(KEY_DESCRIPTION, description);
|
||||
bundle.putParcelable(KEY_PENDING_INTENT, pendingIntent);
|
||||
mActionButtons.add(bundle);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of the secondary toolbar.
|
||||
* @param color The color for the secondary toolbar.
|
||||
*/
|
||||
public Builder setSecondaryToolbarColor(@ColorInt int color) {
|
||||
mIntent.putExtra(EXTRA_SECONDARY_TOOLBAR_COLOR, color);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the remote views displayed in the secondary toolbar in a custom tab.
|
||||
*
|
||||
* @param remoteViews The {@link RemoteViews} that will be shown on the secondary toolbar.
|
||||
* @param clickableIDs The IDs of clickable views. The onClick event of these views will be
|
||||
* handled by custom tabs.
|
||||
* @param pendingIntent The {@link PendingIntent} that will be sent when the user clicks on
|
||||
* one of the {@link View}s in clickableIDs. When the
|
||||
* {@link PendingIntent} is sent, it will have the current URL as its
|
||||
* intent data.
|
||||
* @see CustomTabsIntent#EXTRA_REMOTEVIEWS
|
||||
* @see CustomTabsIntent#EXTRA_REMOTEVIEWS_VIEW_IDS
|
||||
* @see CustomTabsIntent#EXTRA_REMOTEVIEWS_PENDINGINTENT
|
||||
* @see CustomTabsIntent#EXTRA_REMOTEVIEWS_CLICKED_ID
|
||||
*/
|
||||
public Builder setSecondaryToolbarViews(@NonNull RemoteViews remoteViews,
|
||||
@Nullable int[] clickableIDs, @Nullable PendingIntent pendingIntent) {
|
||||
mIntent.putExtra(EXTRA_REMOTEVIEWS, remoteViews);
|
||||
mIntent.putExtra(EXTRA_REMOTEVIEWS_VIEW_IDS, clickableIDs);
|
||||
mIntent.putExtra(EXTRA_REMOTEVIEWS_PENDINGINTENT, pendingIntent);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether Instant Apps is enabled for this Custom Tab.
|
||||
|
||||
* @param enabled Whether Instant Apps should be enabled.
|
||||
*/
|
||||
public Builder setInstantAppsEnabled(boolean enabled) {
|
||||
mInstantAppsEnabled = enabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the start animations.
|
||||
*
|
||||
* @param context Application context.
|
||||
* @param enterResId Resource ID of the "enter" animation for the browser.
|
||||
* @param exitResId Resource ID of the "exit" animation for the application.
|
||||
*/
|
||||
public Builder setStartAnimations(
|
||||
@NonNull Context context, @AnimRes int enterResId, @AnimRes int exitResId) {
|
||||
mStartAnimationBundle = ActivityOptionsCompat.makeCustomAnimation(
|
||||
context, enterResId, exitResId).toBundle();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the exit animations.
|
||||
*
|
||||
* @param context Application context.
|
||||
* @param enterResId Resource ID of the "enter" animation for the application.
|
||||
* @param exitResId Resource ID of the "exit" animation for the browser.
|
||||
*/
|
||||
public Builder setExitAnimations(
|
||||
@NonNull Context context, @AnimRes int enterResId, @AnimRes int exitResId) {
|
||||
Bundle bundle = ActivityOptionsCompat.makeCustomAnimation(
|
||||
context, enterResId, exitResId).toBundle();
|
||||
mIntent.putExtra(EXTRA_EXIT_ANIMATION_BUNDLE, bundle);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines all the options that have been set and returns a new {@link CustomTabsIntent}
|
||||
* object.
|
||||
*/
|
||||
public CustomTabsIntent build() {
|
||||
if (mMenuItems != null) {
|
||||
mIntent.putParcelableArrayListExtra(CustomTabsIntent.EXTRA_MENU_ITEMS, mMenuItems);
|
||||
}
|
||||
if (mActionButtons != null) {
|
||||
mIntent.putParcelableArrayListExtra(EXTRA_TOOLBAR_ITEMS, mActionButtons);
|
||||
}
|
||||
mIntent.putExtra(EXTRA_ENABLE_INSTANT_APPS, mInstantAppsEnabled);
|
||||
return new CustomTabsIntent(mIntent, mStartAnimationBundle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The maximum number of allowed toolbar items for
|
||||
* {@link CustomTabsIntent.Builder#addToolbarItem(int, Bitmap, String, PendingIntent)} and
|
||||
* {@link CustomTabsIntent#EXTRA_TOOLBAR_ITEMS}.
|
||||
*/
|
||||
public static int getMaxToolbarItems() {
|
||||
return MAX_TOOLBAR_ITEMS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the necessary flags and extras to signal any browser supporting custom tabs to use the
|
||||
* browser UI at all times and avoid showing custom tab like UI. Calling this with an intent
|
||||
* will override any custom tabs related customizations.
|
||||
* @param intent The intent to modify for always showing browser UI.
|
||||
* @return The same intent with the necessary flags and extras added.
|
||||
*/
|
||||
public static Intent setAlwaysUseBrowserUI(Intent intent) {
|
||||
if (intent == null) intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(EXTRA_USER_OPT_OUT_FROM_CUSTOM_TABS, true);
|
||||
return intent;
|
||||
}
|
||||
|
||||
public void setUseNewTask() {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a browser receiving the given intent should always use browser UI and avoid using any
|
||||
* custom tabs UI.
|
||||
*
|
||||
* @param intent The intent to check for the required flags and extras.
|
||||
* @return Whether the browser UI should be used exclusively.
|
||||
*/
|
||||
public static boolean shouldAlwaysUseBrowserUI(Intent intent) {
|
||||
return intent.getBooleanExtra(EXTRA_USER_OPT_OUT_FROM_CUSTOM_TABS, false)
|
||||
&& (intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0;
|
||||
}
|
||||
}
|
|
@ -1,271 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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 org.telegram.messenger.support.customtabs;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.IBinder.DeathRecipient;
|
||||
import android.os.RemoteException;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.collection.ArrayMap;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* Abstract service class for implementing Custom Tabs related functionality. The service should
|
||||
* be responding to the action ACTION_CUSTOM_TABS_CONNECTION. This class should be used by
|
||||
* implementers that want to provide Custom Tabs functionality, not by clients that want to launch
|
||||
* Custom Tabs.
|
||||
*/
|
||||
public abstract class CustomTabsService extends Service {
|
||||
/**
|
||||
* The Intent action that a CustomTabsService must respond to.
|
||||
*/
|
||||
public static final String ACTION_CUSTOM_TABS_CONNECTION =
|
||||
"android.support.customtabs.action.CustomTabsService";
|
||||
|
||||
/**
|
||||
* For {@link CustomTabsService#mayLaunchUrl} calls that wants to specify more than one url,
|
||||
* this key can be used with {@link Bundle#putParcelable(String, android.os.Parcelable)}
|
||||
* to insert a new url to each bundle inside list of bundles.
|
||||
*/
|
||||
public static final String KEY_URL =
|
||||
"android.support.customtabs.otherurls.URL";
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({RESULT_SUCCESS, RESULT_FAILURE_DISALLOWED,
|
||||
RESULT_FAILURE_REMOTE_ERROR, RESULT_FAILURE_MESSAGING_ERROR})
|
||||
public @interface Result {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the postMessage request was accepted.
|
||||
*/
|
||||
public static final int RESULT_SUCCESS = 0;
|
||||
/**
|
||||
* Indicates that the postMessage request was not allowed due to a bad argument or requesting
|
||||
* at a disallowed time like when in background.
|
||||
*/
|
||||
public static final int RESULT_FAILURE_DISALLOWED = -1;
|
||||
/**
|
||||
* Indicates that the postMessage request has failed due to a {@link RemoteException} .
|
||||
*/
|
||||
public static final int RESULT_FAILURE_REMOTE_ERROR = -2;
|
||||
/**
|
||||
* Indicates that the postMessage request has failed due to an internal error on the browser
|
||||
* message channel.
|
||||
*/
|
||||
public static final int RESULT_FAILURE_MESSAGING_ERROR = -3;
|
||||
|
||||
private final Map<IBinder, DeathRecipient> mDeathRecipientMap = new ArrayMap<>();
|
||||
|
||||
private ICustomTabsService.Stub mBinder = new ICustomTabsService.Stub() {
|
||||
|
||||
@Override
|
||||
public boolean warmup(long flags) {
|
||||
return CustomTabsService.this.warmup(flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean newSession(ICustomTabsCallback callback) {
|
||||
final CustomTabsSessionToken sessionToken = new CustomTabsSessionToken(callback);
|
||||
try {
|
||||
DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
|
||||
@Override
|
||||
public void binderDied() {
|
||||
cleanUpSession(sessionToken);
|
||||
}
|
||||
};
|
||||
synchronized (mDeathRecipientMap) {
|
||||
callback.asBinder().linkToDeath(deathRecipient, 0);
|
||||
mDeathRecipientMap.put(callback.asBinder(), deathRecipient);
|
||||
}
|
||||
return CustomTabsService.this.newSession(sessionToken);
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayLaunchUrl(ICustomTabsCallback callback, Uri url,
|
||||
Bundle extras, List<Bundle> otherLikelyBundles) {
|
||||
return CustomTabsService.this.mayLaunchUrl(
|
||||
new CustomTabsSessionToken(callback), url, extras, otherLikelyBundles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle extraCommand(String commandName, Bundle args) {
|
||||
return CustomTabsService.this.extraCommand(commandName, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateVisuals(ICustomTabsCallback callback, Bundle bundle) {
|
||||
return CustomTabsService.this.updateVisuals(
|
||||
new CustomTabsSessionToken(callback), bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requestPostMessageChannel(ICustomTabsCallback callback,
|
||||
Uri postMessageOrigin) {
|
||||
return CustomTabsService.this.requestPostMessageChannel(
|
||||
new CustomTabsSessionToken(callback), postMessageOrigin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int postMessage(ICustomTabsCallback callback, String message, Bundle extras) {
|
||||
return CustomTabsService.this.postMessage(
|
||||
new CustomTabsSessionToken(callback), message, extras);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the client side {@link IBinder} for this {@link CustomTabsSessionToken} is dead.
|
||||
* Can also be used to clean up {@link DeathRecipient} instances allocated for the given token.
|
||||
*
|
||||
* @param sessionToken The session token for which the {@link DeathRecipient} call has been
|
||||
* received.
|
||||
* @return Whether the clean up was successful. Multiple calls with two tokens holdings the
|
||||
* same binder will return false.
|
||||
*/
|
||||
protected boolean cleanUpSession(CustomTabsSessionToken sessionToken) {
|
||||
try {
|
||||
synchronized (mDeathRecipientMap) {
|
||||
IBinder binder = sessionToken.getCallbackBinder();
|
||||
DeathRecipient deathRecipient =
|
||||
mDeathRecipientMap.get(binder);
|
||||
binder.unlinkToDeath(deathRecipient, 0);
|
||||
mDeathRecipientMap.remove(binder);
|
||||
}
|
||||
} catch (NoSuchElementException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Warms up the browser process asynchronously.
|
||||
*
|
||||
* @param flags Reserved for future use.
|
||||
* @return Whether warmup was/had been completed successfully. Multiple successful
|
||||
* calls will return true.
|
||||
*/
|
||||
protected abstract boolean warmup(long flags);
|
||||
|
||||
/**
|
||||
* Creates a new session through an ICustomTabsService with the optional callback. This session
|
||||
* can be used to associate any related communication through the service with an intent and
|
||||
* then later with a Custom Tab. The client can then send later service calls or intents to
|
||||
* through same session-intent-Custom Tab association.
|
||||
*
|
||||
* @param sessionToken Session token to be used as a unique identifier. This also has access
|
||||
* to the {@link CustomTabsCallback} passed from the client side through
|
||||
* {@link CustomTabsSessionToken#getCallback()}.
|
||||
* @return Whether a new session was successfully created.
|
||||
*/
|
||||
protected abstract boolean newSession(CustomTabsSessionToken sessionToken);
|
||||
|
||||
/**
|
||||
* Tells the browser of a likely future navigation to a URL.
|
||||
* <p>
|
||||
* The method {@link CustomTabsService#warmup(long)} has to be called beforehand.
|
||||
* The most likely URL has to be specified explicitly. Optionally, a list of
|
||||
* other likely URLs can be provided. They are treated as less likely than
|
||||
* the first one, and have to be sorted in decreasing priority order. These
|
||||
* additional URLs may be ignored.
|
||||
* All previous calls to this method will be deprioritized.
|
||||
*
|
||||
* @param sessionToken The unique identifier for the session. Can not be null.
|
||||
* @param url Most likely URL.
|
||||
* @param extras Reserved for future use.
|
||||
* @param otherLikelyBundles Other likely destinations, sorted in decreasing
|
||||
* likelihood order. Each Bundle has to provide a url.
|
||||
* @return Whether the call was successful.
|
||||
*/
|
||||
protected abstract boolean mayLaunchUrl(CustomTabsSessionToken sessionToken, Uri url,
|
||||
Bundle extras, List<Bundle> otherLikelyBundles);
|
||||
|
||||
/**
|
||||
* Unsupported commands that may be provided by the implementation.
|
||||
* <p>
|
||||
* <p>
|
||||
* <strong>Note:</strong>Clients should <strong>never</strong> rely on this method to have a
|
||||
* defined behavior, as it is entirely implementation-defined and not supported.
|
||||
* <p>
|
||||
* <p> This call can be used by implementations to add extra commands, for testing or
|
||||
* experimental purposes.
|
||||
*
|
||||
* @param commandName Name of the extra command to execute.
|
||||
* @param args Arguments for the command
|
||||
* @return The result {@link Bundle}, or null.
|
||||
*/
|
||||
protected abstract Bundle extraCommand(String commandName, Bundle args);
|
||||
|
||||
/**
|
||||
* Updates the visuals of custom tabs for the given session. Will only succeed if the given
|
||||
* session matches the currently active one.
|
||||
*
|
||||
* @param sessionToken The currently active session that the custom tab belongs to.
|
||||
* @param bundle The action button configuration bundle. This bundle should be constructed
|
||||
* with the same structure in {@link CustomTabsIntent.Builder}.
|
||||
* @return Whether the operation was successful.
|
||||
*/
|
||||
protected abstract boolean updateVisuals(CustomTabsSessionToken sessionToken,
|
||||
Bundle bundle);
|
||||
|
||||
/**
|
||||
* Sends a request to create a two way postMessage channel between the client and the browser
|
||||
* linked with the given {@link CustomTabsSession}.
|
||||
*
|
||||
* @param sessionToken The unique identifier for the session. Can not be null.
|
||||
* @param postMessageOrigin A origin that the client is requesting to be identified as
|
||||
* during the postMessage communication.
|
||||
* @return Whether the implementation accepted the request. Note that returning true
|
||||
* here doesn't mean an origin has already been assigned as the validation is
|
||||
* asynchronous.
|
||||
*/
|
||||
protected abstract boolean requestPostMessageChannel(CustomTabsSessionToken sessionToken,
|
||||
Uri postMessageOrigin);
|
||||
|
||||
/**
|
||||
* Sends a postMessage request using the origin communicated via
|
||||
* {@link CustomTabsService#requestPostMessageChannel(
|
||||
*CustomTabsSessionToken, Uri)}. Fails when called before
|
||||
* {@link PostMessageServiceConnection#notifyMessageChannelReady(Bundle)} is received on the
|
||||
* client side.
|
||||
*
|
||||
* @param sessionToken The unique identifier for the session. Can not be null.
|
||||
* @param message The message that is being sent.
|
||||
* @param extras Reserved for future use.
|
||||
* @return An integer constant about the postMessage request result. Will return
|
||||
* {@link CustomTabsService#RESULT_SUCCESS} if successful.
|
||||
*/
|
||||
@Result
|
||||
protected abstract int postMessage(
|
||||
CustomTabsSessionToken sessionToken, String message, Bundle extras);
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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 org.telegram.messenger.support.customtabs;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
|
||||
/**
|
||||
* Abstract {@link ServiceConnection} to use while binding to a {@link CustomTabsService}. Any
|
||||
* client implementing this is responsible for handling changes related with the lifetime of the
|
||||
* connection like rebinding on disconnect.
|
||||
*/
|
||||
public abstract class CustomTabsServiceConnection implements ServiceConnection {
|
||||
|
||||
@Override
|
||||
public final void onServiceConnected(ComponentName name, IBinder service) {
|
||||
onCustomTabsServiceConnected(name, new CustomTabsClient(
|
||||
ICustomTabsService.Stub.asInterface(service), name) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a connection to the {@link CustomTabsService} has been established.
|
||||
* @param name The concrete component name of the service that has been connected.
|
||||
* @param client {@link CustomTabsClient} that contains the {@link IBinder} with which the
|
||||
* connection have been established. All further communication should be initiated
|
||||
* using this client.
|
||||
*/
|
||||
public abstract void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client);
|
||||
}
|
|
@ -1,204 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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 org.telegram.messenger.support.customtabs;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A class to be used for Custom Tabs related communication. Clients that want to launch Custom Tabs
|
||||
* can use this class exclusively to handle all related communication.
|
||||
*/
|
||||
public final class CustomTabsSession {
|
||||
private static final String TAG = "CustomTabsSession";
|
||||
private final Object mLock = new Object();
|
||||
private final ICustomTabsService mService;
|
||||
private final ICustomTabsCallback mCallback;
|
||||
private final ComponentName mComponentName;
|
||||
|
||||
/**
|
||||
* Provides browsers a way to generate a dummy {@link CustomTabsSession} for testing
|
||||
* purposes.
|
||||
*
|
||||
* @param componentName The component the session should be created for.
|
||||
* @return A dummy session with no functionality.
|
||||
*/
|
||||
public static CustomTabsSession createDummySessionForTesting(ComponentName componentName) {
|
||||
return new CustomTabsSession(null, new CustomTabsSessionToken.DummyCallback(), componentName);
|
||||
}
|
||||
|
||||
/* package */ CustomTabsSession(
|
||||
ICustomTabsService service, ICustomTabsCallback callback, ComponentName componentName) {
|
||||
mService = service;
|
||||
mCallback = callback;
|
||||
mComponentName = componentName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the browser of a likely future navigation to a URL.
|
||||
* The most likely URL has to be specified first. Optionally, a list of
|
||||
* other likely URLs can be provided. They are treated as less likely than
|
||||
* the first one, and have to be sorted in decreasing priority order. These
|
||||
* additional URLs may be ignored.
|
||||
* All previous calls to this method will be deprioritized.
|
||||
*
|
||||
* @param url Most likely URL.
|
||||
* @param extras Reserved for future use.
|
||||
* @param otherLikelyBundles Other likely destinations, sorted in decreasing
|
||||
* likelihood order. Inside each Bundle, the client should provide a
|
||||
* {@link Uri} using {@link CustomTabsService#KEY_URL} with
|
||||
* {@link Bundle#putParcelable(String, android.os.Parcelable)}.
|
||||
* @return true for success.
|
||||
*/
|
||||
public boolean mayLaunchUrl(Uri url, Bundle extras, List<Bundle> otherLikelyBundles) {
|
||||
try {
|
||||
return mService.mayLaunchUrl(mCallback, url, extras, otherLikelyBundles);
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This sets the action button on the toolbar with ID
|
||||
* {@link CustomTabsIntent#TOOLBAR_ACTION_BUTTON_ID}.
|
||||
*
|
||||
* @param icon The new icon of the action button.
|
||||
* @param description Content description of the action button.
|
||||
*
|
||||
* @see CustomTabsSession#setToolbarItem(int, Bitmap, String)
|
||||
*/
|
||||
public boolean setActionButton(@NonNull Bitmap icon, @NonNull String description) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(CustomTabsIntent.KEY_ICON, icon);
|
||||
bundle.putString(CustomTabsIntent.KEY_DESCRIPTION, description);
|
||||
|
||||
Bundle metaBundle = new Bundle();
|
||||
metaBundle.putBundle(CustomTabsIntent.EXTRA_ACTION_BUTTON_BUNDLE, bundle);
|
||||
try {
|
||||
return mService.updateVisuals(mCallback, metaBundle);
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the {@link RemoteViews} of the secondary toolbar in an existing custom tab session.
|
||||
* @param remoteViews The updated {@link RemoteViews} that will be shown in secondary toolbar.
|
||||
* If null, the current secondary toolbar will be dismissed.
|
||||
* @param clickableIDs The ids of clickable views. The onClick event of these views will be
|
||||
* handled by custom tabs.
|
||||
* @param pendingIntent The {@link PendingIntent} that will be sent when the user clicks on one
|
||||
* of the {@link View}s in clickableIDs.
|
||||
*/
|
||||
public boolean setSecondaryToolbarViews(@Nullable RemoteViews remoteViews,
|
||||
@Nullable int[] clickableIDs, @Nullable PendingIntent pendingIntent) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(CustomTabsIntent.EXTRA_REMOTEVIEWS, remoteViews);
|
||||
bundle.putIntArray(CustomTabsIntent.EXTRA_REMOTEVIEWS_VIEW_IDS, clickableIDs);
|
||||
bundle.putParcelable(CustomTabsIntent.EXTRA_REMOTEVIEWS_PENDINGINTENT, pendingIntent);
|
||||
try {
|
||||
return mService.updateVisuals(mCallback, bundle);
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the visuals for toolbar items. Will only succeed if a custom tab created using this
|
||||
* session is in the foreground in browser and the given id is valid.
|
||||
* @param id The id for the item to update.
|
||||
* @param icon The new icon of the toolbar item.
|
||||
* @param description Content description of the toolbar item.
|
||||
* @return Whether the update succeeded.
|
||||
* @deprecated Use
|
||||
* CustomTabsSession#setSecondaryToolbarViews(RemoteViews, int[], PendingIntent)
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean setToolbarItem(int id, @NonNull Bitmap icon, @NonNull String description) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt(CustomTabsIntent.KEY_ID, id);
|
||||
bundle.putParcelable(CustomTabsIntent.KEY_ICON, icon);
|
||||
bundle.putString(CustomTabsIntent.KEY_DESCRIPTION, description);
|
||||
|
||||
Bundle metaBundle = new Bundle();
|
||||
metaBundle.putBundle(CustomTabsIntent.EXTRA_ACTION_BUTTON_BUNDLE, bundle);
|
||||
try {
|
||||
return mService.updateVisuals(mCallback, metaBundle);
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request to create a two way postMessage channel between the client and the browser.
|
||||
*
|
||||
* @param postMessageOrigin A origin that the client is requesting to be identified as
|
||||
* during the postMessage communication.
|
||||
* @return Whether the implementation accepted the request. Note that returning true
|
||||
* here doesn't mean an origin has already been assigned as the validation is
|
||||
* asynchronous.
|
||||
*/
|
||||
public boolean requestPostMessageChannel(Uri postMessageOrigin) {
|
||||
try {
|
||||
return mService.requestPostMessageChannel(
|
||||
mCallback, postMessageOrigin);
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a postMessage request using the origin communicated via
|
||||
* {@link CustomTabsService#requestPostMessageChannel(
|
||||
* CustomTabsSessionToken, Uri)}. Fails when called before
|
||||
* {@link PostMessageServiceConnection#notifyMessageChannelReady(Bundle)} is received on
|
||||
* the client side.
|
||||
*
|
||||
* @param message The message that is being sent.
|
||||
* @param extras Reserved for future use.
|
||||
* @return An integer constant about the postMessage request result. Will return
|
||||
* {@link CustomTabsService#RESULT_SUCCESS} if successful.
|
||||
*/
|
||||
public int postMessage(String message, Bundle extras) {
|
||||
synchronized (mLock) {
|
||||
try {
|
||||
return mService.postMessage(mCallback, message, extras);
|
||||
} catch (RemoteException e) {
|
||||
return CustomTabsService.RESULT_FAILURE_REMOTE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ IBinder getBinder() {
|
||||
return mCallback.asBinder();
|
||||
}
|
||||
|
||||
/* package */ ComponentName getComponentName() {
|
||||
return mComponentName;
|
||||
}
|
||||
}
|
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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 org.telegram.messenger.support.customtabs;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import androidx.core.app.BundleCompat;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Wrapper class that can be used as a unique identifier for a session. Also contains an accessor
|
||||
* for the {@link CustomTabsCallback} for the session if there was any.
|
||||
*/
|
||||
public class CustomTabsSessionToken {
|
||||
private static final String TAG = "CustomTabsSessionToken";
|
||||
private final ICustomTabsCallback mCallbackBinder;
|
||||
private final CustomTabsCallback mCallback;
|
||||
|
||||
/* package */ static class DummyCallback extends ICustomTabsCallback.Stub {
|
||||
@Override
|
||||
public void onNavigationEvent(int navigationEvent, Bundle extras) {}
|
||||
|
||||
@Override
|
||||
public void extraCallback(String callbackName, Bundle args) {}
|
||||
|
||||
@Override
|
||||
public void onMessageChannelReady(Bundle extras) {}
|
||||
|
||||
@Override
|
||||
public void onPostMessage(String message, Bundle extras) {}
|
||||
|
||||
@Override
|
||||
public IBinder asBinder() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a {@link CustomTabsSessionToken} from an intent. See {@link CustomTabsIntent.Builder}
|
||||
* for ways to generate an intent for custom tabs.
|
||||
* @param intent The intent to generate the token from. This has to include an extra for
|
||||
* {@link CustomTabsIntent#EXTRA_SESSION}.
|
||||
* @return The token that was generated.
|
||||
*/
|
||||
public static CustomTabsSessionToken getSessionTokenFromIntent(Intent intent) {
|
||||
Bundle b = intent.getExtras();
|
||||
IBinder binder = BundleCompat.getBinder(b, CustomTabsIntent.EXTRA_SESSION);
|
||||
if (binder == null) return null;
|
||||
return new CustomTabsSessionToken(ICustomTabsCallback.Stub.asInterface(binder));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides browsers a way to generate a dummy {@link CustomTabsSessionToken} for testing
|
||||
* purposes.
|
||||
*
|
||||
* @return A dummy token with no functionality.
|
||||
*/
|
||||
public static CustomTabsSessionToken createDummySessionTokenForTesting() {
|
||||
return new CustomTabsSessionToken(new DummyCallback());
|
||||
}
|
||||
|
||||
CustomTabsSessionToken(ICustomTabsCallback callbackBinder) {
|
||||
mCallbackBinder = callbackBinder;
|
||||
mCallback = new CustomTabsCallback() {
|
||||
|
||||
@Override
|
||||
public void onNavigationEvent(int navigationEvent, Bundle extras) {
|
||||
try {
|
||||
mCallbackBinder.onNavigationEvent(navigationEvent, extras);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "RemoteException during ICustomTabsCallback transaction");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void extraCallback(String callbackName, Bundle args) {
|
||||
try {
|
||||
mCallbackBinder.extraCallback(callbackName, args);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "RemoteException during ICustomTabsCallback transaction");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageChannelReady(Bundle extras) {
|
||||
try {
|
||||
mCallbackBinder.onMessageChannelReady(extras);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "RemoteException during ICustomTabsCallback transaction");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostMessage(String message, Bundle extras) {
|
||||
try {
|
||||
mCallbackBinder.onPostMessage(message, extras);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "RemoteException during ICustomTabsCallback transaction");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
IBinder getCallbackBinder() {
|
||||
return mCallbackBinder.asBinder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getCallbackBinder().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof CustomTabsSessionToken)) return false;
|
||||
CustomTabsSessionToken token = (CustomTabsSessionToken) o;
|
||||
return token.getCallbackBinder().equals(mCallbackBinder.asBinder());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link CustomTabsCallback} corresponding to this session if there was any non-null
|
||||
* callbacks passed by the client.
|
||||
*/
|
||||
public CustomTabsCallback getCallback() {
|
||||
return mCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether this token is associated with the given session.
|
||||
*/
|
||||
public boolean isAssociatedWith(CustomTabsSession session) {
|
||||
return session.getBinder().equals(mCallbackBinder);
|
||||
}
|
||||
}
|
|
@ -1,226 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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 org.telegram.messenger.support.customtabs;
|
||||
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.Parcel;
|
||||
import android.os.RemoteException;
|
||||
|
||||
public interface ICustomTabsCallback extends IInterface {
|
||||
void onNavigationEvent(int var1, Bundle var2) throws RemoteException;
|
||||
|
||||
void extraCallback(String var1, Bundle var2) throws RemoteException;
|
||||
|
||||
void onMessageChannelReady(Bundle var1) throws RemoteException;
|
||||
|
||||
void onPostMessage(String var1, Bundle var2) throws RemoteException;
|
||||
|
||||
abstract class Stub extends Binder implements ICustomTabsCallback {
|
||||
private static final String DESCRIPTOR = "android.support.customtabs.ICustomTabsCallback";
|
||||
static final int TRANSACTION_onNavigationEvent = 2;
|
||||
static final int TRANSACTION_extraCallback = 3;
|
||||
static final int TRANSACTION_onMessageChannelReady = 4;
|
||||
static final int TRANSACTION_onPostMessage = 5;
|
||||
|
||||
public Stub() {
|
||||
this.attachInterface(this, "android.support.customtabs.ICustomTabsCallback");
|
||||
}
|
||||
|
||||
public static ICustomTabsCallback asInterface(IBinder obj) {
|
||||
if(obj == null) {
|
||||
return null;
|
||||
} else {
|
||||
IInterface iin = obj.queryLocalInterface("android.support.customtabs.ICustomTabsCallback");
|
||||
return (iin != null && iin instanceof ICustomTabsCallback?(ICustomTabsCallback)iin:new ICustomTabsCallback.Stub.Proxy(obj));
|
||||
}
|
||||
}
|
||||
|
||||
public IBinder asBinder() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
|
||||
String _arg0;
|
||||
Bundle _arg1;
|
||||
switch(code) {
|
||||
case 2:
|
||||
data.enforceInterface("android.support.customtabs.ICustomTabsCallback");
|
||||
int _arg02 = data.readInt();
|
||||
if(0 != data.readInt()) {
|
||||
_arg1 = Bundle.CREATOR.createFromParcel(data);
|
||||
} else {
|
||||
_arg1 = null;
|
||||
}
|
||||
|
||||
this.onNavigationEvent(_arg02, _arg1);
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
case 3:
|
||||
data.enforceInterface("android.support.customtabs.ICustomTabsCallback");
|
||||
_arg0 = data.readString();
|
||||
if(0 != data.readInt()) {
|
||||
_arg1 = Bundle.CREATOR.createFromParcel(data);
|
||||
} else {
|
||||
_arg1 = null;
|
||||
}
|
||||
|
||||
this.extraCallback(_arg0, _arg1);
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
case 4:
|
||||
data.enforceInterface("android.support.customtabs.ICustomTabsCallback");
|
||||
Bundle _arg01;
|
||||
if(0 != data.readInt()) {
|
||||
_arg01 = Bundle.CREATOR.createFromParcel(data);
|
||||
} else {
|
||||
_arg01 = null;
|
||||
}
|
||||
|
||||
this.onMessageChannelReady(_arg01);
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
case 5:
|
||||
data.enforceInterface("android.support.customtabs.ICustomTabsCallback");
|
||||
_arg0 = data.readString();
|
||||
if(0 != data.readInt()) {
|
||||
_arg1 = Bundle.CREATOR.createFromParcel(data);
|
||||
} else {
|
||||
_arg1 = null;
|
||||
}
|
||||
|
||||
this.onPostMessage(_arg0, _arg1);
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
case 1598968902:
|
||||
reply.writeString("android.support.customtabs.ICustomTabsCallback");
|
||||
return true;
|
||||
default:
|
||||
return super.onTransact(code, data, reply, flags);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Proxy implements ICustomTabsCallback {
|
||||
private IBinder mRemote;
|
||||
|
||||
Proxy(IBinder remote) {
|
||||
this.mRemote = remote;
|
||||
}
|
||||
|
||||
public IBinder asBinder() {
|
||||
return this.mRemote;
|
||||
}
|
||||
|
||||
public String getInterfaceDescriptor() {
|
||||
return "android.support.customtabs.ICustomTabsCallback";
|
||||
}
|
||||
|
||||
public void onNavigationEvent(int navigationEvent, Bundle extras) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
|
||||
try {
|
||||
_data.writeInterfaceToken("android.support.customtabs.ICustomTabsCallback");
|
||||
_data.writeInt(navigationEvent);
|
||||
if(extras != null) {
|
||||
_data.writeInt(1);
|
||||
extras.writeToParcel(_data, 0);
|
||||
} else {
|
||||
_data.writeInt(0);
|
||||
}
|
||||
|
||||
this.mRemote.transact(2, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void extraCallback(String callbackName, Bundle args) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
|
||||
try {
|
||||
_data.writeInterfaceToken("android.support.customtabs.ICustomTabsCallback");
|
||||
_data.writeString(callbackName);
|
||||
if(args != null) {
|
||||
_data.writeInt(1);
|
||||
args.writeToParcel(_data, 0);
|
||||
} else {
|
||||
_data.writeInt(0);
|
||||
}
|
||||
|
||||
this.mRemote.transact(3, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void onMessageChannelReady(Bundle extras) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
|
||||
try {
|
||||
_data.writeInterfaceToken("android.support.customtabs.ICustomTabsCallback");
|
||||
if(extras != null) {
|
||||
_data.writeInt(1);
|
||||
extras.writeToParcel(_data, 0);
|
||||
} else {
|
||||
_data.writeInt(0);
|
||||
}
|
||||
|
||||
this.mRemote.transact(4, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void onPostMessage(String message, Bundle extras) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
|
||||
try {
|
||||
_data.writeInterfaceToken("android.support.customtabs.ICustomTabsCallback");
|
||||
_data.writeString(message);
|
||||
if(extras != null) {
|
||||
_data.writeInt(1);
|
||||
extras.writeToParcel(_data, 0);
|
||||
} else {
|
||||
_data.writeInt(0);
|
||||
}
|
||||
|
||||
this.mRemote.transact(5, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,377 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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 org.telegram.messenger.support.customtabs;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.Parcel;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public interface ICustomTabsService extends IInterface {
|
||||
boolean warmup(long var1) throws RemoteException;
|
||||
|
||||
boolean newSession(ICustomTabsCallback var1) throws RemoteException;
|
||||
|
||||
boolean mayLaunchUrl(ICustomTabsCallback var1, Uri var2, Bundle var3, List<Bundle> var4) throws RemoteException;
|
||||
|
||||
Bundle extraCommand(String var1, Bundle var2) throws RemoteException;
|
||||
|
||||
boolean updateVisuals(ICustomTabsCallback var1, Bundle var2) throws RemoteException;
|
||||
|
||||
boolean requestPostMessageChannel(ICustomTabsCallback var1, Uri var2) throws RemoteException;
|
||||
|
||||
int postMessage(ICustomTabsCallback var1, String var2, Bundle var3) throws RemoteException;
|
||||
|
||||
abstract class Stub extends Binder implements ICustomTabsService {
|
||||
private static final String DESCRIPTOR = "android.support.customtabs.ICustomTabsService";
|
||||
static final int TRANSACTION_warmup = 2;
|
||||
static final int TRANSACTION_newSession = 3;
|
||||
static final int TRANSACTION_mayLaunchUrl = 4;
|
||||
static final int TRANSACTION_extraCommand = 5;
|
||||
static final int TRANSACTION_updateVisuals = 6;
|
||||
static final int TRANSACTION_requestPostMessageChannel = 7;
|
||||
static final int TRANSACTION_postMessage = 8;
|
||||
|
||||
public Stub() {
|
||||
this.attachInterface(this, "android.support.customtabs.ICustomTabsService");
|
||||
}
|
||||
|
||||
public static ICustomTabsService asInterface(IBinder obj) {
|
||||
if(obj == null) {
|
||||
return null;
|
||||
} else {
|
||||
IInterface iin = obj.queryLocalInterface("android.support.customtabs.ICustomTabsService");
|
||||
return (iin != null && iin instanceof ICustomTabsService?(ICustomTabsService)iin:new ICustomTabsService.Stub.Proxy(obj));
|
||||
}
|
||||
}
|
||||
|
||||
public IBinder asBinder() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
|
||||
ICustomTabsCallback _arg0;
|
||||
Bundle _arg2;
|
||||
Uri _arg11;
|
||||
Bundle _arg12;
|
||||
boolean _arg21;
|
||||
switch(code) {
|
||||
case 2:
|
||||
data.enforceInterface("android.support.customtabs.ICustomTabsService");
|
||||
long _arg02 = data.readLong();
|
||||
_arg21 = this.warmup(_arg02);
|
||||
reply.writeNoException();
|
||||
reply.writeInt(_arg21?1:0);
|
||||
return true;
|
||||
case 3:
|
||||
data.enforceInterface("android.support.customtabs.ICustomTabsService");
|
||||
_arg0 = ICustomTabsCallback.Stub.asInterface(data.readStrongBinder());
|
||||
boolean _arg13 = this.newSession(_arg0);
|
||||
reply.writeNoException();
|
||||
reply.writeInt(_arg13?1:0);
|
||||
return true;
|
||||
case 4:
|
||||
data.enforceInterface("android.support.customtabs.ICustomTabsService");
|
||||
_arg0 = ICustomTabsCallback.Stub.asInterface(data.readStrongBinder());
|
||||
if(0 != data.readInt()) {
|
||||
_arg11 = Uri.CREATOR.createFromParcel(data);
|
||||
} else {
|
||||
_arg11 = null;
|
||||
}
|
||||
|
||||
if(0 != data.readInt()) {
|
||||
_arg2 = Bundle.CREATOR.createFromParcel(data);
|
||||
} else {
|
||||
_arg2 = null;
|
||||
}
|
||||
|
||||
ArrayList _result2 = data.createTypedArrayList(Bundle.CREATOR);
|
||||
boolean _result1 = this.mayLaunchUrl(_arg0, _arg11, _arg2, _result2);
|
||||
reply.writeNoException();
|
||||
reply.writeInt(_result1?1:0);
|
||||
return true;
|
||||
case 5:
|
||||
data.enforceInterface("android.support.customtabs.ICustomTabsService");
|
||||
String _arg01 = data.readString();
|
||||
if(0 != data.readInt()) {
|
||||
_arg12 = Bundle.CREATOR.createFromParcel(data);
|
||||
} else {
|
||||
_arg12 = null;
|
||||
}
|
||||
|
||||
_arg2 = this.extraCommand(_arg01, _arg12);
|
||||
reply.writeNoException();
|
||||
if(_arg2 != null) {
|
||||
reply.writeInt(1);
|
||||
_arg2.writeToParcel(reply, 1);
|
||||
} else {
|
||||
reply.writeInt(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
case 6:
|
||||
data.enforceInterface("android.support.customtabs.ICustomTabsService");
|
||||
_arg0 = ICustomTabsCallback.Stub.asInterface(data.readStrongBinder());
|
||||
if(0 != data.readInt()) {
|
||||
_arg12 = Bundle.CREATOR.createFromParcel(data);
|
||||
} else {
|
||||
_arg12 = null;
|
||||
}
|
||||
|
||||
_arg21 = this.updateVisuals(_arg0, _arg12);
|
||||
reply.writeNoException();
|
||||
reply.writeInt(_arg21?1:0);
|
||||
return true;
|
||||
case 7:
|
||||
data.enforceInterface("android.support.customtabs.ICustomTabsService");
|
||||
_arg0 = ICustomTabsCallback.Stub.asInterface(data.readStrongBinder());
|
||||
if(0 != data.readInt()) {
|
||||
_arg11 = Uri.CREATOR.createFromParcel(data);
|
||||
} else {
|
||||
_arg11 = null;
|
||||
}
|
||||
|
||||
_arg21 = this.requestPostMessageChannel(_arg0, _arg11);
|
||||
reply.writeNoException();
|
||||
reply.writeInt(_arg21?1:0);
|
||||
return true;
|
||||
case 8:
|
||||
data.enforceInterface("android.support.customtabs.ICustomTabsService");
|
||||
_arg0 = ICustomTabsCallback.Stub.asInterface(data.readStrongBinder());
|
||||
String _arg1 = data.readString();
|
||||
if(0 != data.readInt()) {
|
||||
_arg2 = Bundle.CREATOR.createFromParcel(data);
|
||||
} else {
|
||||
_arg2 = null;
|
||||
}
|
||||
|
||||
int _result = this.postMessage(_arg0, _arg1, _arg2);
|
||||
reply.writeNoException();
|
||||
reply.writeInt(_result);
|
||||
return true;
|
||||
case 1598968902:
|
||||
reply.writeString("android.support.customtabs.ICustomTabsService");
|
||||
return true;
|
||||
default:
|
||||
return super.onTransact(code, data, reply, flags);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Proxy implements ICustomTabsService {
|
||||
private IBinder mRemote;
|
||||
|
||||
Proxy(IBinder remote) {
|
||||
this.mRemote = remote;
|
||||
}
|
||||
|
||||
public IBinder asBinder() {
|
||||
return this.mRemote;
|
||||
}
|
||||
|
||||
public String getInterfaceDescriptor() {
|
||||
return "android.support.customtabs.ICustomTabsService";
|
||||
}
|
||||
|
||||
public boolean warmup(long flags) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
|
||||
boolean _result;
|
||||
try {
|
||||
_data.writeInterfaceToken("android.support.customtabs.ICustomTabsService");
|
||||
_data.writeLong(flags);
|
||||
this.mRemote.transact(2, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
_result = 0 != _reply.readInt();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
|
||||
return _result;
|
||||
}
|
||||
|
||||
public boolean newSession(ICustomTabsCallback callback) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
|
||||
boolean _result;
|
||||
try {
|
||||
_data.writeInterfaceToken("android.support.customtabs.ICustomTabsService");
|
||||
_data.writeStrongBinder(callback != null?callback.asBinder():null);
|
||||
this.mRemote.transact(3, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
_result = 0 != _reply.readInt();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
|
||||
return _result;
|
||||
}
|
||||
|
||||
public boolean mayLaunchUrl(ICustomTabsCallback callback, Uri url, Bundle extras, List<Bundle> otherLikelyBundles) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
|
||||
boolean _result;
|
||||
try {
|
||||
_data.writeInterfaceToken("android.support.customtabs.ICustomTabsService");
|
||||
_data.writeStrongBinder(callback != null?callback.asBinder():null);
|
||||
if(url != null) {
|
||||
_data.writeInt(1);
|
||||
url.writeToParcel(_data, 0);
|
||||
} else {
|
||||
_data.writeInt(0);
|
||||
}
|
||||
|
||||
if(extras != null) {
|
||||
_data.writeInt(1);
|
||||
extras.writeToParcel(_data, 0);
|
||||
} else {
|
||||
_data.writeInt(0);
|
||||
}
|
||||
|
||||
_data.writeTypedList(otherLikelyBundles);
|
||||
this.mRemote.transact(4, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
_result = 0 != _reply.readInt();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
|
||||
return _result;
|
||||
}
|
||||
|
||||
public Bundle extraCommand(String commandName, Bundle args) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
|
||||
Bundle _result;
|
||||
try {
|
||||
_data.writeInterfaceToken("android.support.customtabs.ICustomTabsService");
|
||||
_data.writeString(commandName);
|
||||
if(args != null) {
|
||||
_data.writeInt(1);
|
||||
args.writeToParcel(_data, 0);
|
||||
} else {
|
||||
_data.writeInt(0);
|
||||
}
|
||||
|
||||
this.mRemote.transact(5, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
if(0 != _reply.readInt()) {
|
||||
_result = Bundle.CREATOR.createFromParcel(_reply);
|
||||
} else {
|
||||
_result = null;
|
||||
}
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
|
||||
return _result;
|
||||
}
|
||||
|
||||
public boolean updateVisuals(ICustomTabsCallback callback, Bundle bundle) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
|
||||
boolean _result;
|
||||
try {
|
||||
_data.writeInterfaceToken("android.support.customtabs.ICustomTabsService");
|
||||
_data.writeStrongBinder(callback != null?callback.asBinder():null);
|
||||
if(bundle != null) {
|
||||
_data.writeInt(1);
|
||||
bundle.writeToParcel(_data, 0);
|
||||
} else {
|
||||
_data.writeInt(0);
|
||||
}
|
||||
|
||||
this.mRemote.transact(6, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
_result = 0 != _reply.readInt();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
|
||||
return _result;
|
||||
}
|
||||
|
||||
public boolean requestPostMessageChannel(ICustomTabsCallback callback, Uri postMessageOrigin) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
|
||||
boolean _result;
|
||||
try {
|
||||
_data.writeInterfaceToken("android.support.customtabs.ICustomTabsService");
|
||||
_data.writeStrongBinder(callback != null?callback.asBinder():null);
|
||||
if(postMessageOrigin != null) {
|
||||
_data.writeInt(1);
|
||||
postMessageOrigin.writeToParcel(_data, 0);
|
||||
} else {
|
||||
_data.writeInt(0);
|
||||
}
|
||||
|
||||
this.mRemote.transact(7, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
_result = 0 != _reply.readInt();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
|
||||
return _result;
|
||||
}
|
||||
|
||||
public int postMessage(ICustomTabsCallback callback, String message, Bundle extras) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
|
||||
int _result;
|
||||
try {
|
||||
_data.writeInterfaceToken("android.support.customtabs.ICustomTabsService");
|
||||
_data.writeStrongBinder(callback != null?callback.asBinder():null);
|
||||
_data.writeString(message);
|
||||
if(extras != null) {
|
||||
_data.writeInt(1);
|
||||
extras.writeToParcel(_data, 0);
|
||||
} else {
|
||||
_data.writeInt(0);
|
||||
}
|
||||
|
||||
this.mRemote.transact(8, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
_result = _reply.readInt();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
|
||||
return _result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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 org.telegram.messenger.support.customtabs;
|
||||
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.Parcel;
|
||||
import android.os.RemoteException;
|
||||
|
||||
public interface IPostMessageService extends IInterface {
|
||||
|
||||
void onMessageChannelReady(ICustomTabsCallback var1, Bundle var2) throws RemoteException;
|
||||
|
||||
void onPostMessage(ICustomTabsCallback var1, String var2, Bundle var3) throws RemoteException;
|
||||
|
||||
abstract class Stub extends Binder implements IPostMessageService {
|
||||
private static final String DESCRIPTOR = "android.support.customtabs.IPostMessageService";
|
||||
static final int TRANSACTION_onMessageChannelReady = 2;
|
||||
static final int TRANSACTION_onPostMessage = 3;
|
||||
|
||||
public Stub() {
|
||||
this.attachInterface(this, "android.support.customtabs.IPostMessageService");
|
||||
}
|
||||
|
||||
public static IPostMessageService asInterface(IBinder obj) {
|
||||
if(obj == null) {
|
||||
return null;
|
||||
} else {
|
||||
IInterface iin = obj.queryLocalInterface("android.support.customtabs.IPostMessageService");
|
||||
return (iin != null && iin instanceof IPostMessageService?(IPostMessageService)iin:new IPostMessageService.Stub.Proxy(obj));
|
||||
}
|
||||
}
|
||||
|
||||
public IBinder asBinder() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
|
||||
ICustomTabsCallback _arg0;
|
||||
switch(code) {
|
||||
case 2:
|
||||
data.enforceInterface("android.support.customtabs.IPostMessageService");
|
||||
_arg0 = ICustomTabsCallback.Stub.asInterface(data.readStrongBinder());
|
||||
Bundle _arg11;
|
||||
if(0 != data.readInt()) {
|
||||
_arg11 = Bundle.CREATOR.createFromParcel(data);
|
||||
} else {
|
||||
_arg11 = null;
|
||||
}
|
||||
|
||||
this.onMessageChannelReady(_arg0, _arg11);
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
case 3:
|
||||
data.enforceInterface("android.support.customtabs.IPostMessageService");
|
||||
_arg0 = ICustomTabsCallback.Stub.asInterface(data.readStrongBinder());
|
||||
String _arg1 = data.readString();
|
||||
Bundle _arg2;
|
||||
if(0 != data.readInt()) {
|
||||
_arg2 = Bundle.CREATOR.createFromParcel(data);
|
||||
} else {
|
||||
_arg2 = null;
|
||||
}
|
||||
|
||||
this.onPostMessage(_arg0, _arg1, _arg2);
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
case 1598968902:
|
||||
reply.writeString("android.support.customtabs.IPostMessageService");
|
||||
return true;
|
||||
default:
|
||||
return super.onTransact(code, data, reply, flags);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Proxy implements IPostMessageService {
|
||||
private IBinder mRemote;
|
||||
|
||||
Proxy(IBinder remote) {
|
||||
this.mRemote = remote;
|
||||
}
|
||||
|
||||
public IBinder asBinder() {
|
||||
return this.mRemote;
|
||||
}
|
||||
|
||||
public String getInterfaceDescriptor() {
|
||||
return "android.support.customtabs.IPostMessageService";
|
||||
}
|
||||
|
||||
public void onMessageChannelReady(ICustomTabsCallback callback, Bundle extras) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
|
||||
try {
|
||||
_data.writeInterfaceToken("android.support.customtabs.IPostMessageService");
|
||||
_data.writeStrongBinder(callback != null?callback.asBinder():null);
|
||||
if(extras != null) {
|
||||
_data.writeInt(1);
|
||||
extras.writeToParcel(_data, 0);
|
||||
} else {
|
||||
_data.writeInt(0);
|
||||
}
|
||||
|
||||
this.mRemote.transact(2, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void onPostMessage(ICustomTabsCallback callback, String message, Bundle extras) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
|
||||
try {
|
||||
_data.writeInterfaceToken("android.support.customtabs.IPostMessageService");
|
||||
_data.writeStrongBinder(callback != null?callback.asBinder():null);
|
||||
_data.writeString(message);
|
||||
if(extras != null) {
|
||||
_data.writeInt(1);
|
||||
extras.writeToParcel(_data, 0);
|
||||
} else {
|
||||
_data.writeInt(0);
|
||||
}
|
||||
|
||||
this.mRemote.transact(3, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* This is the source code of Telegram for Android v. 5.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
package org.telegram.messenger.support.customtabs;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
/**
|
||||
* A service to receive postMessage related communication from a Custom Tabs provider.
|
||||
*/
|
||||
public class PostMessageService extends Service {
|
||||
private IPostMessageService.Stub mBinder = new IPostMessageService.Stub() {
|
||||
|
||||
@Override
|
||||
public void onMessageChannelReady(
|
||||
ICustomTabsCallback callback, Bundle extras) throws RemoteException {
|
||||
callback.onMessageChannelReady(extras);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostMessage(ICustomTabsCallback callback,
|
||||
String message, Bundle extras) throws RemoteException {
|
||||
callback.onPostMessage(message, extras);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return mBinder;
|
||||
}
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
* This is the source code of Telegram for Android v. 5.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
package org.telegram.messenger.support.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;
|
||||
|
||||
/**
|
||||
* A {@link ServiceConnection} for Custom Tabs providers to use while connecting to a
|
||||
* {@link PostMessageService} on the client side.
|
||||
*/
|
||||
public abstract class PostMessageServiceConnection implements ServiceConnection {
|
||||
private final Object mLock = new Object();
|
||||
private final ICustomTabsCallback mSessionBinder;
|
||||
private IPostMessageService mService;
|
||||
|
||||
public PostMessageServiceConnection(CustomTabsSessionToken session) {
|
||||
mSessionBinder = ICustomTabsCallback.Stub.asInterface(session.getCallbackBinder());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(Context context, String packageName) {
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName(packageName, PostMessageService.class.getName());
|
||||
return context.bindService(intent, this, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbinds this service connection from the given context.
|
||||
* @param context The context to be unbound from.
|
||||
*/
|
||||
public void unbindFromContext(Context context) {
|
||||
context.unbindService(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mService = IPostMessageService.Stub.asInterface(service);
|
||||
onPostMessageServiceConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onServiceDisconnected(ComponentName name) {
|
||||
mService = null;
|
||||
onPostMessageServiceDisconnected();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public final boolean notifyMessageChannelReady(Bundle extras) {
|
||||
if (mService == null) return false;
|
||||
synchronized (mLock) {
|
||||
try {
|
||||
mService.onMessageChannelReady(mSessionBinder, extras);
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public final boolean postMessage(String message, Bundle extras) {
|
||||
if (mService == null) return false;
|
||||
synchronized (mLock) {
|
||||
try {
|
||||
mService.onPostMessage(mSessionBinder, message, extras);
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the {@link PostMessageService} connection is established.
|
||||
*/
|
||||
public void onPostMessageServiceConnected() {}
|
||||
|
||||
/**
|
||||
* Called when the connection is lost with the {@link PostMessageService}.
|
||||
*/
|
||||
public void onPostMessageServiceDisconnected() {}
|
||||
}
|
|
@ -16,8 +16,8 @@ package org.telegram.messenger.support.customtabsclient.shared;
|
|||
|
||||
import android.content.ComponentName;
|
||||
|
||||
import org.telegram.messenger.support.customtabs.CustomTabsClient;
|
||||
import org.telegram.messenger.support.customtabs.CustomTabsServiceConnection;
|
||||
import androidx.browser.customtabs.CustomTabsClient;
|
||||
import androidx.browser.customtabs.CustomTabsServiceConnection;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
package org.telegram.messenger.support.customtabsclient.shared;
|
||||
|
||||
import org.telegram.messenger.support.customtabs.CustomTabsClient;
|
||||
import androidx.browser.customtabs.CustomTabsClient;
|
||||
|
||||
/**
|
||||
* Callback for events when connecting and disconnecting from Custom Tabs Service.
|
||||
|
|
Loading…
Reference in New Issue