以编程方式拍照并返回文件名和路径

时间:2019-08-05 19:18:23

标签: android android-intent android-camera

我读了this,以便在单击按钮时打开Camera意向,并返回保存的图片文件和调用它的活动的路径,但是我的应用程序崩溃并重新启动无需打开相机的意图。

Manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:dist="http://schemas.android.com/apk/distribution"
          package="com.oryx.geoop">

<uses-feature android:name="android.hardware.camera"
                  android:required="true" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA"/>

<application android:theme="@style/AppTheme">
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths">
        </meta-data>
     </provider>

     <activity android:name=".AnotherActivity">
        <intent-filter>
            <action android:name="android.media.action.IMAGE_CAPTURE" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
     </activity>
</application>
</manifest>

xml/file_paths

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

Activity

class AnotherActivity : AppCompatActivity() {

    val REQUEST_TAKE_PHOTO = 1
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_another)
        // Grant permissions
        Dexter.withActivity(this)
            .withPermissions(
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.CAMERA
            )
            .withListener(object : MultiplePermissionsListener {
                override fun onPermissionRationaleShouldBeShown(
                    permissions: MutableList<PermissionRequest>?,
                    token: PermissionToken?
                ) {
                    /* ... */
                }
            })

        save_local.setOnClickListener { captureFromCamera(this) }
    }

    @Throws(IOException::class)
    private fun createImageFile(): File {
        val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
        val dir =
       """${getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)}/geoOp/"""
       val storageDir = File(dir)
        storageDir.mkdirs()

        return File.createTempFile(
            "JPEG_${timeStamp}_", /* prefix */
            ".jpg", /* suffix */
            storageDir /* directory */
        ).apply {
            // Save a file: path for use with ACTION_VIEW intents
            val currentPhotoPath = absolutePath
        }

    }

    private fun captureFromCamera(context: Context) {
        Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
            // Ensure that there's a camera activity to handle the intent
            takePictureIntent.resolveActivity(context.packageManager)?.also {
                // Create the File where the photo should go
                val photoFile: File? = try {
                    createImageFile()
                } catch (ex: IOException) {
                    // Error occurred while creating the File
                    null
                }
                // Continue only if the File was successfully created
                photoFile?.also {
                    val photoURI: Uri = FileProvider.getUriForFile(
                        this,
                        "com.oryx.geoop.fileprovider",
                        it
                    )
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
                    startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO)
                }
            }
        }
    }

    public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        // Result code is RESULT_OK only if the user captures an Image
        if (resultCode == Activity.RESULT_OK && resultCode == RESULT_OK) {
            Toast.makeText(this, "pic saved", Toast.LENGTH_SHORT).show()
            println("pic saved")
        }
    }
}

更新 由于getExternalStoragePublicDirectory在Android Q中已弃用,并由以下代码代替,如here所示:

Kotlin
val resolver = context.contentResolver
val contentValues = ContentValues().apply {
    put(MediaStore.MediaColumns.DISPLAY_NAME, "CuteKitten001")
    put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
    put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/PerracoLabs")
}

val uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)

      resolver.openOutputStream(uri).use {
        // TODO something with the stream
      }

如何在上面的代码中使用它,请注意此更新会返回Uri, while original code return文件以获取图像位置:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
       // return Uri
} else {
       // return file
}

0 个答案:

没有答案