Chrome Custom Tabsを使いこなす


Chrome 45から導入されたCustom Tabs機能は、アプリ内のWebページ読み込みを大幅に高速化するだけではありません。
“Custom”の名前のとおり、Toolbarにアクションボタンメニューを追加する拡張機能も備えています。前回の記事ではCustom Tabsを構成するCustomTabsServiceConnection、CustomTabsClient、CustomTabsSessionなど基本的な要素を解説しました。

pic

ここでは図で示したようにToolbar上のアクションボタン、メニューの追加方法について解説していきます。サンプルプロジェクトは次のリポジトリからダウンロード可能です。

今回、紹介しているCustomTabsIntent.Builderの機能は次のとおりです。

CustomTabsIntent.Builderの主なメソッド

メソッド名 説明
setToolbarColor ツールバーの色を設定する
setShowTitle タイトルを表示する
setStartAnimations 開始時アニメーションを指定する
setExitAnimations 終了時アニメーションを指定する
setActionButton アクションボタンを追加する
setCloseButtonIcon Back、クローズボタンを指定する
addMenuItem メニュー項目を追加する

サンプルコード、解説は続きから。

Support Libraryを使う

Support Library v23ではCustomTabsに対応しています。Android Stduioのプロジェクトに次の設定を行ってください。

■app/guild.gradleのdependenciesに依存パッケージを追加

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.0.1'
    compile 'com.android.support:customtabs:23.0.1'
}

com.android.support:customtabsをつかうには、サポートライブラリがv23以上である必要があります。エラーが出た場合は、開発環境を更新してください。

CustomTabsを試す準備

ChromeのCustomTabsを使う特徴のひとつにInternetパーミッションが不要である点があります。これはChromeアプリでブラウジングしているためで、アプリが直接インターネットにつなぐわけではないためです。

次のコードは前提となるActivityのコードですが読み飛ばしても影響ありません。画面のボタンをおしたらGoogleを開くサンプルを例に処理を見ていきましょう。

■src/MainActivity.java

public class MainActivity extends AppCompatActivity {

    private String TAG = "CustomTabs";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button b = (Button) findViewById(R.id.button);
        b.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // URLをひらく
                lunchCustomTabs("https://google.co.jp/");
                // lunchCustomTabsWithAction("https://google.co.jp/");
                // lunchCustomTabsWithMenuItem("https://google.co.jp/");
            }
        });
    }
    ...省略...
}

CustomTabsを呼び出す処理を、MainActivityのlunchCustomTabsメソッドで行っています。

ブラウジングに使う

次のメソッドはCustomTabsIntent.Builderを使ってCustomTabsIntentを作っています。
ここではToolbarのタイトルや色を指定しています。

■src/MainActivity.java

public class MainActivity extends AppCompatActivity {
    ...省略...
    private void lunchCustomTabs(String url) {
        // ビルダーを使って表示方法を指定する
        CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
        builder.setToolbarColor(Color.BLUE).setShowTitle(true);
        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);

        // CustomTabsでURLをひらくIntentを発行
        CustomTabsIntent customTabsIntent = builder.build();
        customTabsIntent.launchUrl(this, Uri.parse(url));
    }
    ...省略...
}

CustomTabsIntent.BuilderがCustomTabsIntentを生成、launchUrlメソッドでChromeブラウザを起動するIntentを発行します。CustomTabsはChromeブラウザのバージョン45以上で実行できる機能ですが、もし端末のChromeが44以下だった場合&Chromeが入っていない場合は、適切に通常のブラウザを呼びます(普通のIntentになります)。開発者自分で判定する必要はありません。

ただし、セッションの維持を必要とする場合は注意してください。サンプルではCustomTabsIntent.Builderの生成には引数を指定していませんが、引数を与えることも可能で、その引数がセッション情報です。たとえば、OAuth認証に使う、ログイン処理を伴う場合、またはショッピングカートのようにこの後も処理を継続する場合(=セッションを保存し続ける必要がある)は、セッションをアプリ側で保存する必要があります。

セッション情報をもつCustomTabsSession前回の記事でActivityに保持しているので興味があれば確認してみてください。

アクションボタンを追加する

actionbutton

CustomTabsでは、クローズボタンやアクションボタンを追加できます。次のコードはアクションボタンを追加して、押したら暗黙的インテントを発行する例です。

■src/MainActivity.java

public class MainActivity extends AppCompatActivity {
    ...省略...
    private void lunchCustomTabsWithAction(String url) {

        // ビルダーを使って表示方法を指定する
        CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
        builder.setToolbarColor(Color.BLUE).setShowTitle(true);
        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);

        // アクションボタン押下時に発行するIntent
        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtra("test", "Action Button Pushed!");
        // PendingIntentを用意する
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* REQUEST_CODE */, intent, 0 /* flags */);
        Bitmap icon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
        builder.setActionButton(icon, "action", pendingIntent);

        // CustomTabsでURLをひらくIntentを発行
        CustomTabsIntent customTabsIntent = builder.build();
        customTabsIntent.launchUrl(this, Uri.parse(url));
    }
    ...省略...
}

CustomTabsIntent.BuilderのsetActionButtonメソッドで追加しています。アクションボタンにはアイコン、名前、実行時のPendingIntentを含めることができます。PendingIntentはNotificationなどでもお馴染みの通知機能です。設定完了後、CustomTabsIntentを生成、launchUrlメソッドでURLを読み込みます。

またサンプルでは例示していませんが、クローズボタンを追加する場合はsetCloseButtonIconメソッドを利用します。こちらも引数はアイコン用のリソースだけのシンプルなメソッドです。

メニューアイテムを追加する

最後にCustomTabsのToolbarにメニュー項目を追加する方法を解説します。

menuitem

メニューの追加もアクションボタンの追加と同じく、CustomTabsIntent.Builderを利用します。

■src/MainActivity.java

public class MainActivity extends AppCompatActivity {
    ...省略...
    private void lunchCustomTabsWithMenuItem(String url) {

        // ビルダーを使って表示方法を指定する
        CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
        builder.setToolbarColor(Color.BLUE).setShowTitle(true);
        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);

        // メニュー押下のときのIntentをpendingIntentにいれて設定
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("text/plain");
        intent.putExtra(Intent.EXTRA_TEXT, "Send from Chrome Custom Tabs!");
        // PendingIntentを用意する
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* REQUEST_CODE */, intent, 0 /* flags */);
        builder.addMenuItem("ACTION_SEND", pendingIntent);

        // CustomTabsでURLをひらくIntentを発行
        CustomTabsIntent customTabsIntent = builder.build();
        customTabsIntent.launchUrl(this, Uri.parse(url));
    }
    ...省略...
}

CustomTabsIntent.BuilderのaddMenuItemメソッドを使い、メニュー項目を追加します。表示する文字列および押された時に実行するPendingIntentを指定します。ここではACTION_SENDと表示して、押されたら文字列を共有するIntentを発行しています。

実際にメニューを追加する際は、遷移したURLから先、どのような操作をしたか情報が得られない(通常のブラウザなのでリンクが有効なら遷移する)ためアプリ固有の遷移先をメニューに埋め込むことになるでしょう(設定やトップに戻る、一覧表示など)。

CustomTabsは、簡単に使えるだけでなく、高速化やログイン情報などをWebブラウザと共有できる利点があります(WebViewを使うとログインしているはずのサービスで2度目のログインを要求されるなど誰しも経験していそうですね)。

また、ちゃんと作っていてもWebViewを使っていると自由度が高い反面、ユーザの行動をトラッキングしているのでは?という不要な疑惑も生まれがちでした。CustomTabは、このようなセキュリティ上の懸念を除外しつつ高速化などの恩恵を受けられる機能といえます。現時点では最新のChrome v45が必要ですが、浸透していくにしたがって強力な選択肢となるでしょう。

以上、おつかれさまでした。