はじめに
つい先日、SFSafariViewContoroller について調べたのですが、
Chrome Custom Tabs についても依頼があったので、
ホームグラウンドキタ━━━━(゚∀゚)━━━━!!
と喜び勇んで調べてみたメモ
やりたいこと
- アプリと Chrome で Cookie を同期したい
結論
無理!!
例によって、言い訳していきます。
カスタムは許されない
この辺は、SFSafariViewController と同じですね。
とはいえ、カスタムできない理由は SFSafariViewController と異なります。
以下、Chrome Custom Tabs の呼び出しのコードです。
// ビルダーを使って Chrome Custom Tabs のインテントを生成
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder
.setToolbarColor(Color.BLUE)
.setShowTitle(true)
.setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left)
.setExitAnimations(this, R.anim.slide_in_left, R.anim.slide_out_right)
.build();
// Chrome Custom Tabs の開始
customTabsIntent.launchUrl(this, Uri.parse(url));
コードを見てわかるように、__呼び出しはインテントを利用__しています。
つまり、別アプリ\(^o^)/
手出しなんて、しようがありません。
こいつの主機能も__「指定された URL にアクセスしてウェブページを表示する」だけ__です。
でも、Cookieの共有は双方向 ※
Chrome Custom Tabs と Chrome の Cookie 共有は、双方向です。
SFSafariViewController と手順で Google ログインを試したところ、どちらも OK でした。わーい!
手順 | 期待値 | 結果 |
---|---|---|
Chrome Custom Tabs からログイン → Chrome でログイン後のページを表示 | ログイン状態で表示される | OK |
Chrome からログイン → Chrome Custom Tabs でログイン後のページを表示 | ログイン状態で表示される | OK |
Chrome Custom Tabs を経由せずに Chrome を立ち上げても同じ結果でした。
ここも SFSafariViewController とは異なりますね。
ただし、アプリ側に Cookie をひっぱってこれないのは一緒。
よく考えたら、コレできちゃうと脆弱性だよね。仕方ないね。
余談
本筋からずれちゃうので、余談として相違点とか Tips とか書いときます。
SFSafariViewController との相違点
相違点は、以下の通り。
- 表示対象のウェブページを先読みできる
→ 誰かしら書いてるだろうと思ってここではコードとか省いてるけど、
先読みによって表示時のロード時間を短縮できます。
CustomTabsServiceConnection クラスを利用するので、CustomTabsService 的なものが待機していて、
それに対して、「この URL を読んどいてくれー」的に通知してるんだろうね。
ちゃんとコーディングしたら、また追記します。 - サポートライブラリが提供されている
→ 現在は、API 15 以上を対象としたサポートライブラリが存在しています。
Gradle への追記は「※1」な感じ。
先読みの時は、モジュールを公式から持ってこないといけないらしいので、「※2」な感じ。 - 端末側にバージョン 45 以上の Chrome のインストールが必要
→ Chrome Custom Tabs に対応してないバージョンの Chrome だった場合や
Chrome ではなく、他のブラウザ系のアプリしかインストールされていない場合は、
別アプリとしてブラウザ系のアプリが起動します。
Chrome Custom Tabs として起動されません。
ちなみにブラウザ系アプリが端末に存在しない場合は、ActivityNotFoundException が発生します。
この辺りは、もろインテント利用時の動きですね。
※1 単純に Chrome Custom Tabs を使う時の build.gradle(一部抜粋)
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.0'
// Chrome Custom Tabs のサポートライブラリ
compile 'com.android.support:customtabs:23.1.0'
}
※2 Chrome Custom Tabs を先読みさせたい時の build.gradle(一部抜粋)
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.0'
// Chrome Custom Tabs のサポートライブラリ
compile 'com.android.support:customtabs:23.1.0'
// ↑を指定せずに、公式の customtabs モジュールを読み込んでもいい。
// shared モジュールとバージョンを合わせたいという観点の時は、こっちの方がいいかも?
// compile project(':customtabs')
// 公式の shared モジュールの組み込み
// サービスのバインド時に必要なパッケージ名をとってくるヘルパークラスがいるので、こいつは必須です。
// (そこを自作するというなら、使わなくてもいい気がしないでもない)
compile project(':shared')
}
Chrome Custom Tabs のツールバーをアプリのアクションバーと同じ色にしたい
以下のようにすればできます。
/**
* テーマのプライマリーカラーを取得する
*
* @return プライマリーカラー
*/
private int getThemeColorPrimary() {
final TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true);
return typedValue.data;
}
/**
* アニメーションなしで Chrome Custom Tabs を起動
*
* @param url 表示対象のURL
*/
private void launchCustomTabs(Uri url) {
// ビルダーを使ってカスタムタブのインテントを生成
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder
.setToolbarColor(getThemeColorPrimary()) // ← ここで指定
.setShowTitle(true)
.build();
// カスタムタブの開始
customTabsIntent.launchUrl(this, url);
}
まとめ
- 双方向の共有ができるけど、アプリでの利用はできないよ!
- 実態は、別アプリだよ!たぶん iframe 的に Chrome が入れ子されてるよ!
- Android 好きだよ!
参考
- GoogleChrome/custom-tabs-client · GitHub
https://github.com/GoogleChrome/custom-tabs-client - How to get accent color programmatically?
http://stackoverflow.com/questions/27611173/how-to-get-accent-color-programmatically