iT邦幫忙

2021 iThome 鐵人賽

DAY 11
0
Mobile Development

重新瞭解Android硬體控制系列 第 11

110/11 - 把照片儲存在Pictures/應用程式名稱資料夾 - 1

不太可能每個專案都那麼爽,可以把相片儲存在內部儲存空間/Android/data/packageName/files/,所以還是要練習把檔案儲存在內部儲存空間/Pictures/應用程式名稱資料夾/

100/09的畫面繼續,同樣新增一顆MaterialButtonAppCompatImageView

<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".CropLensActivity">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.button.MaterialButton
            android:id="@+id/aclMbCreatePackageNamePicture"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="4dp"
            android:layout_marginEnd="8dp"
            android:padding="8dp"
            android:text="在應用程式資料夾建立照片"
            android:textAllCaps="false"
            app:autoSizeTextType="uniform"
            app:layout_constraintBottom_toTopOf="@+id/aclIvPackageNamePicture"
            app:layout_constraintDimensionRatio="5:1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_chainStyle="packed" />

        <androidx.appcompat.widget.AppCompatImageView
            android:id="@+id/aclIvPackageNamePicture"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_margin="4dp"
            android:layout_marginTop="4dp"
            app:layout_constraintBottom_toTopOf="@+id/aclMbCreatePhonePicture"
            app:layout_constraintDimensionRatio="4:3"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/aclMbCreatePackageNamePicture"
            tools:src="@tools:sample/backgrounds/scenic" />

        <com.google.android.material.button.MaterialButton
            android:id="@+id/aclMbCreatePhonePicture"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="4dp"
            android:layout_marginEnd="8dp"
            android:padding="8dp"
            android:text="在圖片資料夾建立照片"
            android:textAllCaps="false"
            app:autoSizeTextType="uniform"
            app:layout_constraintBottom_toTopOf="@+id/aclIvPhonePicture"
            app:layout_constraintDimensionRatio="5:1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/aclIvPackageNamePicture" />

        <androidx.appcompat.widget.AppCompatImageView
            android:id="@+id/aclIvPhonePicture"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_margin="4dp"
            android:layout_marginTop="4dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintDimensionRatio="4:3"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/aclMbCreatePhonePicture"
            tools:src="@tools:sample/backgrounds/scenic" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

我們拍照前先建立應用程式資料夾來存放相片,以下是建立資料夾的範例

private fun isCreateFolder(folderPath: File): Boolean {
    val file = File(folderPath, "AndroidSystem")
    return if (file.exists()) {
        true
    } else file.mkdir()
}

拍照點擊事件,先判斷資料夾有沒有建立,有的話就繼續執行

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_crop_lens)

    aclMbCreatePhonePicture.setOnClickListener {
    
        if (!isCreateFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES))) {
            Log.d("maho", "資料夾建立失敗")
            return@setOnClickListener
        }
        
        val phoneFile = File(
            Environment.getExternalStoragePublicDirectory("${Environment.DIRECTORY_PICTURES}/AndroidSystem"),
            "002.jpg"
        )
        
        val uri = getPictureUri(phoneFile)
        
        takePictureResultLauncher.launch(uri)
    }
}

拍照完後一樣重新整理,讓相簿能顯示我們儲存的檔案

private val takePictureResultLauncher =
    registerForActivityResult(ActivityResultContracts.TakePicture()) { isTakePicture ->
        
        if (!isTakePicture) {
            Log.d("maho", "拍照建立檔案失敗")
            return@registerForActivityResult
        }
        
        val packageNameFile =
            File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "001.jpg")
        val phoneFile = File(
            Environment.getExternalStoragePublicDirectory("${Environment.DIRECTORY_PICTURES}/AndroidSystem"),
            "002.jpg"
        )
        
        MediaScannerConnection.scanFile(
            this,
            arrayOf(packageNameFile.toString(), phoneFile.toString()),
            null
        ) { path, uri ->
            Log.d("maho", "${Thread.currentThread().name}  path: $path / uri: $uri")
        }
        
        aclIvPackageNamePicture.setImageURI(getPictureUri(packageNameFile))
        
        aclIvPhonePicture.setImageURI(null)
        aclIvPhonePicture.setImageURI(getPictureUri(phoneFile))
    }

感覺很完美對吧?但有個問題是getExternalStoragePublicDirectoryAndroid 11也被標記棄用,所以我們要換個方式寫。


上一篇
110/10 - Intent.ACTION_MEDIA_SCANNER_SCAN_FILE棄用
下一篇
110/12 - 把照片儲存在Pictures/應用程式名稱資料夾 - 2
系列文
重新瞭解Android硬體控制19

尚未有邦友留言

立即登入留言