Commit e4f9a4f5 authored by Peter E Conn's avatar Peter E Conn Committed by Commit Bot

Reland "🛃 Move Custom Tabs example into Chromium."

This CL is a reland of the following CL. It fixes the issues that
produced lint warnings.

https://chromium-review.googlesource.com/c/chromium/src/+/2120724

TBR=dominickn@chromium.org, twellington@chromium.org, agrieve@chromium.org, yfriedman@chromium.org

Bug: 980567
Change-Id: Ia48f18c9f10ce3a2239781d0c97174de4d234d7f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2142251Reviewed-by: default avatarPeter Conn <peconn@chromium.org>
Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Commit-Queue: Peter Conn <peconn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#758858}
parent bd8517d1
...@@ -385,10 +385,10 @@ group("gn_all") { ...@@ -385,10 +385,10 @@ group("gn_all") {
"//chrome/android:chrome_public_apk", "//chrome/android:chrome_public_apk",
"//chrome/android:chrome_public_test_apk", "//chrome/android:chrome_public_test_apk",
"//chrome/android/features/media_router:media_router_junit_tests", "//chrome/android/features/media_router:media_router_junit_tests",
"//chrome/browser/android/examples/custom_tabs_client:custom_tabs_client_example_apk",
"//chrome/browser/android/examples/partner_browser_customizations_provider:partner_browser_customizations_example_apk", "//chrome/browser/android/examples/partner_browser_customizations_provider:partner_browser_customizations_example_apk",
"//chrome/test/chromedriver/test/webview_shell:chromedriver_webview_shell_apk", "//chrome/test/chromedriver/test/webview_shell:chromedriver_webview_shell_apk",
"//content/shell/android:content_shell_test_apk", "//content/shell/android:content_shell_test_apk",
"//third_party/custom_tabs_client:custom_tabs_client_example_apk",
] ]
} }
......
...@@ -875,11 +875,6 @@ deps = { ...@@ -875,11 +875,6 @@ deps = {
'condition': 'checkout_linux', 'condition': 'checkout_linux',
}, },
'src/third_party/custom_tabs_client/src': {
'url': Var('chromium_git') + '/custom-tabs-client.git' + '@' + 'a633542d9854151eb4f0bfd1d93da88f5934a11a',
'condition': 'checkout_android',
},
'src/third_party/depot_tools': 'src/third_party/depot_tools':
Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '08f4d59e0b177d3d15b65f9826bbf05491b3841d', Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '08f4d59e0b177d3d15b65f9826bbf05491b3841d',
......
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/android/rules.gni")
android_resources("chrome_tabs_client_example_apk_resources") {
sources = [
"src/res/anim/slide_in_left.xml",
"src/res/anim/slide_in_right.xml",
"src/res/anim/slide_out_left.xml",
"src/res/anim/slide_out_right.xml",
"src/res/drawable-hdpi/cover.jpg",
"src/res/drawable-hdpi/ic_arrow_back.png",
"src/res/drawable-hdpi/ic_launcher.png",
"src/res/drawable-hdpi/ic_notification_icon.png",
"src/res/drawable-hdpi/ic_play.png",
"src/res/drawable-hdpi/ic_share.png",
"src/res/drawable-hdpi/ic_stop.png",
"src/res/drawable-mdpi/cover.jpg",
"src/res/drawable-mdpi/ic_arrow_back.png",
"src/res/drawable-mdpi/ic_launcher.png",
"src/res/drawable-mdpi/ic_notification_icon.png",
"src/res/drawable-mdpi/ic_play.png",
"src/res/drawable-mdpi/ic_share.png",
"src/res/drawable-mdpi/ic_stop.png",
"src/res/drawable-xhdpi/cover.jpg",
"src/res/drawable-xhdpi/ic_arrow_back.png",
"src/res/drawable-xhdpi/ic_launcher.png",
"src/res/drawable-xhdpi/ic_notification_icon.png",
"src/res/drawable-xhdpi/ic_play.png",
"src/res/drawable-xhdpi/ic_share.png",
"src/res/drawable-xhdpi/ic_stop.png",
"src/res/drawable-xxhdpi/cover.jpg",
"src/res/drawable-xxhdpi/ic_arrow_back.png",
"src/res/drawable-xxhdpi/ic_launcher.png",
"src/res/drawable-xxhdpi/ic_notification_icon.png",
"src/res/drawable-xxhdpi/ic_play.png",
"src/res/drawable-xxhdpi/ic_share.png",
"src/res/drawable-xxhdpi/ic_stop.png",
"src/res/drawable-xxxhdpi/ic_arrow_back.png",
"src/res/drawable-xxxhdpi/ic_launcher.png",
"src/res/drawable-xxxhdpi/ic_share.png",
"src/res/layout/main.xml",
"src/res/layout/remote_view.xml",
"src/res/raw/amazing_grace.mp3",
"src/res/values/strings.xml",
]
android_manifest = "src/AndroidManifest.xml"
custom_package = "org.chromium.customtabsclient"
deps = [ "//third_party/android_deps:android_support_v7_appcompat_java" ]
}
android_apk("custom_tabs_client_example_apk") {
sources = [
"src/java/org/chromium/customtabsclient/BottomBarManager.java",
"src/java/org/chromium/customtabsclient/BrowserActionsReceiver.java",
"src/java/org/chromium/customtabsclient/MainActivity.java",
"src/java/org/chromium/customtabsclient/SessionHelper.java",
"src/java/org/chromium/customtabsclient/shared/CustomTabsHelper.java",
"src/java/org/chromium/customtabsclient/shared/KeepAliveService.java",
"src/java/org/chromium/customtabsclient/shared/ServiceConnection.java",
"src/java/org/chromium/customtabsclient/shared/ServiceConnectionCallback.java",
]
android_manifest = "src/AndroidManifest.xml"
min_sdk_version = 19
target_sdk_version = 21
apk_name = "CustomTabsClientExample"
deps = [
":chrome_tabs_client_example_apk_resources",
"//third_party/android_deps:android_support_v7_appcompat_java",
"//third_party/android_deps:androidx_annotation_annotation_java",
"//third_party/android_deps:androidx_appcompat_appcompat_java",
"//third_party/android_deps:androidx_lifecycle_lifecycle_common_java",
"//third_party/android_sdk/androidx_browser:androidx_browser_java",
]
}
file://chrome/android/java/src/org/chromium/chrome/browser/customtabs/OWNERS
# COMPONENT: UI>Browser>Mobile>CustomTabs
# OS: Android
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2015 Google Inc. All Rights Reserved.
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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.chromium.customtabsclient"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="21" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:allowBackup="false"
android:theme="@style/Theme.AppCompat.Light" >
<activity
android:name="org.chromium.customtabsclient.MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="https"
android:host="www.example.com"
android:pathPrefix="/notifications"/>
</intent-filter>
</activity>
<service
android:name=".shared.KeepAliveService"
android:exported="true"/>
<receiver android:name=".BottomBarManager"/>
<service
android:name="android.support.customtabs.trusted.TrustedWebActivityService"
android:enabled="true"
android:exported="true">
<meta-data android:name="android.support.customtabs.trusted.SMALL_ICON"
android:resource="@drawable/ic_notification_icon" />
<intent-filter>
<action android:name="android.support.customtabs.trusted.TRUSTED_WEB_ACTIVITY_SERVICE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
</application>
</manifest>
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.customtabsclient;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.widget.RemoteViews;
import android.widget.Toast;
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.browser.customtabs.CustomTabsSession;
import java.lang.ref.WeakReference;
/**
* A {@link BroadcastReceiver} that manages the interaction with the active Custom Tab.
*/
public class BottomBarManager extends BroadcastReceiver {
private static WeakReference<MediaPlayer> sMediaPlayerWeakRef;
@Override
public void onReceive(Context context, Intent intent) {
int clickedId = intent.getIntExtra(CustomTabsIntent.EXTRA_REMOTEVIEWS_CLICKED_ID, -1);
Toast.makeText(context, "Current URL " + intent.getDataString() + "\nClicked id "
+ clickedId, Toast.LENGTH_SHORT).show();
CustomTabsSession session = SessionHelper.getCurrentSession();
if (session == null) return;
if (clickedId == R.id.play_pause) {
MediaPlayer player = sMediaPlayerWeakRef.get();
if (player != null) {
boolean isPlaying = player.isPlaying();
if (isPlaying) player.pause();
else player.start();
// Update the play/stop icon to respect the current state.
session.setSecondaryToolbarViews(createRemoteViews(context, isPlaying),
getClickableIDs(), getOnClickPendingIntent(context));
}
} else if (clickedId == R.id.cover) {
// Clicking on the cover image will dismiss the bottom bar.
session.setSecondaryToolbarViews(null, null, null);
}
}
/**
* Creates a RemoteViews that will be shown as the bottom bar of the custom tab.
* @param showPlayIcon If true, a play icon will be shown, otherwise show a pause icon.
* @return The created RemoteViews instance.
*/
public static RemoteViews createRemoteViews(Context context, boolean showPlayIcon) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.remote_view);
int iconRes = showPlayIcon ? R.drawable.ic_play : R.drawable.ic_stop;
remoteViews.setImageViewResource(R.id.play_pause, iconRes);
return remoteViews;
}
/**
* @return A list of View ids, the onClick event of which is handled by Custom Tab.
*/
public static int[] getClickableIDs() {
return new int[]{R.id.play_pause, R.id.cover};
}
/**
* @return The PendingIntent that will be triggered when the user clicks on the Views listed by
* {@link BottomBarManager#getClickableIDs()}.
*/
public static PendingIntent getOnClickPendingIntent(Context context) {
Intent broadcastIntent = new Intent(context, BottomBarManager.class);
return PendingIntent.getBroadcast(context, 0, broadcastIntent, 0);
}
/**
* Sets the {@link MediaPlayer} to be used when the user clicks on the RemoteViews.
*/
public static void setMediaPlayer(MediaPlayer player) {
sMediaPlayerWeakRef = new WeakReference<>(player);
}
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.customtabsclient;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
/**
* A {@link BroadcastReceiver} that handles the callback if default menu items are chosen from
* Browser Actions.
*/
public class BrowserActionsReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String toastMsg = "Chosen item Id: " + intent.getDataString();
Toast.makeText(context, toastMsg, Toast.LENGTH_SHORT).show();
}
}
\ No newline at end of file
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.customtabsclient;
import android.support.annotation.Nullable;
import androidx.browser.customtabs.CustomTabsSession;
import java.lang.ref.WeakReference;
/**
* A class that keeps tracks of the current {@link CustomTabsSession} and helps other components of
* the app to get access to the current session.
*/
public class SessionHelper {
private static WeakReference<CustomTabsSession> sCurrentSession;
/**
* @return The current {@link CustomTabsSession} object.
*/
public static @Nullable CustomTabsSession getCurrentSession() {
return sCurrentSession == null ? null : sCurrentSession.get();
}
/**
* Sets the current session to the given one.
* @param session The current session.
*/
public static void setCurrentSession(CustomTabsSession session) {
sCurrentSession = new WeakReference<CustomTabsSession>(session);
}
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.customtabsclient.shared;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
/**
* Helper class for Custom Tabs.
*/
public class CustomTabsHelper {
private static final String TAG = "CustomTabsHelper";
static final String STABLE_PACKAGE = "com.android.chrome";
static final String BETA_PACKAGE = "com.chrome.beta";
static final String DEV_PACKAGE = "com.chrome.dev";
static final String LOCAL_PACKAGE = "com.google.android.apps.chrome";
private static final String EXTRA_CUSTOM_TABS_KEEP_ALIVE =
"android.support.customtabs.extra.KEEP_ALIVE";
private static final String ACTION_CUSTOM_TABS_CONNECTION =
"android.support.customtabs.action.CustomTabsService";
private static String sPackageNameToUse;
private CustomTabsHelper() {}
public static void addKeepAliveExtra(Context context, Intent intent) {
Intent keepAliveIntent = new Intent().setClassName(
context.getPackageName(), KeepAliveService.class.getCanonicalName());
intent.putExtra(EXTRA_CUSTOM_TABS_KEEP_ALIVE, keepAliveIntent);
}
/**
* Goes through all apps that handle VIEW intents and have a warmup service. Picks
* the one chosen by the user if there is one, otherwise makes a best effort to return a
* valid package name.
*
* This is <strong>not</strong> threadsafe.
*
* @param context {@link Context} to use for accessing {@link PackageManager}.
* @return The package name recommended to use for connecting to custom tabs related components.
*/
public static String getPackageNameToUse(Context context) {
if (sPackageNameToUse != null) return sPackageNameToUse;
PackageManager pm = context.getPackageManager();
// Get default VIEW intent handler.
Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
ResolveInfo defaultViewHandlerInfo = pm.resolveActivity(activityIntent, 0);
String defaultViewHandlerPackageName = null;
if (defaultViewHandlerInfo != null) {
defaultViewHandlerPackageName = defaultViewHandlerInfo.activityInfo.packageName;
}
// Get all apps that can handle VIEW intents.
List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(activityIntent, 0);
List<String> packagesSupportingCustomTabs = new ArrayList<>();
for (ResolveInfo info : resolvedActivityList) {
Intent serviceIntent = new Intent();
serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION);
serviceIntent.setPackage(info.activityInfo.packageName);
if (pm.resolveService(serviceIntent, 0) != null) {
packagesSupportingCustomTabs.add(info.activityInfo.packageName);
}
}
// Now packagesSupportingCustomTabs contains all apps that can handle both VIEW intents
// and service calls.
if (packagesSupportingCustomTabs.isEmpty()) {
sPackageNameToUse = null;
} else if (packagesSupportingCustomTabs.size() == 1) {
sPackageNameToUse = packagesSupportingCustomTabs.get(0);
} else if (!TextUtils.isEmpty(defaultViewHandlerPackageName)
&& !hasSpecializedHandlerIntents(context, activityIntent)
&& packagesSupportingCustomTabs.contains(defaultViewHandlerPackageName)) {
sPackageNameToUse = defaultViewHandlerPackageName;
} else if (packagesSupportingCustomTabs.contains(STABLE_PACKAGE)) {
sPackageNameToUse = STABLE_PACKAGE;
} else if (packagesSupportingCustomTabs.contains(BETA_PACKAGE)) {
sPackageNameToUse = BETA_PACKAGE;
} else if (packagesSupportingCustomTabs.contains(DEV_PACKAGE)) {
sPackageNameToUse = DEV_PACKAGE;
} else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) {
sPackageNameToUse = LOCAL_PACKAGE;
}
return sPackageNameToUse;
}
/**
* Used to check whether there is a specialized handler for a given intent.
* @param intent The intent to check with.
* @return Whether there is a specialized handler for the given intent.
*/
private static boolean hasSpecializedHandlerIntents(Context context, Intent intent) {
try {
PackageManager pm = context.getPackageManager();
List<ResolveInfo> handlers = pm.queryIntentActivities(
intent,
PackageManager.GET_RESOLVED_FILTER);
if (handlers == null || handlers.size() == 0) {
return false;
}
for (ResolveInfo resolveInfo : handlers) {
IntentFilter filter = resolveInfo.filter;
if (filter == null) continue;
if (filter.countDataAuthorities() == 0 || filter.countDataPaths() == 0) continue;
if (resolveInfo.activityInfo == null) continue;
return true;
}
} catch (RuntimeException e) {
Log.e(TAG, "Runtime exception while getting specialized handlers");
}
return false;
}
/**
* @return All possible chrome package names that provide custom tabs feature.
*/
public static String[] getPackages() {
return new String[]{"", STABLE_PACKAGE, BETA_PACKAGE, DEV_PACKAGE, LOCAL_PACKAGE};
}
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.customtabsclient.shared;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
/**
* Empty service used by the custom tab to bind to, raising the application's importance.
*/
public class KeepAliveService extends Service {
private static final Binder sBinder = new Binder();
@Override
public IBinder onBind(Intent intent) {
return sBinder;
}
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.customtabsclient.shared;
import android.content.ComponentName;
import androidx.browser.customtabs.CustomTabsClient;
import androidx.browser.customtabs.CustomTabsServiceConnection;
import java.lang.ref.WeakReference;
/**
* Implementation for the CustomTabsServiceConnection that avoids leaking the
* ServiceConnectionCallback
*/
public class ServiceConnection extends CustomTabsServiceConnection {
// A weak reference to the ServiceConnectionCallback to avoid leaking it.
private WeakReference<ServiceConnectionCallback> mConnectionCallback;
public ServiceConnection(ServiceConnectionCallback connectionCallback) {
mConnectionCallback = new WeakReference<>(connectionCallback);
}
@Override
public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
ServiceConnectionCallback connectionCallback = mConnectionCallback.get();
if (connectionCallback != null) connectionCallback.onServiceConnected(client);
}
@Override
public void onServiceDisconnected(ComponentName name) {
ServiceConnectionCallback connectionCallback = mConnectionCallback.get();
if (connectionCallback != null) connectionCallback.onServiceDisconnected();
}
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.customtabsclient.shared;
import androidx.browser.customtabs.CustomTabsClient;
/**
* Callback for events when connecting and disconnecting from Custom Tabs Service.
*/
public interface ServiceConnectionCallback {
/**
* Called when the service is connected.
* @param client a CustomTabsClient
*/
void onServiceConnected(CustomTabsClient client);
/**
* Called when the service is disconnected.
*/
void onServiceDisconnected();
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2015 Google Inc. All Rights Reserved.
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.
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="-100%p" android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
</set>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2015 Google Inc. All Rights Reserved.
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.
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%p" android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
</set>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2015 Google Inc. All Rights Reserved.
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.
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="-100%p"
android:duration="@android:integer/config_mediumAnimTime"/>
</set>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2015 Google Inc. All Rights Reserved.
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.
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="100%p"
android:duration="@android:integer/config_mediumAnimTime"/>
</set>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2015 Google Inc. All Rights Reserved.
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.
-->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:padding="5dp"
android:orientation="vertical" >
<EditText
android:id="@+id/edit"
android:padding="5dp"
android:layout_margin="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/url_hint"
android:inputType="textNoSuggestions"
android:text="@string/default_url" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:text="@string/package_label"/>
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/spinner"
android:layout_margin="3dp"
android:layout_gravity="center_horizontal" />
</LinearLayout>
<Space
android:layout_width="match_parent"
android:layout_height="5dp" />
<Button
android:id="@+id/connect_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:textAllCaps="false"
android:text="@string/connect_button_text"
android:enabled="true" />
<Button
android:id="@+id/warmup_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:textAllCaps="false"
android:text="@string/warmup_button_text"
android:enabled="false" />
<Button
android:id="@+id/may_launch_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:textAllCaps="false"
android:text="@string/may_launch_button_text"
android:enabled="false" />
<Button
android:id="@+id/launch_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:textAllCaps="false"
android:text="@string/launch_button_text"
android:enabled="true" />
<Button
android:id="@+id/launch_browser_actions_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:textAllCaps="false"
android:text="@string/launch_browser_actions_button_text" />
<Button
android:id="@+id/register_twa_service"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:textAllCaps="false"
android:text="@string/register_twa_service" />
</LinearLayout>
</ScrollView>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="56dp"
android:orientation="horizontal"
android:background="@android:color/white">
<android.widget.ImageView
android:id="@+id/cover"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="4dp"
android:scaleType="centerCrop"
android:src="@drawable/cover"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:padding="4dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/amazing_grace"
android:paddingTop="2dp"
android:textSize="16sp"
android:textColor="@android:color/black"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="2dp"
android:text="@string/artist"
android:textSize="12sp"
android:textColor="#666666"/>
</LinearLayout>
<android.widget.ImageView
android:id="@+id/play_pause"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:layout_marginEnd="8dp"
android:src="@drawable/ic_play"/>
</LinearLayout>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2015 Google Inc. All Rights Reserved.
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.
-->
<resources>
<string name="app_name">Chrome Custom Tabs Example</string>
<string name="url_hint">Please type the url here.</string>
<string name="warmup_button_text">Warmup Chrome</string>
<string name="may_launch_button_text">May Launch URL</string>
<string name="launch_button_text">Launch URL in a Chrome Custom Tab</string>
<string name="connect_button_text">Connect to the service</string>
<string name="launch_browser_actions_button_text">Launch URL in Browser Actions Context Menu</string>
<string name="register_twa_service">Register TrustedWebActivityService</string>
<string name="default_url">https://www.google.com</string>
<string name="package_label">Package:</string>
<string name="amazing_grace">Amazing Grace 2011</string>
<string name="artist">Kevin MacLeod</string>
</resources>
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/android/rules.gni")
android_resources("chrome_tabs_client_example_apk_resources") {
sources = [
"src/Application/src/main/res/anim/slide_in_left.xml",
"src/Application/src/main/res/anim/slide_in_right.xml",
"src/Application/src/main/res/anim/slide_out_left.xml",
"src/Application/src/main/res/anim/slide_out_right.xml",
"src/Application/src/main/res/drawable-hdpi/ic_arrow_back.png",
"src/Application/src/main/res/drawable-hdpi/ic_launcher.png",
"src/Application/src/main/res/drawable-hdpi/ic_notification_icon.png",
"src/Application/src/main/res/drawable-hdpi/ic_play.png",
"src/Application/src/main/res/drawable-hdpi/ic_share.png",
"src/Application/src/main/res/drawable-hdpi/ic_stop.png",
"src/Application/src/main/res/drawable-mdpi/ic_arrow_back.png",
"src/Application/src/main/res/drawable-mdpi/ic_launcher.png",
"src/Application/src/main/res/drawable-mdpi/ic_notification_icon.png",
"src/Application/src/main/res/drawable-mdpi/ic_play.png",
"src/Application/src/main/res/drawable-mdpi/ic_share.png",
"src/Application/src/main/res/drawable-mdpi/ic_stop.png",
"src/Application/src/main/res/drawable-xhdpi/ic_arrow_back.png",
"src/Application/src/main/res/drawable-xhdpi/ic_launcher.png",
"src/Application/src/main/res/drawable-xhdpi/ic_notification_icon.png",
"src/Application/src/main/res/drawable-xhdpi/ic_play.png",
"src/Application/src/main/res/drawable-xhdpi/ic_share.png",
"src/Application/src/main/res/drawable-xhdpi/ic_stop.png",
"src/Application/src/main/res/drawable-xxhdpi/cover.jpg",
"src/Application/src/main/res/drawable-xxhdpi/ic_arrow_back.png",
"src/Application/src/main/res/drawable-xxhdpi/ic_launcher.png",
"src/Application/src/main/res/drawable-xxhdpi/ic_notification_icon.png",
"src/Application/src/main/res/drawable-xxhdpi/ic_play.png",
"src/Application/src/main/res/drawable-xxhdpi/ic_share.png",
"src/Application/src/main/res/drawable-xxhdpi/ic_stop.png",
"src/Application/src/main/res/drawable-xxxhdpi/ic_arrow_back.png",
"src/Application/src/main/res/drawable-xxxhdpi/ic_launcher.png",
"src/Application/src/main/res/drawable-xxxhdpi/ic_share.png",
"src/Application/src/main/res/layout/main.xml",
"src/Application/src/main/res/layout/remote_view.xml",
"src/Application/src/main/res/raw/amazing_grace.mp3",
"src/Application/src/main/res/values/strings.xml",
]
android_manifest = "src/Application/src/main/AndroidManifest.xml"
custom_package = "org.chromium.customtabsclient"
deps = [ "//third_party/android_deps:android_support_v7_appcompat_java" ]
}
android_resources("custom_tabs_support_resources") {
sources = [
"src/customtabs/res/layout/browser_actions_context_menu_page.xml",
"src/customtabs/res/layout/browser_actions_context_menu_row.xml",
"src/customtabs/res/values/colors.xml",
"src/customtabs/res/values/dimens.xml",
"src/customtabs/res/values/strings.xml",
"src/customtabs/res/xml/image_share_filepaths.xml",
]
android_manifest = "src/customtabs/AndroidManifest.xml"
custom_package = "android.support.customtabs"
}
android_apk("custom_tabs_client_example_apk") {
skip_jetify = true
sources = [
"src/Application/src/main/java/org/chromium/customtabsclient/BottomBarManager.java",
"src/Application/src/main/java/org/chromium/customtabsclient/BrowserActionsReceiver.java",
"src/Application/src/main/java/org/chromium/customtabsclient/MainActivity.java",
"src/Application/src/main/java/org/chromium/customtabsclient/SessionHelper.java",
]
android_manifest = "src/Application/src/main/AndroidManifest.xml"
min_sdk_version = 16
target_sdk_version = 21
apk_name = "CustomTabsClientExample"
deps = [
":chrome_tabs_client_example_apk_resources",
":custom_tabs_client_shared_java",
":custom_tabs_support_java",
"//third_party/android_deps:android_arch_lifecycle_common_java",
"//third_party/android_deps:android_support_v7_appcompat_java",
"//third_party/android_deps:com_android_support_appcompat_v7_java",
"//third_party/android_deps:com_android_support_support_annotations_java",
]
chromium_code = false
}
android_library("custom_tabs_client_shared_java") {
skip_jetify = true
sources = [
"src/shared/src/main/java/org/chromium/customtabsclient/shared/CustomTabsHelper.java",
"src/shared/src/main/java/org/chromium/customtabsclient/shared/KeepAliveService.java",
"src/shared/src/main/java/org/chromium/customtabsclient/shared/ServiceConnection.java",
"src/shared/src/main/java/org/chromium/customtabsclient/shared/ServiceConnectionCallback.java",
]
deps = [ ":custom_tabs_support_java" ]
chromium_code = false
}
android_library("custom_tabs_support_java") {
skip_jetify = true
sources = [
"src/customtabs/src/android/support/customtabs/CustomTabColorSchemeParams.java",
"src/customtabs/src/android/support/customtabs/CustomTabsCallback.java",
"src/customtabs/src/android/support/customtabs/CustomTabsClient.java",
"src/customtabs/src/android/support/customtabs/CustomTabsIntent.java",
"src/customtabs/src/android/support/customtabs/CustomTabsService.java",
"src/customtabs/src/android/support/customtabs/CustomTabsServiceConnection.java",
"src/customtabs/src/android/support/customtabs/CustomTabsSession.java",
"src/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java",
"src/customtabs/src/android/support/customtabs/PostMessageBackend.java",
"src/customtabs/src/android/support/customtabs/PostMessageService.java",
"src/customtabs/src/android/support/customtabs/PostMessageServiceConnection.java",
"src/customtabs/src/android/support/customtabs/TrustedWebUtils.java",
"src/customtabs/src/android/support/customtabs/browseractions/BrowserActionItem.java",
"src/customtabs/src/android/support/customtabs/browseractions/BrowserActionsFallbackMenuAdapter.java",
"src/customtabs/src/android/support/customtabs/browseractions/BrowserActionsFallbackMenuDialog.java",
"src/customtabs/src/android/support/customtabs/browseractions/BrowserActionsFallbackMenuUi.java",
"src/customtabs/src/android/support/customtabs/browseractions/BrowserActionsFallbackMenuView.java",
"src/customtabs/src/android/support/customtabs/browseractions/BrowserActionsIntent.java",
"src/customtabs/src/android/support/customtabs/browseractions/BrowserServiceFileProvider.java",
"src/customtabs/src/android/support/customtabs/browseractions/BrowserServiceImageReadTask.java",
"src/customtabs/src/android/support/customtabs/trusted/TrustedWebActivityBuilder.java",
"src/customtabs/src/android/support/customtabs/trusted/TrustedWebActivityService.java",
"src/customtabs/src/android/support/customtabs/trusted/TrustedWebActivityServiceConnectionManager.java",
"src/customtabs/src/android/support/customtabs/trusted/TrustedWebActivityServiceWrapper.java",
]
deps = [
":custom_tabs_support_resources",
# TODO (bjoyce): Restore to android_support_v7_appcompat_java once source
# files are manually written to androidx crbug.com/1047843.
# "//third_party/android_deps:android_support_v7_appcompat_java",
# Remove _temp target once upstream is compatible.
"//third_party/android_deps:com_android_support_appcompat_v7_java_temp",
"//third_party/android_deps:com_android_support_collections_java_orig",
"//third_party/android_deps:com_android_support_interpolator_java",
"//third_party/android_deps:com_android_support_support_annotations_java",
"//third_party/android_deps:com_android_support_support_compat_java",
]
srcjar_deps = [ ":chrome_custom_tabs_service_aidl" ]
android_manifest_for_lint = "src/customtabs/AndroidManifest.xml"
chromium_code = false
}
android_aidl("chrome_custom_tabs_service_aidl") {
interface_file = "common.aidl"
java_in_dir = "src/customtabs/src/android/support/customtabs"
sources = [
"$java_in_dir/ICustomTabsCallback.aidl",
"$java_in_dir/ICustomTabsService.aidl",
"$java_in_dir/IPostMessageService.aidl",
"$java_in_dir/trusted/ITrustedWebActivityService.aidl",
]
}
This diff is collapsed.
lizeb@chromium.org
peconn@chromium.org
yusufo@chromium.org
per-file *.aidl=set noparent
per-file *.aidl=file://ipc/SECURITY_OWNERS
# COMPONENT: UI>Browser>Mobile>CustomTabs
Name: Chrome Custom Tabs - Example and Usage
Short Name: Chrome Custom Tabs Client
URL: https://chromium.googlesource.com/external/github.com/GoogleChrome/custom-tabs-client
Version: unknown
License: Apache 2.0
Security Critical: yes
License Android Compatible: yes
Description:
This presents an example application using Chrome Custom Tabs, and a possible
usage of both the intent and the background service APIs. It covers UI
customization, callback setup, pre-warming and pre-fetching, and lifecycle
management. Also inside demos there is another application that launches
custom tabs in different modes.
The example applicaton also presents how to use Browser Actions, including
creating request intent and adding custom items.
The actual code that Chromium builds from is in
//third_party/android_sdk/androidx_browser, this subdirectory is kept around
for the example app (the custom_tabs_client_example_apk target).
TODO(peconn): Get rid of src/customtabs and depend instead on
androidx_browser.
Local Modifications: None
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
interface android.support.customtabs.ICustomTabsService;
interface android.support.customtabs.ICustomTabsCallback;
interface android.support.customtabs.IPostMessageService;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment