Chrome Custom Tabs最佳实践
本文是 Chrome Custom Tabs 官方文檔的按照自己的理解的整理譯文
什么是Chrome Custom Tabs(CCT)?
當開發者是去打開一個URL時候往往有兩種方式:WebView和打開瀏覽器。目前這兩種方式皆有不足,WebView不與瀏覽器共享狀態,維護開銷大;打開瀏覽器是一個重量級的操作并且瀏覽器不可定制化。此時谷歌爸爸給了我們新的選擇,CCT讓我們在網絡體驗上有了很多的控制,使本地和Web內容更加無縫之間的轉換,而無需采取WebView的方式。CCT允許應用定制瀏覽器的外觀和樣式,如下:
- Toolbar顏色
- 打開關閉時的切換動畫
- 添加Toolbar的Actions,添加Overflow Menu 和底部Toolbar
CCT還允許開發人員預啟動Chrome和更快的內容預抓取加載。
現在可以在Github上測試這些 sample.
怎么選擇Chrome Custom Tabs vs WebView?
WebView是對于展示自己域名下或本地的網頁內容很好的一種解決方案,因為你可能會去網頁內容做很多自定義的內容。而如果引導用戶去第三方的網址時,建議您使用CCT,理由如下:
- 易于實現。無需建代碼來管理請求,權限授予和Cookie
- UI上的自定義上文已提到
- 導航:瀏覽器提供了一個可回調的外部導航模塊
- 性能優化:
- 在后臺瀏覽器的預加熱,避免從應用程序竊取資源。
- 提前提供一個合適的URL到瀏覽器,它可以進行投機性的工作,加快頁面加載時間
- 生命周期管理:通過提高“foreground”的重要級來防止CCT防止被系統被消滅
- 共享Cookie和權限模塊,用戶不必再次登錄到他們已經連接或者重新授權他們已經授權的網站
- 使用CCT用戶依舊可以從Data Saver(Chrome插件:幫助用戶節省瀏覽時的數據使用量)獲益
- 更好的完成設備自動同步
- 簡單的定制模式
- 更快速的返回到本地應用
- You want to use the latest browser implementations on devices pre-Lollipop (auto updating WebView) instead of older WebViews.
使用條件?
需要安裝Chrome45或以上版本,支持的Android版本(Jellybean(4.1)以上)。
使用向導
一個完整的例子可在https://github.com/GoogleChrome/custom-tabs-client 找到。它包含了使用可重復的類來定制UI,連接到后臺服務,并處理應用程序和CCT的生命周期。
首先你需要添加CCT的依賴 Custom Tabs Support Library 在你的build.gradle文件里
dependencies {
…
compile‘com.android.support:customtabs:24.2.0’
}
當你完成添加依賴你可能有兩個配置需要自定義:
- 自定義選項卡的UI和交互
- 使頁面加載速度更快,并使應用程序保活
UI的自定義你可能會使用到 CustomTabsIntent 和 CustomTabsIntent.Builder; 性能的改進通過使用CustomTabsClient 來連接Custom Tabs service,預加熱Chrome以及讓它知道那個URL將被打開.
快速使用
String url = ¨https://paul.kinlan.me/¨; CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); CustomTabsIntent customTabsIntent = builder.build(); customTabsIntent.launchUrl(this, Uri.parse(url));設置Toolbar顏色
builder.setToolbarColor(colorInt);自定義Action Buttons
作為開發者你將擁有呈現給用戶的Chrome標簽內的操作按鈕的所有控制。
在大多數情況下,這將是一個主要的作用,如分享,或者你的用戶將執行另一種常見的活動。
用戶點擊操作按鈕調用的PendingIntent通過Bundle由Chrome傳遞過來。該圖標是高度最好是24dp和24-48dp的寬度。
// 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);自定義菜單
Chrome瀏覽器CCT將始終會有前進,頁面信息,刷新三個圖標,菜單上會有“查找頁面”和“在瀏覽器中打開”兩項。作為開發者你還可以添加多達5個菜單項。
菜單項是通過調用 CustomTabsIntent.Builder#addMenuItem 和帶有標題的PendingIntent,然后Chrome會將用戶的行為作為參數傳遞過來。
builder.addMenuItem(menuItemTitle, menuItemPendingIntent);設置切換動畫
很多Android應用程序中使用自定義動畫來過渡Android上的Activities切換。 CCT并沒有什么不同,你可以改變的打開和關閉(當用戶按下后退)動畫,讓他們與你的應用程序的其他部分相一致。
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);預加熱Chrome加速加載頁面
默認情況下,當CustomTabsIntent#launchUrl 被調用時它會啟動Chrome和URL,這會占用寶貴的時間和影響切換平滑的感覺。
我們知道用戶需要近乎瞬時的體驗,所以我們提供一個可以讓應用連接并告訴Chrome預加熱瀏覽器和本地組件的服務。同時我們也可以告訴Chrome瀏覽器你設置的用戶將會訪問的網址,然后Chrome將會執行一下步驟:
- DNS預解析主域
- DNS預解析最有可能的子資源
- 預連接到目的地,包括HTTPS / TLS。
預加熱Chrome的過程如下:
- 使用 CustomTabsClient#bindCustomTabsService 連接到服務
- 一旦服務連接,調用 CustomTabsClient#warmup 在后臺啟動Chrome
- 調用 CustomTabsClient#newsession 來創建一個新的會話。本次會話是用于所有請求的API
- (可選)當創建一個會話的時候添加參數 CustomTabsCallback,可以知道頁面是否加載完成
- 通過 CustomTabsSession#mayLaunchUrl 加載一個頁面可以告訴Chrome那個頁面是用戶最有可能去加載的
- 調用 CustomTabsIntent.Builder 構造函數傳遞創建的 CustomTabsSession
連接到Chrome Service
CustomTabsClient#bindCustomTabsService 簡化了連接到Custom Tabs service的流程,創建 CustomTabsServiceConnection,并使用 onCustomTabsServiceConnected 得到 CustomTabsClient的一個實例。操作如下
// 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 stableCustomTabsServiceConnection connection = new CustomTabsServiceConnection() {@Overridepublic void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {mCustomTabsClient = client;}@Overridepublic void onServiceDisconnected(ComponentName name) {} }; boolean ok = CustomTabsClient.bindCustomTabsService(this, mPackageNameToBind, connection);Warm up the Browser Process
boolean warmup(long flags)
返回 true 代表成功.
預加熱瀏覽器進程和加載庫文件。此操作是異步的,返回值表示請求是否被接受。多次調用成功亦返回true
創建Tab session
boolean newSession(CustomTabsCallback callback)
會話被用于隨后與CustomTabsCallback相連接的回調,并產生相互的標簽。這里提供的回調與創建會話相關聯。所創建的會話的任何更新(見下面的自定義選項卡回調)通過該回調接收。返回值表示會話是否已成功創建。多個調用相同CustomTabsCallback或者空值將返回false。
設置可能打開的URL
boolean mayLaunchUrl(Uri url, Bundle extras, List otherLikelyBundles)
該方法告訴瀏覽器一個未來可能加載的URL。warmup() 首先會被調用,最有可能的URL必須首先指定。(可選)可以提供其它可能的URL列表。它們被視為不太可能相比第一個,并且以降序進行排序。這些額外的URL可能會被忽略。這種方法以前所有的請求都將被deprioritized。返回值表示操作是否成功完成。
自定義選項卡Connection Callback
void onNavigationEvent(int navigationEvent, Bundle extras)
自定義選項卡有用戶行為發生時將被調用。該 navigationEvent int是定義的6種頁面狀態。請參閱下面的詳細信息。
如果用戶沒有安裝了最新版本的Chrome會發生什么?
自定義選項卡使用帶有附加功能鍵的ACTION_VIEW意圖定制UI。這意味著,在默認情況下頁面將會在系統瀏覽器,或用戶的默認瀏覽器。
如果用戶安裝了Chrome瀏覽器并且設置默認的瀏覽器,它會自動拿起額外設備和呈現的自定義UI。另外,也可以為其他瀏覽器使用意圖額外提供一個類似的定制接口。
如何檢查Chrome是否支持CCT?
所有版本的Chrome都支持CCT暴露出來的一個服務。要檢查是否支持自定義選項卡,嘗試綁定到該服務。如果成功,則可以安全使用自定義選項卡。
最佳實踐
Connect to the Custom Tabs service and call warmup()
通過這樣的方式你最多可以節省700ms,700ms差不多是界定卡與不卡的時間。在Activity的 onStart() 去連接Custom Tab service, 連接后調用 warmup(). 這一操作將作為低優先級的進程,這意味著它不會對你的應用程序性能的負面影響,但加載鏈接時會給出一個大的性能提升。
Pre-render content
預渲染將使外部內容瞬間打開。所以,如果你的用戶至少點擊鏈接的50%的可能性,調用mayLaunchUrl()這個方法會提前下載并渲染網頁內容,但不可避免的會有一點流量和電量的消耗。如果用戶正在使用收費的數據流量,或者手機電量不足,那么這個方法不會生效。所以我們完全不用自己考慮性能優化。
備選方案
如果用戶的手機上沒有安裝Chrome,那么打開默認瀏覽器可能并不是最好的用戶體驗。所以如果在bindService那一步失敗了,無論是打開默認瀏覽器還是WebView,選擇一個你認為最好的備選方案。
Add your app as the referrer
很多網站都會統計自己的流量是從哪兒來的,所以最好告訴他們是你的帥氣APP給他們帶來了流量:
intent.putExtra(Intent.EXTRA_REFERRER, Uri.parse(Intent.URI_ANDROID_APP_SCHEME + "//" + context.getPackageName()));自定義動畫
自定義動畫將讓你的應用程序將網站內容更平滑的過渡。確保完成動畫和動畫開始是相對應的,這會幫助用戶了解他們已經回到了應用程序。
//Setting custom enter/exit animationsCustomTabsIntent.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/"));為ActionButton添加一個Icon
添加ActionButton可以讓用戶更多的了解應用有那些功能。你可以創建描述該操作的文本的位圖,如果沒有一個很好的圖標來表示你的操作按鈕執行的操作,記住位圖的最大尺寸為24dp高x寬48dp。
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 implementationIntent 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);多個瀏覽器的選擇
用戶可以安裝多個支持CCT的瀏覽器。如果有一個以上的瀏覽器支持自定義選項卡或者其中沒有一個是首選瀏覽器,那么可以詢問用戶想如何打開鏈接.另外添加一個可以選擇默認瀏覽器的選項,這樣可以讓用戶自由的去選擇是否使用CCT.
/*** 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;}使用本地應用處理鏈接
一些URL可以通過本地應用程序進行處理。如果用戶安裝了Twitter的應用程序,那么點擊鏈接后更期望在Twitter中打開。所以在應用程序打開一個URL之前,最好先檢查本機是否有方法可以代替。
定義Toolbar顏色
如果你希望用戶覺得內容是應用程序的一部分,那么可以設置Toolbar顏色為Primary color。如果你考慮讓用戶知道該頁面已經離開了你的App那么千萬不要自定義Toolbar顏色。
添加分享
大多數情況下用戶都會想要分享這個鏈接但是CCT默認不添加,所以最好自己加上
//Sharing content from CustomTabs with on a BroadcastReceiverpublic 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);}}定義關閉按鈕
如果你希望用戶感覺像CCT是一個對話框可以使用默認的“X”按鈕。如果你希望用戶感覺到CCT是App的一部分可以使用后退箭頭。
//Setting a custom back buttonCustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder();intentBuilder.setCloseButtonIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_arrow_back));處理內部鏈接
當攔截到由android:autoLink或者WebView產生的內部鏈接點擊時,最好讓應用程序自己去處理,CCT只處理外部鏈接。
WebView webView = (WebView)findViewById(R.id.webview); webView.setWebViewClient(new WebViewClient() {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {return true;}@Overridepublic void onLoadResource(WebView view, String url) {if (url.startsWith("http://www.example.com")) {//Handle Internal Link...} else {//Open Link in a Custom TabUri uri = Uri.parse(url);CustomTabsIntent.Builder intentBuilder =new CustomTabsIntent.Builder(mCustomTabActivityHelper.getSession());//Open the Custom Tab intentBuilder.build().launchUrl(context, url)); }} });連擊處理
確保用戶點擊鏈接后到打開CCT之間不要超過100ms,否則用戶會覺得反應遲鈍,并嘗試多次點擊。當然卡頓是無法避免的,所以在用戶多次點擊后確保只打開CCT一次。
轉載請注明出處:http://blog.csdn.net/just_sanpark/article/details/52249051
參考 http://qq157755587.github.io/2016/08/12/custom-tabs-best-practices/
總結
以上是生活随笔為你收集整理的Chrome Custom Tabs最佳实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android 打开网页之CustomT
- 下一篇: USB协议学习笔记 - CUSTOM H