val contentValues = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, "view.png")
put(MediaStore.Images.Media.MIME_TYPE, "image/png")
put(MediaStore.Images.Media.IS_PENDING, "1")
}
val contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
contentResolver.run {
insert(contentUri, contentValues)?.let{ uri ->
openOutputStream(uri)?.let{ stream ->
val view = findViewById<View>(R.id.some_view)
view.drawToBitmap().compress(Bitmap.CompressFormat.PNG, 100, stream )
stream.close()
contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0)
update( uri, contentValues, null, null)
}
}
}
View のビットマップを取得するには Android KTX coreの drawToBitmap()
メソッドを使う。
API 28から getDrawingCache()
は非推奨となっている
MediaStore
クラスで外部ストレージのURIを取得する。
MediaStore
クラスを利用すると権限の認証は不要。
外部ストレージURIとファイルのMimeTypeを指定し contentResolver
でインサートする。
contentResolver
オブジェクトはコンテンツプロバイダとの仲介を行ってくれる。Androidのコンテンツプロバイダ APIはファイル情報などをDBで保持している(おそらくSQLite3)
保存するファイル情報のインサートが成功すれば、保存先URIが返ってくる。
URIは content://media/external/images/media/1
のような形式。
ストレージへのファイルの書込はURIに対し openOutPutStream
オブジェクトが行う。
書込後にファイル情報DBをアップデートすることで、Photoアプリなど他のアプリで即座に画像を表示できる。
ファイル名が被ったら末尾に連番が入る。
上記の書き方だと、成功・失敗のメッセージもなくPictureフォルダにPNGファイルが保存されるのみ。
ただし、Android Q 未満は MediaStore
を使えないので、Android P以下にも対応するには参考としたStack Overflowの回答のようにバージョン毎に処理を変える必要がある。
参考サイト
【Android】Viewのスクリーンショットを撮影してギャラリーアプリで見れるようにする - Qiita
最終的にこの記事のコードとちょっと違うだけになりました。
[Android] view.getDrawingCache()がDeprecatedになったのでPixelCopyでスクリーンキャプチャを撮る | Android開発知識ゼロ人間の生活
java - How to save an image in Android Q using MediaStore? - Stack Overflow
アンドロイド - MediaStoreにメディアファイルを保存する方法
公式リファレンス
View.getDrawingCache() | Android Developers
コンテンツ プロバイダの基本 | Android Developers
参考にしたが使わなかった情報
Canvasを利用して、Viewのビットマップを取得するコードが掲載されている。
「Android」Viewの内容をBitmapの保存方法 | | 最新IT技術情報_arkgame.com