ActionBarの共有ボタンに共有履歴を表示する方法

# ShareActionProvider
ICS以降、ActionBarに共有MenuItemを置く際、共有履歴を表示することができるようになった。
ShareActionProviderはその実装のための仕組みとして導入された。

## 実装
まず、menu定義に共有MenuItemを定義する。
このとき、`android:actionProviderClass`属性に`android.widget.ShareActionProvider`を定義する。
この属性を定義すると自動的に共有アイコンも設定される。
`android:showAsAction`は`never`でも正常に動作するが、最新履歴の表示がなくなってしまうため`ifroom`か`always`が良いだろう。

````xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MyActivity">
    <item
        android:id="@+id/action_share_always"
        android:actionProviderClass="android.widget.ShareActionProvider"
        android:showAsAction="always"
        android:title="@string/action_share" />
</menu>
````

次に、ソースコード側でMenuItemの設定を行う。
`ShareActionProvider`を使用する場合、共有アクションで実行する`Intent`も`onCreateOptionsMenu`で指定できてしまうため、`onOptionsItemSelected`での処理は特に必要なくなる。
また、下の例では`ShareCompat.IntentBuilder`を利用しているが、普通に`Intent`を生成して`setShareIntent`しても問題なく動く。

````java
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.my, menu);

        // ShareActionProvider の設定
        MenuItem actionItem = menu.findItem(R.id.action_share_always);
        ShareActionProvider actionProvider = (ShareActionProvider) actionItem.getActionProvider();
        // インテントの設定
        Intent shareIntent = ShareCompat.IntentBuilder.from(this)
                .setText("hogehoge")
                .setType("text/plain")
                .getIntent();
        // ShareActionProviderにインテントの設定
        actionProvider.setShareIntent(shareIntent);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // 何も書かなくてOK
        return super.onOptionsItemSelected(item);
    }

````

## 動作
はじめて共有アイコンをタップした場合、以下のようなポップアップが表示される。
![共有動作実行前](https://qiita-image-store.s3.amazonaws.com/0/48019/5001b587-b3f2-cf4c-22ab-36b964ab33c7.jpeg)


すべてを表示→Twitterを選択し、Twitterから戻るとこのような画面になっている。
複数のアプリで共有を試すと左側の共有アイコンタップで表示されるポップアップも最新以前の履歴になっていることがわかる。
![Twitterで共有後](https://qiita-image-store.s3.amazonaws.com/0/48019/33824bda-97bd-1ba4-e1cd-60cd4ca8a116.jpeg)

# ShareCompat
`ShareActionProvider`は便利だがICS以降でしか実装ができない。
ICS以前の端末に対応したアプリで同様の実装を行うためには`SupportLibrary`の`ShareCompat`を利用する。
ただし、`ShareCompat`を使ってもICS以前の端末で履歴が表示されるわけではない。
この辺りは`NotificationCompat`等と一緒だ。

## 実装
`ShareCompat`で実装を行う場合、menu定義では特別な表記は必要ない。
ただし、デフォルトの共有アイコンが設定されないため、こちらは定義する必要がある。

````xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MyActivity">
    <item
        android:id="@+id/action_share_always"
        android:icon="@android:drawable/ic_menu_share"
        android:title="共有"
        app:showAsAction="always" />
</menu>
````

ソースコード側の処理は`ShareActionProvider`を使用していた部分を`ShareCompat`で書きなおすような形になる。
`ShareActionProvider`同様、`onOptionsItemSelected`での処理は特に必要ない。
ただし、`Intent`ではなく`ShareCompat.IntentBuilder`を渡すことになるため、若干の制限が生じる。
たとえば、`ShareCompat.IntentBuilder`では`setAction()`ができないため、`ACTION_SEND`か`ACTION_SEND_MULTIPLE`以外のアクションが指定できないようだ(ちょっと自信がない…)。

````java
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.my, menu);

        // IntentBuilderの生成
        ShareCompat.IntentBuilder builder = ShareCompat.IntentBuilder.from(this);
        builder.setText("hogehoge")
                .setType("text/plain");
        // MenuItemにShareアクションの設定
        ShareCompat.configureMenuItem(menu, R.id.action_share_always, builder);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return super.onOptionsItemSelected(item);
    }
````

## 動作
ICS以降の端末での挙動は`ShareActionProvider`と変わらない。
それ以前の端末ではmenuのxmlで指定したアイコンのみが表示され、タップ時には`IntentBuilder`で生成した`Intent`が発行される。
物理メニューボタンのある機種でも同様。

# まとめ
ActionBarに共有ボタンを置くAndroidアプリは多い。
`ShareActionProvider`、`ShareCompat`を使うと(ICS以降だけだが)非常に少ない手間で共有ボタンをリッチにできるため、かなり便利だと思う。
個人的にも便利なので、アプリ作成者はどんどん実装してほしい。