共有アクションに応答できるActivityを管理し、ユーザの選択履歴を記録することで
"よく使う共有アイテム"のような機能を提供します。
●動作イメージ
初回は「共有アクション」のみ表示。一度でも共有アイテムを選択すると、選択履歴として蓄積され"よく使う共有アイテム"
には専用のUIが用意されます。
メニューアイテムがoverflowの場合は、共有可能なアイテムをサブメニューとして表示
します。
共有可能なアイテムは"よく使う順"にソートされた状態でリスト表示されます。
●使い方
ShareActionProviderはメニューアイテムと関連付けされます。メニューアイテムがActionItemとして表示されているか、OverflowItemとして表示されて
いるかによって若干振る舞いが変化します。
しかし、開発者はメニューアイテムがActionItem状態かOverflowItem状態かを意識する
必要はありません。
状態の違いからくる動作差異はShareActionProviderによってカプセル化されています。
ShareActionProviderを使う手順はシンプルです。
1. メニューアイテムにShareActionProviderを関連付ける
2. メニュー生成時にShareActionProviderインスタンスを取得する
3. 共有IntentをShareActionProviderに設定する
1はメニューリソースで指定可能です。
関連付けにはitem要素のandroid:actionProviderClass属性で行います。
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_item_share_action" android:showAsAction="always" android:title="@string/menu_share1" android:actionProviderClass="android.widget.ShareActionProvider" /> </menu>2はメニュー生成時のコールバックメソッドonCreateOptionsMenuで可能です。
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_share_action, menu); MenuItem shareAction = menu.findItem(R.id.menu_item_share_action); mShareActionProvider = (ShareActionProvider)shareAction.getActionProvider(); return true; }3はShareActionProvider.setShareIntent(intent)メソッドで可能です。
下記は0-9が押されたら、キーラベルを共有するコードです。
Cキーが押された場合は共有インテントをクリアします。
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (KeyEvent.KEYCODE_9 >= keyCode && keyCode >= KeyEvent.KEYCODE_0) { Intent sharedIntent = new Intent(Intent.ACTION_SEND); sharedIntent.setType("text/plain"); sharedIntent.putExtra( Intent.EXTRA_TEXT, String.valueOf(event.getDisplayLabel())); doShare(sharedIntent); } else if (KeyEvent.KEYCODE_C == keyCode) { doShare(null); } return super.onKeyDown(keyCode, event); } private void doShare(Intent intent) { mShareActionProvider.setShareIntent(intent); }ShareActionProviderはsetShareIntentを契機に共有アイテムのリストを更新します。
setShareIntentにnullが渡された場合は、共有アイテム無しとして扱われます。
この状態ではActionItemを押下しても無反応。
setShareIntentに共有Intentを設定すると共有アイテムリストが自動更新される。
setShareIntentにnullを設定すると共有アイテム無しとなる。
ちなみに、"よく使う共有アイテム"を長押下すると共有アイテムリストが表示される機能
も搭載されています。
●堅牢性
ShareActionProviderは堅牢性も備えています。例えば、"よく使う共有アイテム"の対象となっているパッケージが無効化されていた場合、
別のよく使う共有アイテムを表示するようになっています。
しかし、共有アイテムリスト表示中にバックグラウンドへ一時退避して、リストに含まれ
るパッケージを無効化した後にアプリを復帰させると、共有アイテムリストに含まれるパ
ッケージは表示され続け、これを選択するとActivityNotFound例外で強制終了します。
ただし、これは特異な手順となるため対応の必要性はほぼ無いでしょう。
●注意
通常、ActionItemが選択されるとonOptionsItemSelectedが呼ばれます。しかし、ActionItemのShareActionProviderのアイテムを選択しても、onOptionsItemSelected
は呼ばれません。※メニューがoverflow状態の場合は呼ばれます。
共有アイテムの中に同じパッケージ名をもつアイテムが複数ある場合は注意が必要です。
例えば、"android.intent.action.VIEW"には下記2つのActivityが反応します。
- com.android.development/com.android.development.AppHwPref
- com.android.development/com.android.development.ProcessInfo
"よく使う共有アイテム"にAppHwPrefが登録されていると仮定します。
あなたはこれを選択してAppHwPrefを起動します。これは正しく起動できるはずです。
しかし、もう一度これを選択した場合は"ProcessInfo"が起動されます。
ユーザの意図に反する動作のように見えますが、、、
ShareActionProviderは"よく使う共有アイテム"に属するコンポーネントのパッケージが
複数ある場合は、選択する都度スイッチするような動作になっています。
●その他
ShareActionProviderはどのようにして、共有アクション履歴を管理しているのでしょうか?これは、アプリローカルに選択履歴をxmlファイルとして保存することで実現しています。
デフォルトでは、/data/data/<ApplicationPackageName>/files配下にshare_history.xml
の名前で保存されます。
share_history.xmlは下記のような内容になっています。
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?> <historical-records> <historical-record activity="com.android.calendar/com.android.calendar.EventInfoActivity" time="1340782021420" weight="1.0" /> <historical-record activity="com.android.development/com.android.development.ProcessInfo" time="1340783164738" weight="1.0" /> <historical-record activity="com.android.development/com.android.development.ProcessInfo" time="1340783171474" weight="1.0" /> <historical-record activity="com.android.development/com.android.development.AppHwPref" time="1340783189589" weight="1.0" /> <historical-record activity="com.android.development/com.android.development.ProcessInfo" time="1340783191079" weight="1.0" /> <historical-record activity="com.android.development/com.android.development.AppHwPref" time="1340783195569" weight="1.0" /> <historical-record activity="com.android.development/com.android.development.ProcessInfo" time="1340783197179" weight="1.0" /> </historical-records>共有アイテムが選択されるとhistorical-record要素が末尾に追加されていきます。
選択履歴のxmlファイルはsetShareHistoryFileNameメソッドで指定可能です。
共有アクションを実装したい場合、ShareActionProviderは使いやすさも確保できる便利
なクラスといえそうです。
以上です。