アプリのイメージ
カメラアプリで写真を撮って表示したい。
実装
レイアウト
ImageView
とボタンを設置しておく。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="300dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/next"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/imageView"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
cacheフォルダへの書き込みを許可する
外部のカメラアプリがアプリのcache
フォルダへ書き込み、アプリはそれを画面に表示する。
そのためAndroidManifest.xml
にcache
フォルダへのファイルの保存を許可設定を追加する。
<application ...>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider" />
</provider>
</application>
許可するフォルダは以下の設定で行なう。
<paths>
<cache-path name="cache" path="." />
</paths>
Fragment
フィールドにregisterForActivityResult
でActivityResultContracts.TakePicture()
のlauncherを作る。
private val viewModel: FirstViewModel by viewModels()
private var uri: Uri = Uri.EMPTY
private val takePicture = registerForActivityResult(ActivityResultContracts.TakePicture()) {
val context = context ?: return@registerForActivityResult
if (it) {
viewModel.loadImage(uri, context)
}
}
ViewModel
は以下の通り。
val image = MutableLiveData<Bitmap>()
fun loadImage(uri: Uri, context: Context) {
viewModelScope.launch {
image.value = ImageDecoder.decodeBitmap(
ImageDecoder.createSource(context.contentResolver, uri)
)
}
}
Fragmentに戻ってonCreateView
でViewModel
のimage
を監視して変更があったらレイアウトのImageView
にセット。
カメラアプリがアプリのcacheフォルダに一時的に保存するパスも作成しておく。
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
...
// カメラアプリが一時的に保存するパス
uri = FileProvider.getUriForFile(
requireContext(),
"${BuildConfig.APPLICATION_ID}.provider",
requireContext().cacheDir.toPath().resolve("${UUID.randomUUID()}.jpg").toFile())
viewModel.image.observe(viewLifecycleOwner) {
binding.imageView.setImageBitmap(it)
}
...
}
onViewCreated
でボタンクリック時にGetContent
のlauncherを呼び出す。
選択できるファイルのContent Typeを画像に絞っておく。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.button.setOnClickListener {
takePicture?.launch(uri)
}
}
\確かな知識を身に着けたい、Androidアプリ開発を学びたい人にオススメ!/