Chrome Custom Tabs for Android
+Getting Started
+Using a Chrome Custom tab you can style and control Chrome to fit in with your brand. +
+diff --git a/README.md b/README.md index 4ee7a96..fb9c483 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,7 @@ This is the source of the official [Chrome Multi-Device documentation](https://d 2. Open [http://localhost:8000/_preview.html](http://localhost:8000/_preview.html) 3. You will see the boilerplate with the index.html file already included 4. To preview another document, add a url paramater with the filename - * Something like: [http://localhost:8000/_preview.html?data-compression.html](http://localhost:8000/_preview.html?data-compression.html) - * Or: [http://localhost:8888/_preview.html?webview/gettingstarted.html](http://localhost:8888/_preview.html?webview/gettingstarted.html) + * Something like: [http://localhost:8000/_preview.html?webview/gettingstarted.html](http://localhost:8000/_preview.html?webview/gettingstarted.html) * Things mostly work but is not exactly the same as viewing through DCC. ### Deployment diff --git a/_preview.html b/_preview.html index 1fe35cb..0d4609b 100755 --- a/_preview.html +++ b/_preview.html @@ -169,7 +169,7 @@
@@ -401,7 +401,7 @@Last updated by Paul Kinlan: Friday May 6, 2016.
+ +App developers face a choice when a user taps a URL to either launch a +browser, or build their own in-app browser using WebViews.
+ +Both options present challenges — launching the browser is a heavy context +switch that isn't customizable, while WebViews don't share state with the +browser and add maintenance overhead.
+ +Chrome Custom Tabs give apps more control over their web experience, and make +transitions between native and web content more seamless without having to +resort to a WebView.
+ +Chrome Custom Tabs allow an app to customize how Chrome looks and feels. An app +can change things like:
+ +Chrome Custom Tabs also allow the developer to pre-start Chrome and pre-fetch +content for faster loading.
+ +
+
++You can test this now with our +sample on Github. +
+ +The WebView is good solution if you are hosting your own content inside your +app. If your app directs people to URLs outside your domain, we recommend +that you use Chrome Custom Tabs for these reasons:
+ +As of Chrome 45, Chrome Custom Tabs is now generally available to all users of +Chrome, + on all of Chrome's supported Android versions (Jellybean onwards).
+ +We are looking for feedback, questions and suggestions on this project, +so we encourage you to file issues on +crbug.com and ask questions to our Twitter account +@ChromiumDev.
+ +A complete example is available at +https://github.com/GoogleChrome/custom-tabs-client. +It contains re-usable classes to customize the UI, +connect to the background service, and handle the lifecycle of both the application and the custom tab activity. + +
If you follow the guidance from this page, +you will be able to create a great integration.
+ +The first step for a Custom Tabs integration is adding the Custom Tabs Support Library to your project. Open your build.gradle file and add the support library to the dependency section.
+dependencies {
+ ...
+ compile 'com.android.support:customtabs:23.3.0'
+}
+
+
+Once the Support Library is added to your project there are two sets of possible customizations:
+The UI Customizations are done by using the CustomTabsIntent and the CustomTabsIntent.Builder classes;
+the performance improvements are achieved by using the CustomTabsClient to connect to the Custom Tabs service, warm-up Chrome and let it know which urls will be opened.
+// Use a CustomTabsIntent.Builder to configure CustomTabsIntent. +// Once ready, call CustomTabsIntent.Builder.build() to create a CustomTabsIntent +// and launch the desired Url with CustomTabsIntent.launchUrl() + +String url = ¨https://paul.kinlan.me/¨; +CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); +CustomTabsIntent customTabsIntent = builder.build(); +customTabsIntent.launchUrl(this, Uri.parse(url)); ++ +
One of the most important (and simplest to implement) aspects of Chrome Custom +Tabs is the ability for you to change the color of the address bar to be +consistent with your app's theme. +
+ ++// Changes the background color for the omnibox. colorInt is an int +// that specifies a Color. + +builder.setToolbarColor(colorInt); ++ +
+
+As the developer of your app, you have full control over the Action Button + that is presented to your users inside the Chrome tab.
+ +In most cases, this will be a primary action such as Share, or another common +activity that your users will perform.
+ +The Action Button is represented as a Bundle with an icon of the action button +and a pendingIntent that will be called by Chrome when your user hits the action +button. The icon is currenlty 24dp in height and 24-48 dp in width.
+ ++// Adds an Action Button to the Toolbar. +// 'icon' is a Bitmap to be used as the image source for the +// action button. + +// 'description' is a String be used as an accessible description for the button. + +// 'pendingIntent is a PendingIntent to launch when the action button +// or menu item was tapped. Chrome will be calling PendingIntent#send() on +// taps after adding the url as data. The client app can call +// Intent#getDataString() to get the url. + +// 'tint' is a boolean that defines if the Action Button should be tinted. + +builder.setActionButton(icon, description, pendingIntent, tint);+ +
+The Chrome browser has a comprehensive menu of actions that users will perform +frequently inside a browser, however they may not be relevant to your +application context.
+ +Chrome Custom Tabs will have a three icon row with "Forward", "Page Info" and +"Refresh" on top at all times, with "Find page" and "Open in Browser" on the +footer of the menu.
+ +As the developer, you can add and customize up to five menu items that will appear +between the icon row and foot items.
+ +The menu item is added by calling CustomTabsIntent.Builder#addMenuItem with title and a pendingIntent that Chrome will call on your behalf when the user taps the item are passed as parameters.
+builder.addMenuItem(menuItemTitle, menuItemPendingIntent); ++ +
Many Android applications use custom View Entrance and Exit animations when +transition between Activities on Android. Chrome Custom Tabs is no different, +you can change the entrance and exit (when the user presses Back) animations to +keep them consistent with the rest of your application.
+ ++builder.setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left); +builder.setExitAnimations(this, R.anim.slide_in_left, R.anim.slide_out_right); ++ +
By default, when CustomTabsIntent#launchUrl is called, it will spin up Chrome and launch the URL. This can take up
+precious time and impact on the perception of smoothness.
We believe that users demand a near instantaneous experience, so we have +provided a Service in Chrome that your app can connect to and tell Chrome to +warm up the browser and the native components. We are also experimenting with +the ability for you, the developer to tell Chrome the likely set of web pages +the user will visit. Chrome will then be able to perform:
+ +The process for warming up Chrome is as follows:
+CustomTabsClient#bindCustomTabsService to connect to the service.CustomTabsClient#warmup to start Chrome behind the scenes.CustomTabsClient#newSession to create a new session. This session is used for all requests to the API.CustomTabsCallback as a parameter when creating a new session, so that you know a page
+ was loaded.CustomTabsSession#mayLaunchUrl.CustomTabsIntent.Builder constructor passing the created CustomTabsSession as a parameter.The CustomTabsClient#bindCustomTabsService method takes away the complexity of
+connecting to the Custom Tabs service.
Create a class that extends CustomTabsServiceConnection and use onCustomTabsServiceConnected
+to get an instance of the CustomTabsClient. This instance will be needed on the next steps.
+// Package name for the Chrome channel the client wants to connect to. This
+// depends on the channel name.
+// Stable = com.android.chrome
+// Beta = com.chrome.beta
+// Dev = com.chrome.dev
+public static final String CUSTOM_TAB_PACKAGE_NAME = "com.android.chrome"; // Change when in stable
+
+CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
+ @Override
+ public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
+ mCustomTabsClient = client;
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+
+ }
+};
+boolean ok = CustomTabsClient.bindCustomTabsService(this, mPackageNameToBind, connection);
+
+
+boolean warmup(long flags)
+
+Warms up the browser process and loads the native libraries. Warmup is + asynchronous, the return value indicates whether the request has been + accepted. Multiple successful calls will also return true. +
+ +Returns true for success.
boolean newSession(CustomTabsCallback callback)
+
+Session is used in subsequent calls to link mayLaunchUrl call, + the CustomTabsIntent and the tab generated to each other. The callback + provided here is associated with the created session. Any updates for the created + session (see Custom Tabs Callback below) is also received through this + callback. Returns whether a session was created successfully. Multiple + calls with the same CustomTabsCallback or a null value will return false. +
+ +boolean mayLaunchUrl(Uri url, Bundle extras, List otherLikelyBundles)
+
+This CustomTabsSession method tells the browser of a likely future navigation to a URL.
+ The method warmup() should be called first as a best practice. 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. Returns whether the
+ operation completed successfully.
void onNavigationEvent(int navigationEvent, Bundle extras)
+
+Will be called when a navigation event happens in the custom tab. The `navigationEvent int` +is one of 6 values that defines the state of the the page is in. See below for more information.
+ ++/** +* 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; ++ +
Custom Tabs uses an ACTION_VIEW Intent with key Extras to customize the UI. +This means that by default the page willopen in the system browser, or the user's default browser.
+ +If the user has Chrome installed and it is the default browser, it will +automatically pick up the EXTRAS and present a customized UI. It is also +possible for another browser to use the Intent extras to provide a similar +customized interface.
+ +All versions of Chrome supporting Chrome Custom Tabs expose a service. +To check whether Chrome supports custom tabs, try to bind to the service. If it succeeds, +then custom tabs can safely be used. +
+ +Since Chrome Custom Tabs was launched, we've seen various implementations + with different levels of quality. This section describes a set of best + practices we've found to create a good integration.
+ +You can save up to 700 ms when opening a link with the + Custom Tabs by connecting to the service and pre-loading Chrome.
+ +Connect to the Custom Tabs service on the + onStart() + method of the Activities you plan to launch a Custom Tab from. Upon connection, + call warmup().
+ +The loading happens as a low priority process, meaning that it won’t + have any negative performance impact on your application, but will + give a big performance boost when loading a link.
+ +Pre-rendering will make external content open instantly. So, as if your user + has at least a 50% likelihood of clicking on the link, call + the mayLaunchUrl() method.
+ +Calling mayLaunchUrl() will make + Custom Tabs pre-fetch the main page with the supporting content and + pre-render. This will give the maximum speed up to the page loading process, + but comes with a network and battery cost.
+ +Custom Tabs is smart and knows if the user is using the phone on a metered + network or if it’s a low end device and pre-rendering will have a negative + effect on the overall performance of the device and won’t pre-fetch or + pre-render on those scenarios. So, there’s no need to optimize your + application for those cases.
+ +Although Custom Tabs is available for the great majority of users, there + are some scenarios where a browser that supports Custom Tabs is not + installed on the device or the device does not support a browser version + that has Custom Tabs enabled.
+ +Make sure to provide a fallback that provides a good user experience + by either opening the default browser or using your own + WebView + implementation.
+ +It's usually very important for websites to track where their traffic is coming from. Make sure you let them know you are sending them users by setting the referrer when launching your Custom Tab
++intent.putExtra(Intent.EXTRA_REFERRER, + Uri.parse(Intent.URI_ANDROID_APP_SCHEME + "//" + context.getPackageName())); ++ +
Custom animations will make the transition from your application to the + web content smoother. Make sure the finish animation is the reverse of the + start animation, as it will help the user understand she’s returning to the + content where the navigation started.
+ +
+ //Setting custom enter/exit animations
+ CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder();
+ intentBuilder.setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left);
+ intentBuilder.setExitAnimations(this, android.R.anim.slide_in_left,
+ android.R.anim.slide_out_right);
+
+ //Open the Custom Tab
+ intentBuilder.build().launchUrl(context, Uri.parse("https://developer.chrome.com/"));
+
+
+Adding an Action Button will make users engage more with your app features. + But, if there isn’t a good icon to represent the action your Action Button + will perform, create a bitmap with a text describing the action.
+ +Remember the maximum size for the bitmap is 24dp height x 48dp width.
+ ++ String shareLabel = getString(R.string.label_action_share); + Bitmap icon = BitmapFactory.decodeResource(getResources(), + android.R.drawable.ic_menu_share); + + //Create a PendingIntent to your BroadCastReceiver implementation + Intent actionIntent = new Intent( + this.getApplicationContext(), ShareBroadcastReceiver.class); + PendingIntent pendingIntent = + PendingIntent.getBroadcast(getApplicationContext(), 0, actionIntent, 0); + + //Set the pendingIntent as the action to be performed when the button is clicked. + intentBuilder.setActionButton(icon, shareLabel, pendingIntent); ++ +
Remember the user may have more than one browser installed that supports + Custom Tabs. If there's more than one browser that supports Custom Tabs and + none if them is the preferred browser, ask the user how she wants to open + the link
+ ++ /** + * Returns a list of packages that support Custom Tabs. + */ + public static ArrayList+ +getCustomTabsPackages(Context context) { + PackageManager pm = context.getPackageManager(); + // Get default VIEW intent handler. + Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com")); + + // Get all apps that can handle VIEW intents. + List resolvedActivityList = pm.queryIntentActivities(activityIntent, 0); + ArrayList packagesSupportingCustomTabs = new ArrayList<>(); + for (ResolveInfo info : resolvedActivityList) { + Intent serviceIntent = new Intent(); + serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION); + serviceIntent.setPackage(info.activityInfo.packageName); + // Check if this package also resolves the Custom Tabs service. + if (pm.resolveService(serviceIntent, 0) != null) { + packagesSupportingCustomTabs.add(info); + } + } + return packagesSupportingCustomTabs; + } +
Add an option into the application for the user to open links in the default + browser instead of using a Custom Tab. This is specially important if the + application opened the link using the browser before adding support for + Custom Tabs.
+ +Some URLs can be handled by native applications. If the user has the Twitter + app installed and clicks on a link to a tweet. She expects that the Twitter + application will handle it.
+ +Before opening an url from your application, check if a native alternative + is available and use it.
+ +Customize with your application's primary color if you want the user to feel + that the content is a part of your application.
+ +If you want to make it clear for the user that she has left your application, + don’t customize the color at all.
+ ++ //Setting a custom toolbar color + CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder(); + intentBuilder.setToolbarColor(Color.BLUE); ++ +
Make sure you add the Share Action to the overflow menu, as users expect to + be able to share the link to the content they are seeing in most use cases, + and Custom Tabs doesn’t add one by default.
+ +
+ //Sharing content from CustomTabs with on a BroadcastReceiver
+ public void onReceive(Context context, Intent intent) {
+ String url = intent.getDataString();
+
+ if (url != null) {
+ Intent shareIntent = new Intent(Intent.ACTION_SEND);
+ shareIntent.setType("text/plain");
+ shareIntent.putExtra(Intent.EXTRA_TEXT, url);
+
+ Intent chooserIntent = Intent.createChooser(shareIntent, "Share url");
+ chooserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ context.startActivity(chooserIntent);
+ }
+ }
+
+
+Customize the close button to make the Custom Tab feel it is part of your + application.
+ +If you want the user to feel like Custom Tabs is a modal dialog, use the + default “X” button. If you want the user to feel the Custom Tab is part of + the application flow, use the back arrow.
+ ++ //Setting a custom back button + CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder(); + intentBuilder.setCloseButtonIcon(BitmapFactory.decodeResource( + getResources(), R.drawable.ic_arrow_back)); ++ +
When intercepting clicks on links generated by + android:autoLink + or overriding clicks on links on WebViews, make sure that your application + handles the internal links and let's Custom Tabs handle the external + ones.
+ +
+WebView webView = (WebView)findViewById(R.id.webview);
+webView.setWebViewClient(new WebViewClient() {
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ return true;
+ }
+
+ @Override
+ public void onLoadResource(WebView view, String url) {
+ if (url.startsWith("http://www.example.com")) {
+ //Handle Internal Link...
+ } else {
+ //Open Link in a Custom Tab
+ Uri uri = Uri.parse(url);
+ CustomTabsIntent.Builder intentBuilder =
+ new CustomTabsIntent.Builder(mCustomTabActivityHelper.getSession());
+ //Open the Custom Tab
+ intentBuilder.build().launchUrl(context, url));
+ }
+ }
+});
+
+
+If you need to do any processing between the user clicking on a link and + opening the Custom Tab, make sure it runs in under 100ms. Otherwise people + will see the unresponsiveness and may try to click multiple times on the + link.
+ +If it's not possible to avoid the delay, make sure you application is + prepared for when a user clicks multiple times on the same link and does not + open a Custom Tab multiple times.
+ +Although the recommended method to integrate your application with Custom Tabs is using the Custom Tabs Support Library, a low level implementation is also available.
+ +The complete implementation of the Support Library is available on Github and an be used as a start point. It also contains the AIDL files required to connect to the service, as the ones contained in the Chromium repository are not directly usable with Android Studio.
+ ++// Using a VIEW intent for compatibility with any other browsers on device. +// Caller should not be setting FLAG_ACTIVITY_NEW_TASK or +// FLAG_ACTIVITY_NEW_DOCUMENT. +String url = ¨https://paul.kinlan.me/¨; +Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); +// Must have. Extra used to match the session. Its value is an IBinder passed +// whilst creating a news session. See newSession() below. Even if the service is not +// used and there is no valid session id to be provided, this extra has to be present +// with a null value to launch a custom tab. + +private static final String EXTRA_CUSTOM_TABS_SESSION = "android.support.customtabs.extra.SESSION"; +Bundle extras = new Bundle; +extras.putBinder(EXTRA_CUSTOM_TABS_SESSION, + sessionICustomTabsCallback.asBinder() /* Set to null for no session */); +intent.putExtras(extras); ++ +
UI Customizations are included by adding Extras to the ACTION_VIEW Intent. A full list of the +extras keys used to customise the UI can be found on the CustomTabsIntent docs. An example on how to add a custom toolbar color follows:
+ ++// Extra that changes the background color for the omnibox. colorInt is an int +// that specifies a Color. + +private static final String EXTRA_CUSTOM_TABS_TOOLBAR_COLOR = "android.support.customtabs.extra.TOOLBAR_COLOR"; +intent.putExtra(EXTRA_CUSTOM_TABS_TOOLBAR_COLOR, colorInt); ++ +
The Custom Tabs service can be used in the same way other Android Services are. The interface is created with AIDL and automatically creates a proxy service class for you.
+ +Use the methods on the proxy service to warm-up, create sessions and pre-fetch
+ ++// Package name for the Chrome channel the client wants to connect to. This +// depends on the channel name. +// Stable = com.android.chrome +// Beta = com.chrome.beta +// Dev = com.chrome.dev +public static final String CUSTOM_TAB_PACKAGE_NAME = "com.chrome.dev"; // Change when in stable + +// Action to add to the service intent. This action can be used as a way +// generically pick apps that handle custom tabs for both activity and service +// side implementations. +public static final String ACTION_CUSTOM_TABS_CONNECTION = + "android.support.customtabs.action.CustomTabsService"; +Intent serviceIntent = new Intent(ACTION_CUSTOM_TABS_CONNECTION); + +serviceIntent.setPackage(CUSTOM_TAB_PACKAGE_NAME); +context.bindService(serviceIntent, mServiceConnection, + Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY); ++
-Since Chrome M31, -you can set up your web app to have an application shortcut icon added to a device's homescreen, -and have the app launch in full-screen "app mode" using Chrome for Android’s "Add to homescreen" menu item.
- -New in Chrome M39, you can define the metadata associated with your web application -in a JSON-based manifest. -The manifest provides a way to wrap metadata about a web application into a single file. -Using this metadata in conjunction with Add to Homescreen, -you can create launch experiences more comparable to native applications.
- -Homescreen-installed apps work exactly like you would expect a normal web application to work. -They follow the same sandboxed security policies and have access to the same APIs; -however, they integrate with the Android environment in the following ways.
-Installs directly to the homescreen
-When a user clicks "Add to homescreen", they will see the app being added on the homescreen.
-
- Integrates into the OS task-switcher
-Web apps launched from the homescreen will appear in the task switcher separate from the browser, they will, however still say "Web App" on the app title.
-
- Provides a full screen experience
-Web apps will launch full-screen with no vestiges of a browser. The URL will not be present, nor will traditional browser actions such as bookmarking and navigation controls.
-
- Supports a default device orientation
-Web apps will launch and stay in the designated orientation, for example, landscape.
-Navigating to external pages from a web app highlights them to the user
-Users will always know if the app routes them to a location outside the application’s domain. This is especially useful for authentication flows, the user is kept in the app experience but the URL of the authentication system is clearly visible to the user.
-
- Developers seeking to enable "add to homescreen" should link to a manifest -and define the manifest metadata.
- -To associate the manifest with your website, -include the link element in your web page -(for example, index.html):
- -<link rel="manifest" href="manifest.json">- -
The manifest metadata can define a title, landing page, default orientation, -and different icons depending on size and screen density. -The display represents how developers would like the user agent -to present the web application to a user (for example, in fullscreen). -
- -For example, this
-manifest
-includes a title ("Web Application Manifest Sample"),
-different icons to support a range of devices,
-a start page (index.html),
-and the default orientation ("landscape").
-
display property is "standalone".
-The web app has the look and feel of a standalone native application.
-This can include the application having a different window,
-its own icon in the application launcher, etc.
-In this mode, the user agent will exclude UI elements for controlling navigation,
-but can include other UI elements such as a status bar.
-
-
-
-{
- "name": "Web Application Manifest Sample",
- "icons": [
- {
- "src": "launcher-icon-0-75x.png",
- "sizes": "36x36",
- "type": "image/png",
- "density": "0.75"
- },
- {
- "src": "launcher-icon-1x.png",
- "sizes": "48x48",
- "type": "image/png",
- "density": "1.0"
- },
- {
- "src": "launcher-icon-1-5x.png",
- "sizes": "72x72",
- "type": "image/png",
- "density": "1.5"
- },
- {
- "src": "launcher-icon-2x.png",
- "sizes": "96x96",
- "type": "image/png",
- "density": "2.0"
- },
- {
- "src": "launcher-icon-3x.png",
- "sizes": "144x144",
- "type": "image/png",
- "density": "3.0"
- },
- {
- "src": "launcher-icon-4x.png",
- "sizes": "192x192",
- "type": "image/png",
- "density": "4.0"
- }
- ],
- "start_url": "index.html",
- "display": "standalone",
- "orientation": "landscape"
-}
-
-
-Since M31,
-Chrome will look for the following meta tag in the <head> element of the web-page
-(if there's a manifest with display specified, this is ignored):
<meta name="mobile-web-app-capable" content="yes">- -
The name attribute MUST be "mobile-web-app-capable" and the content attribute must be "yes" (case in-sensitive). -If there is any other value in the content attribute the web app will be added as a regular bookmark.
- --
- -The icon that is used to install to the homescreen is determined by using the largest icon found in one of the following <link> tags:
<link rel="icon" sizes="192x192" href="nice-highres.png"> (recommended)<link rel="icon" sizes="128x128" href="niceicon.png"><link rel="apple-touch-icon" sizes="128x128" href="niceicon.png"><link rel="apple-touch-icon-precomposed" sizes="128x128" href="niceicon.png">The application’s <title> element serves as the default label for the icon on the homescreen.
The following example is the minimum required configuration -to support a homescreen launch experience before Chrome 39.
- --<!doctype html> -<html> - <head> - <title>Awesome app </title> - <meta name="viewport" content="width=device-width"> - <meta name="mobile-web-app-capable" content="yes"> - <link rel="icon" sizes="192x192" href="/icon.png"> - </head> - <body></body> -</html> -- -
Chrome will also allow web apps to launch in "App mode" if they embed a meta tag using the "apple-mobile-web-app-capable" name. Chrome will stop supporting this usage in an upcoming release. Chrome currently shows a deprecation warning in the Developer Tools’ console log when it detects a page with only the "apple-mobile-web-app-capable" meta tag. The warning appears as follows:
- -
-
-Whilst Chrome temporarily accepts the usage of "apple-mobile-web-app-capable", Chrome does not offer compatibility with the iOS Safari API’s including:
- -<meta name="apple-mobile-web-app-status-bar-style" content="black"><link rel="apple-touch-startup-image" href="/startup.png">target="_blank" to an anchor forces the user out of the
- web app and into the browser that the user added the icon from.<link rel="icon" sizes="192x192" href="nice-highres.png"> for the highest quality homescreen icons.Get faster, safer, and cheaper mobile web browsing with data compression.
- --The latest Chrome browser for Android and Chrome browser for iOS can significantly reduce cellular data usage by using proxy servers hosted at Google to optimize website content. This feature has been shown to reduce the size of web pages by 50%. To enable it, visit Settings > Bandwidth Management > Reduce data usage and toggle the option. -
- --Starting with the Android L Developer Preview, developers can preview bandwidth savings of WebViews inside Android apps. On a development-enabled device, users can enable this feature by going to Settings > Developer Options > Reduce WebView network usage. -
- --Note that WebView bandwidth management is under development and may change in the future. The Safe Browsing feature in not yet supported in WebView. -
- --The core optimizations that allow us to reduce overall data usage are performed by Google servers. When the Data Compression Proxy feature is enabled, Chrome Mobile opens a connection between your phone and one of the optimization servers running in Google's datacenters and relays all non-encrypted HTTP requests over this connection. -
- -
-The proxy server receives the request initiated on the mobile device, initiates a request for the required resource on your behalf, and then optimizes each response before delivering it back to the client. The content optimization is performed by our open-source PageSpeed libraries, which are specifically tuned for Chrome Mobile. The rendering of the page, and all JavaScript execution, is performed by the client’s browser. -
- -For your security and privacy:
- --Curious to see the bandwidth savings provided by the proxy? Visit your browser settings to see a graph of the original data size vs. the optimized version that your browser received. The bandwidth savings add up quickly! -
- -
-Let’s take a closer look at some of the specific optimizations enabled by the data compression proxy. -
- --Where possible the connection from the mobile device to the proxy runs over SPDY, an optimized protocol for the Web that is supported by Chrome, Firefox and Opera, and is also the basis for the forthcoming HTTP/2.0 standard being developed in the IETF. If a SPDY connection cannot be made, a regular HTTP/1.1 proxy connection is established. -
- -
-By using SPDY, the proxy is able to multiplex multiple request and response streams in parallel over a single TCP connection, which has numerous performance benefits: it amortizes TCP handshake overhead for multiple requests, enables higher throughput by removing the TCP slow-start phase incurred by each new connection, and enables intelligent request and response prioritization between the streams. In fact, our studies show that just the use of SPDY alone can reduce page load times by 23% on cellular networks, and this is before we have even talked about optimizing any of the content! -
- --Further, there are many additional benefits to using the compression proxy: -
- --Unfortunately, many web-sites are not optimized for the mobile web, which results in inefficient content delivery and slow rendering times. However, our experience with PageSpeed shows that many content optimizations can, in fact, be automated, which is precisely what the data compression proxy does on your behalf! -
- --Transcoding images: -Over 60% of the transferred bytes, for an average page, are images. Hence, the proxy takes great care to optimize and transcode all images to the WebP format, which requires fewer bytes than other popular formats, such as JPEG and PNG. The proxy supports the new -WebP lossless format for certain images, and also optimizes the perceptual quality of each image based on device screen resolution and pixel density of your device. By combining all these features the resulting images are up to 80% smaller! -
- --Content-aware compression: -The proxy performs intelligent compression and minification of HTML, JavaScript and CSS resources, which removes unnecessary whitespace, comments, and other metadata which is not essential to the rendering of the page. These optimizations, combined with mandatory gzip compression for all resources, can yield substantial bandwidth savings for the client. -
- --Safer, more secure browsing: -The proxy implements Safe Browsing for Chrome Mobile, by informing the browser when you attempt to visit a known malware or phishing site. This causes a warning page to be displayed, which you can click through if you wish to visit the site. The list of harmful sites is continuously updated on the proxy. -
- --This is just the beginning of what a powerful proxy service can provide to make the mobile web experience more efficient and enjoyable, regardless of whether you are on a latest 4G connection, or using an older generation mobile network. We are continuously improving the service and experimenting with new optimizations — stay tuned for more. -
- -X-Forwarded-For header. Site owners should check for this header to correctly determine the location of the user based on client's IP address.Cache-Control: no-transform directive. Site owners can mark individual resources with this directive and the proxy will pass them through directly to the mobile browser.googlechrome/googlechromes schemes instead of
-http/https. More information can be found in
-the article on this topic.
-The Google Chrome Mobile browser is based on the same code used by Chrome for Desktop. However, -there are implementation differences between Chrome for Android and Chrome for iOS. See the following -pages:
- - +The Google Chrome Mobile browser is based on the same code used by Chrome for Desktop. + See Chrome for Android. +
Many of our favorite apps have implemented Chrome mobile technologies.
- -The callback -feature in Chrome for iOS is a valuable asset for the following implementors:
- - - -{{/partials.standard_multidevice_article}} diff --git a/ios/feedly.html b/ios/feedly.html deleted file mode 100644 index 70a287f..0000000 --- a/ios/feedly.html +++ /dev/null @@ -1,17 +0,0 @@ -{{+bindTo:partials.standard_multidevice_article}} - -Feedly, a reader loved by more than 13 million users, has become a hub for users to organize their favorite blogs, news sites, podcasts, and YouTube channels for quick and efficient updates on the go, across any device.
- -
-
-Feedly prioritizes speed and intuitive usability to provide users with easy, direct access to their favorite content. Some of Feedly’s mobile publishers use partial RSS feeds. Users who click on these feeds navigate out of Feedly app to read the remainder of the content in the browser. As a result, the Feedly team prioritized helping users navigate between the Feedly app and the browser.
- -The integration of the Chrome callback feature into the Feedly iPhone and iPad app “was a no brainer and surprisingly simple to implement,” said the Feedly team.
- -The Feedly team notes that “90% of the time, once a user has finished reading an article, they want to resume skimming their feedly, looking for the next article to read.” Chrome callback enables a seamless transition between Feedly and Chrome, helping users access the content they want faster.
- -Knowing their users have a faster, more integrated web experience has allowed Feedly to continue focusing on helping people keep in touch with their favorite sites.
- -{{/partials.standard_multidevice_article}} diff --git a/ios/links.html b/ios/links.html index 7ea16a6..173e030 100644 --- a/ios/links.html +++ b/ios/links.html @@ -2,44 +2,38 @@
The easiest way to have your iOS app open links in Chrome is to use the OpenInChromeController class. +
The easiest way to have your iOS app open links in Chrome is to use the +OpenInChromeController class. This API is described here along with the URI schemes it supports.
The OpenInChromeController class provides methods -that encapsulate the URI schemes and the scheme replacement process also described in this document. -Use this class to check if Chrome is installed, to specify the URL to open, -to provide a callback URL, and to force opening in a new tab.
+The OpenInChromeController class provides methods that +encapsulate the URI schemes and the scheme replacement process also described +in this document. Use this class to check if Chrome is installed or to specify +the URL to open.
Methods
For example, use the OpenInChromeController class as follows:
if ([openInController_ isChromeInstalled]) {
- [openInController_ openInChrome:urlToOpen
- withCallbackURL:callbackURL
- createNewTab:createNewTab];
+ [openInController_ openInChrome:urlToOpen];
}
The OpenInChromeController class file is available here. Copy it into your Xcode installation.
+The OpenInChromeController class file is available +here. Copy it into +your Xcode installation.
The rest of this document describes the underpinnings of this API.
@@ -51,7 +45,6 @@To check if Chrome is installed, an app can simply check if either of these URI schemes is available:
@@ -65,8 +58,9 @@To actually open a URL in Chrome, the URI scheme provided in the URL -must be changed from http or https to the Google Chrome equivalent. The -following sample code opens a URL in Chrome: +must be changed from http or https to the Google Chrome equivalent of +googlechrome or googlechromes respectively. +The following sample code opens a URL in Chrome:
NSURL *inputURL = <the URL to open>; @@ -107,131 +101,6 @@URI schemes
Chrome for iOS also supports -x-callback-url, -an open specification for inter-app communications and messaging between iOS apps -that provides a way for the application opened in Chrome -to specify a callback URL to return to the calling app. -Applications supporting x-callback-url have to register a URL scheme -that will be used to call the app with compliant URLs.
- -See the following case studies for examples in the wild:
- - - -The URI scheme that Chrome registers for x-callback-url is:
- -This scheme will accept x-callback-url compliant URLs with the “open” action and the following parameters:
- -For example:
- -googlechrome-x-callback://x-callback-url/open/?url=http%3A%2F%2Fwww.google.com -- -
The x-callback-url parameters are supported in Google Chrome as of version 23.0. -Previous versions of Chrome are not registered for the googlechrome-x-callback URL scheme. -It’s important for apps to check if the URL scheme is registered -before trying to invoke the googlechrome-x-callback scheme.
- -To check if Chrome with x-callback-url is installed, an app can use the following code:
- -[[UIApplication sharedApplication] canOpenURL: - [NSURL URLWithString:@"googlechrome-x-callback://"]]; -- -
Once it has been determined that Google Chrome with x-callback-url is installed, -the app can then open a URL in Chrome specifying a callback URL as in the following example.
- -// Method to escape parameters in the URL.
-static NSString * encodeByAddingPercentEscapes(NSString *input) {
- NSString *encodedValue =
- (NSString *)CFURLCreateStringByAddingPercentEscapes(
- kCFAllocatorDefault,
- (CFStringRef)input,
- NULL,
- (CFStringRef)@"!*'();:@&=+$,/?%#[]",
- kCFStringEncodingUTF8);
- return [encodedValue autorelease];
-}
-…
-NSString *appName =
- [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
-NSURL *inputURL = <the URL to open>;
-NSURL *callbackURL = <the callback URL>;
-
-NSString *scheme = inputURL.scheme;
-
-// Proceed only if scheme is http or https.
-if ([scheme isEqualToString:@"http"] ||
- [scheme isEqualToString:@"https"]) {
- NSString *chromeURLString = [NSString stringWithFormat:
- @"googlechrome-x-callback://x-callback-url/open/?x-source=%@&x-success=%@&url=%@",
- encodeByAddingPercentEscapes(appName),
- encodeByAddingPercentEscapes([callbackURL absoluteString]),
- encodeByAddingPercentEscapes([inputURL absoluteString])];
- NSURL *chromeURL = [NSURL URLWithString:chromeURLString];
-
- // Open the URL with Google Chrome.
- [[UIApplication sharedApplication] openURL:chromeURL];
-}
-
-
-The calling application can also specify a URL as callback -when the user finishes the navigation using the -x-success parameter in the x-callback-url. -When specifying x-success with the callback URL, -you must also specify the application name -(via the x-source parameter), -which will be displayed in Chrome as a hint to the user -for how to return to the calling application. -Failing to provide the app name will result -in the x-success parameter to be discarded and ignored.
- -For example:
- -googlechrome-x-callback://x-callback-url/open/?x-source=MyApp&x-success=com.myapp.callback%3A%2F%2F&url=http%3A%2F%2Fwww.google.com -- -
In this case, -the callback URL specified is com.myapp.callback:// -and Chrome will call back to the calling app on that URL -when the user has finished the navigation. -The application name, specified using the x-source parameter, is MyApp, -and it will be shown as a replacement of the back button -when the user can return to the calling application.
- -By default, Chrome reuses the same tab when opened by the same application. -To override this default behavior, -the calling app should provide the create-new-tab -parameter as part of the action parameter in the x-callback-url URL.
- -For example:
- -googlechrome-x-callback://x-callback-url/open/?x-source=MyApp&x-success=com.myapp.callback%3A%2F%2F&url=http%3A%2F%2Fwww.google.com&create-new-tab -- -
Chrome for iOS is designed to be fast. Users search and navigate fast, directly from the same omnibox. Results appear as the user types (prefetching). Users open and quickly switch between an unlimited number of tabs. With sign-in to Chrome, the user's tabs, bookmarks, passwords, and omnibox data sync automatically from other Chrome instances to the iPhone, iPod touch, or iPad, eliminating the delay otherwise inherent with switching between devices. Moreover, the user can send pages from Chrome on the computer to the iPhone, iPod touch, or iPad with one click and read them on the go, even when offline. - -
Chrome for iOS is derived from the WebKit browser codebase, as is Apple's Mobile Safari. However, while Apple allows only Safari to access iOS facilities like the iOS Nitro engine, Chrome uses Apple's UIWebView for loading and rendering content. Any of the considerations for UIWebView apply to Chrome for iOS. See the Chrome Mobile FAQ for more information.
- -There are considerations as well for opening URLs in Chrome for iOS, see Opening links in Chrome.
- -{{/partials.standard_multidevice_article}} diff --git a/ios/pocket.html b/ios/pocket.html deleted file mode 100644 index 7993f54..0000000 --- a/ios/pocket.html +++ /dev/null @@ -1,15 +0,0 @@ -{{+bindTo:partials.standard_multidevice_article}} - -Pocket provides a cross-device experience where users can save articles and almost any other type of web content to view later, on or offline. The Pocket team strives to make taking any type of content with you “as simple an action as putting it in your pocket.”
- -
-
-Pocket excels at presenting that content in a clean, clutter-free viewing experience across platforms. Still, there are times when users want access to a full browsing experience. In addition, Pocket notes, "Chrome users spend nearly 30% more time in the app than users of the next leading browser."
- -Chrome callback enables Pocket to pass users seamlessly between Chrome browser and the Pocket app while maintaining Pocket’s simple design. Now, users, which save over 43 million items a month, have a quick and intuitive way to return to the Pocket app while viewing their saved content on the web.
- -With a growing base of engaged, tech-savvy users, Pocket looks to continue enhancing the way its more than 9.5 million users discover and consume content.
- -{{/partials.standard_multidevice_article}} diff --git a/pillar.html b/pillar.html index c61d67f..ba24bc6 100644 --- a/pillar.html +++ b/pillar.html @@ -12,6 +12,14 @@
+
+
+ Using a Chrome Custom tab you can style and control Chrome to fit in with your brand. +
+
In iOS, there are several methods for opening links in Chrome. On iOS, URLs are opened in - Safari by default. However, applications can check whether Chrome is installed, and explicitly - open links in Chrome if desired. -
- -requestAutocomplete?requestAutocomplete is available on all up-to-date Chrome browsers: Windows, Mac, ChromeOS, Android, iOS, and Linux.
requestAutocomplete is available on all up-to-date Chrome browsers: Windows, Mac, ChromeOS, Android, and Linux.
Here’s an example of the Chrome UA on iPhone:
-Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) -AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 -Safari/7534.48.3+
Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) +AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 +Mobile/14E5239e Safari/602.1-
For comparison, the Safari UA:
+For comparison, the Mobile Safari UA:
-Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) -AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543 -Safari/419.3+
Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) +AppleWebKit/603.1.23 (KHTML, like Gecko) Version/10.0 +Mobile/14E5239e Safari/602.1-
For more information about Mobile Safari user agent strings, see -Using the Safari User Agent String.
+When the Request Desktop Site feature is enabled, the Desktop Safari UA is +sent: -Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) +AppleWebKit/600.7.12 (KHTML, like Gecko) Version/8.0.7 +Safari/600.7.12+
Old WebView UA:
-Mozilla/5.0 (Linux; U; Android 4.1.1; en-gb; Build/KLP) +Mozilla/5.0 (Linux; U; Android 4.1.1; en-gb; Build/KLP) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30WebView UA in KitKat to Lollipop
-Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/_BuildID_) +Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/_BuildID_) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36-If you’re attempting to differentiate between the WebView and Chrome for Android, +
If you’re attempting to differentiate between the WebView and Chrome for Android, you should look for the presence of the Version/_X.X_ string in the WebView -user-agent string. Don’t rely on the specific Chrome version number +user-agent string. Don’t rely on the specific Chrome version number (for example, 30.0.0.0) as the version numbers changes with each release.
WebView UA in Lollipop and Above
-In the newer versions of WebView you can differentiate the WebView by looking for the wv field as highlighted below.
- -Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.65 Mobile Safari/537.36+In the newer versions of WebView, +you can differentiate the WebView by looking for the wv field as highlighted below.
+Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B; wv) +AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.65 Mobile +Safari/537.36
Since Android 4.4 (KitKat) the WebView component is based on the Chromium -open source project. These WebView's include an updated version of the V8 -JavaScript engine and support for modern web standards that were missing in -the old WebView. It also shares the same rendering engine as Chrome for Android, +
Since Android 4.4 (KitKat), the WebView component is based on the Chromium +open source project. WebViews now include an updated version of the V8 +JavaScript engine and support for modern web standards +previously missing in old WebViews. +New Webviews also share the same rendering engine as Chrome for Android, so rendering should be much more consistent between the WebView and Chrome.
-In Android 5.0 (Lollipop) the WebView was moved to an APK, meaning it -could be updated seperately to the Android platform. To see what version -of Chrome is currently used on a Lollipop device, simply go to Settings < -Apps < Android System WebView and look at the version.
+In Android 5.0 (Lollipop), the WebView has moved to an APK +so it can be updated seperately to the Android platform. +To see what version of Chrome is currently used on a Lollipop device, +simply go to Settings < Apps < Android System WebView +and look at the version.
If you're a web developer looking to start developing a WebView-based Android application, see Getting Started: WebView-based Applications for Web Developers.
+If you're primarily planning to show external web content inside of your app, you should consider Custom Tabs instead.
+For tips on scaling WebView content for mobile devices, see Pixel-Perfect UI in the WebView.
The new WebView also supports remote debugging @@ -44,9 +48,10 @@
For future proofing you app you can use the Beta WebView to test -versions of the WebView before it's launched. Checkout this [Android Developer -blog post for more details](http://android-developers.blogspot.com/2015/02/beta-channel-for-android-webview.html).
+For future proofing you app, you can use the Beta WebView to test +versions of the WebView before it's launched. +Checkout this +[Android Developer blog post for more details](http://android-developers.blogspot.com/2015/02/beta-channel-for-android-webview.html).