のらぬこの日常を描くスマートフォン用の表示で見るのらぬこの日常を描くノージャンルのお役立ち情報やアニメとゲームの話、ソフトウェア開発に関する話などを中心としたブログです。技術・開発Tweetどうものらぬこです。今回は、androidアプリから端末内のファイルの扱いについての記事です。端末内ストレージ(内臓ストレージ、外部SDカード)のファイル操作(編集したり、コピーしたり、削除したり)機能の実装方法は、androidOSのファイルアクセス系APIの仕組みが、OS更新ごとに仕様が複雑怪奇化、API機能の制約が増加されたなどの理由により、以前(Kitkat以前)と比べると格段に面倒くさくなっています。今回は、その変革の軌跡をたどりながら、googleマジいい加減にしろよ●すぞ!っていう殺意にも似た感情を書いてきます。Kitkat以前(~4.3)アプリにPermissonさえ付与しておけば、内蔵ストレージ内のファイルもSDカード内のファイルは自由に読み書きできた時代。以外のディレクトリへの書き込みが実質不可能になる。「実質」と書きましたが、全く不可能だったわけではないようで、実は、LOLIPOPで話題に上がったストレージアクセスフレームワーク(SAF)という仕組み、実はAPIレベル19、つまりKitkatですでに実装されていたらしいのだが、機能が中途半端なせいで外部ストレージのファイルを自由に読み書きする仕組みとしては使い物にならなかったようだ。Permissionの設定の効力は及ばなくなる。記載があったとしても、アプリから上記ディレクトリ以外に書き込みを行なおうとした場合、無情にもSecurityExceptionが発生する。内蔵ストレージ内のファイル操作は、androidManifest.xml内にPermission設定をすれば従来のバージョンと同等の方法で読み書き可能。ちなみに、システムアプリ(端末標準搭載の削除できないアプリ)からはSDカード内のファイルも自由に書き込みが可能だった。Kitkat搭載端末には、ESファイルエクスプローラ等の優秀なファイル管理アプリよりも遥かに使いづらいアプリが標準添付されていたり。/etc配下に置かれているPermission関連の設定ファイルを手動で書き換えることで、回避可能。何の制約もなくKitkatでも行えるようになる。制限を回避するためにroot化した人も結構いたみたい。セキュリティーを向上するためとかいう大義名分を嘲笑うかのよう。昔、恒久的にroot化することなく、この制限を回避するためのツールを公開してた(消えてなければファイルも残っていると思う)。noranuk0.hatenablog.comかなり後発で公開したのだが、意外とダウンロード数もあり、需要はあったんでしょうね。いうAPIを利用することで、SDカード内のファイルも、ユーザが明示的に許可を出せば、自由に読み書きできるようになる。「ユーザが明示的に許可を出せば」というのがポイントで、アプリから書き込操作を行ってもよいSDカードのディレクトリを、「androidOSが用意しているディレクトリ選択画面」を使ってユーザが自分で設定しなければならない。このandroidが用意したディレクトリ選択画面、いきなりこれを出してもエンドユーザさんは何の事かサッパリ分からないような画面のため、アプリ側で操作方法の説明を記載したり、その辺の解説サイトに説明を丸投げしたりと、色々苦労があったみたい(あった)。エンドユーザにとっては大きな改善ではあったと思うが、新しく実装されたAPIは、従来のAPIとは全く互換性がなく、対応するにはアプリの再実装が必要で、開発側にとっては良いことばかりでもなかった。みたいなことをやらないといけない。考えても仕様バグみたいなこの制限は、Android7.0でようやく解消される。いって、インストール時にアプリが使う可能性のあるすべての権限をユーザに強制承認させるのではなく、アプリインストール後、いくつかの権限については、必要になったときにユーザに承認を求めるという方式に変更される。電話を掛ける操作や、カメラを使う操作、端末内ストレージを読み書きする操作などは、機能の利用前にユーザの明示的な承認が個別に必要となる。Permission設定を書いておくだけではだめで、権限が必要な操作の実行前に、権限を使用するためのリクエストをエンドユーザに承認してもらうためのダイアログを表示する必要があり、この部分はアプリ側で追加の実装が必要。対象のため、ひと手間かけて、そのための処理を追加実装する必要がある。}}エンドユーザにとっては、カメラや音声の録音、通話の発信等の悪用さえるとちょっと危険な香りのする権限を、アプリごとに個別に拒否することが出来るようになるというメリットがあり、世間的には割と歓迎された。SAFを使う必要がある。LOLIPOPで実装されたSAFは本当に黒歴史だと心底思う。N(7.0)SAFの仕様バグ、ファイルの移動ができない不具合がようやく解消される。android7.0が出てから2年ほど経つが、対応アプリはそんなに多くないのが実情のようで(僕が知らないだけかもしれないけど)。端末内のファイルを選択し、それを他のアプリで開くような操作に対応する場合(例えば、ファイル管理アプリで動画ファイルを選択して、それを動画再生アプリを開くときなど)、対象ファイルのパス名を指定することがこのバージョンから不可能になった。代わりに、呼び出し元アプリでContentProviderを実装して、そいつのスキーマを使えという事になっている。エンドユーザにとってはメリットなど一つもない、場合によってはデメリットしかない気がするのだけど、なんでこんなことしたのか理解不能。デメリットとしては、例えば以下のようなことが考えられる。ContentProviderで指定するパス名は呼び出し元アプリが自由に決められるようになっていて、ファイルシステム上同一のファイルに、毎回別のパスを割り当てることも、逆にファイルシステム上は別のファイルに、同一のパスを割り当てることも可能になっている。したがって、呼び出し元アプリの実装方法にもよるが、例えば、アプリから動画ファイルを開く場合、動画アプリ側のレジューム再生機能などに支障をきたす場合もある。スキーマが利用可能なのが唯一の救い。最近はandroidの最新情報を追いかけていないので、8.0でまた仕様が変わったとか9.0でさらに制約が増えるとかいうことがあるのかないのかとかは分からない。これ以上中途半端な仕様・制約の追加変更はやらんでいただきたいとは切に願う。記事内に埋め込まれたコードは、過去実装したアプリコードの一部をそのまま貼り付けているため、掲載したコード単独では不完全な部分が多くあり、そのままではおそらく動作しません。参考にされる場合は、不足していると思われる部分を各自補ってください。いうわけで、今回の記事は以上となります。お読みいただいてありがとうございました。今日は、とても軽くて、メモリーもほとんど...2017-05-18うわっ...私のmac、重すぎ...?ホイール操作のもたつきを完全に解消する方法とはどうも、のらぬこです。book、iMacなど...2016-11-06【android】firebaseをdebug版で有効化すると、アプリ権限周りに不具合が出る可能性ア...どうもこんにちは。V5今日、レジャーケースを買ってきました。(1)月別アーカイブはてなブログをはじめよう!noranuk0さんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。