前回は、テキストファイルを Googleドライブに対して共有することができた。
正確にいえば、ファイルを受け付けるパッケージに対して共有できた、になるのかな?
気にしているのは intentを投げたときに logcatに出てくる例外。出てくるだけで動作としては問題ないので困っている。 grantUriPermission()で READ_URI_PERMISSION を与えると出なくなるので、さらに困っている。動作しないなら対策しようとするし、ログが消せないならあきらめるのだが、どちらもできてしまうからだ。
何から調べるとよいかわからないので、まずは intentからいってみよう。
Android にいくつ基本要素があるか知らないが、 intent はその中でもかなり上位に位置するだろう。
インテントとインテント フィルタ | Android デベロッパー | Android Developers
https://developer.android.google.cn/guide/components/intents-filters?hl=ja
前回は startActivity() を呼んだので、アクティビティの開始になる。特定のパッケージを指定しなくても、暗黙的インテントであればマッチするパッケージの候補を出してくれるのは助かるね。
それより前には startService() とか bindService() とかしたので、サービスの開始もやったことがあることになる。ブロードキャストはまだだな。
intent への設定項目は多数ある。
気になっていたのは setData() と putExtra()。どっちも intent先に渡すデータを設定しているように見えるのだが、違いが分からん。
読むと、データはまあデータで、エクストラは key-value のペアとのこと。前回の intentでは URIしか送るものはなかったのだが、それはデータではなくエクストラだった。
どこでその使い分けをするかというと、アクションくらいしかなさそうだ。。。と思ったのだが、下の例を見ていくと「明示的インテントの例」では送り先のパッケージを指定してデータを設定して startService()しているだけで、アクション指定はない。そういうやり方もあるのか。
ACTION_SEND を見ると、エクストラの記述がいろいろある。 ACTION_PICK は getData()と書いてあるので、送り元としては setData()してあげればよいということかな。公式というか共通というか、そういうアクションについてはそのページの Input のところを見てやればよいのだろう。
改めて ACTION_SEND を見よう。とにかく書いてあることが多い。
- Activity Action
- データを誰かに送信する
- データの配信先は特定されていない
- データの送信先をユーザに尋ねるのは、アクションの受信者次第
- SEND intentを立ち上げるとき chooserでくるんであげると、ユーザがデータの送信方法を選択するプロンプトが出てくる(通常はそうする)
- Input
- MIMEタイプ
- EXTRA_TEXT か EXTRA_STREAM + 送信データ
- EXTRA_TEXTの場合、MIMEは "text/plain"
- その場合、EXTRA_HTML_TEXT でクライアントがHTMLフォーマットでテキストを取得するようにもできる
- それ以外なら EXTRA_STREAM
- JELLY_BEAN(Android 4.1)以降であれば、データを setClipData()経由で送ることもできる
- コンテンツを共有するときに FLAG_GRANT_READ_URI_PERMISSIONを使用できる
- このアプローチを使用する場合、互換性のために EXTRA_TEXT か EXTRA_STREAM で同じデータを提供する必要がある。ClipDataを設定しない場合、 setActivity()を呼んだときにコピーされる。
- Oreo(Android 8)から、CATEGORY_TYPED_OPENABLEが渡された場合、EXTRA_STREAM または setClipData()を介して渡された URIsは openTypedAssetFileDescriptor()を使用するあっセットタイプファイルとしてのみ開くことができる
- 受信側が解釈できるオプションの標準エクストラは以下
- EXTRA_EMAIL, EXTRA_CC, EXTRA_BCC, EXTRA_SUBJECT
- Output
- 無し
- Constant Value
- "android.intent.action.SEND"
機械的に訳した。
EXTRA_TEXT や EXTRA_STREAM で渡す方法だけでなく、ClipData経由でも渡すことができるのが grantの例外と関わっているのだろう。
まず ClipDataだが、これはクリップボードのデータ、というわけではないようだ。というのも間違いなのかな。クリップボードに保存したデータは ClipData扱いになるから、結果としては同じで良いのかな?
intentに ClipDataを紐付ける関数として setClipData()があるが、ClipDataに含まれる URIに対して FLAG_GRANT_READ_URI_PERMISSION や FLAG_GRANT_WRITE_URI_PERMISSION が機能するそうだ。
つまり、今回のように ClipData を使うつもりがない場合には気にしなくてよいはずだ!という結論に至った。私の解釈が間違ってなければね。
01: fun sendIntent(view: View?) { 02: val filename = "myfile.txt" 03: val pathUri: Uri = FileProvider.getUriForFile( 04: this, 05: BuildConfig.APPLICATION_ID + ".fileprovider", 06: File(filesDir, filename) 07: ) 08: val shareIntent: Intent = Intent().apply { 09: action = Intent.ACTION_SEND 10: putExtra(Intent.EXTRA_STREAM, pathUri) 11: type = "plain/text" 12: } 13: val chooseIntent: Intent = Intent.createChooser(shareIntent, null) 14: // ClipDataを使う場合 15: // grantUriPermission("android", pathUri, Intent.FLAG_GRANT_READ_URI_PERMISSION) 16: startActivity(chooseIntent) 17: }
AndroidStudio というか IntelliJ というかはショートカットキーでコメントアウトすると行頭になるのがちょっときになるね。思わず手動でやってしまった。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。