使用CameraX设置EXIF地理位置

问题描述 投票:0回答:3

如何使用 CameraX API 在图像 EXIF 中添加 Location 信息。我使用 https://codelabs.developers.google.com/codelabs/camerax-getting-started/#4.

创建了自己的应用程序

我筛选了https://developer.android.com/training/cameraxhttps://developer.android.com/jetpack/androidx/releases/exifinterface但没有找到任何指南。

exif android-camerax
3个回答
1
投票

如果你拍了一张照片,你就会覆盖

onImageSaved
。在那里您可以将 exif 数据写入您的照片。我只有Java版的,不过原理是一样的

 ExifInterface exif = null;
      try {
          exif = new ExifInterface(PhotoPath);
      } catch (IOException e) {
          e.printStackTrace();
      }
 exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, "location");

您可以在此处查找不同的标签。如何获取位置位于此处,如果您需要有关如何在 exif 中存储位置的更多信息,请查看此处


1
投票

您可以使用 Metadata.setLocation 方法设置位置


   val metadata = Metadata().apply {
            location = Location() // set the location here
        }

        val contentValues = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, System.currentTimeMillis())
            put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
            put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM)
        }
        val contentUri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
        val outputOptions = OutputFileOptions.Builder(contentResolver, contentUri, contentValues)
            .setMetadata(metadata)
            .build()


        imageCapture.takePicture(outputOptions, mainExecutor, object : OnImageSavedCallback {
            override fun onImageSaved(outputFileResults: OutputFileResults) {
              Log.d(TAG, "Photo URI ${outputFileResults.savedUri}")
 
            }

            override fun onError(exception: ImageCaptureException) {
                Log.e(TAG, "Error", exception)
            }
        })


0
投票

这是我想找到的答案: 使用 CameraX 时,会自动设置 EXIF 数据,但不会设置 GPS EXIF 标签,因为:

  • 需要权限才能访问位置
  • 获取位置的方法有多种,不同的选项对电池消耗有不同的影响,因此最好进行控制。

这是我在 onImageSaved() 回调中调用的函数:

fun setCurrentLocationInExif(context: Context, uri : Uri, fusedLocationClient : FusedLocationProviderClient){
    // check location permissions
    if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
        ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
    ) {
        throw(Exception("no location found"))
    }
    else {
        // get location (a new one if older than 60s)
        val locRequest = CurrentLocationRequest.Builder().setMaxUpdateAgeMillis(60000).build()
        fusedLocationClient.getCurrentLocation(locRequest, null)
            .addOnSuccessListener { location: Location? ->
                // Got last known location. In some rare situations this can be null. In that case we do not go further
                if (location != null){
                    Log.d(TAG, "latitude=${location.latitude}")
                    Log.d(TAG, "longitude=${location.longitude}")
                    val uriFd = context.contentResolver.openFileDescriptor(uri, "rw")
                    if (uriFd != null) {
                        val uriExif = ExifInterface(uriFd.fileDescriptor)
                        uriExif.setGpsInfo(location)
                        uriExif.saveAttributes()
                        uriFd.close()
                    }
                    else{
                        throw(Exception("Cannot find file for uri=$uri"))
                    }
                }
            }
    }
}

onImageSaved 中的调用:

override fun onImageSaved(output: ImageCapture.OutputFileResults){
    setCurrentLocationInExif(requireContext(), output.savedUri!!, fusedLocationClient)
}

fusedLocationClient 是在 Lateinit 之后在我的主活动 onCreate 中定义的(您需要在 gradle.build(app) 中激活 Play 服务/位置服务:

fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
© www.soinside.com 2019 - 2024. All rights reserved.