allow removing EXIF values from the Properties dialog
This commit is contained in:
parent
0956159a76
commit
3ddd537d86
3 changed files with 84 additions and 56 deletions
|
@ -26,6 +26,8 @@ class PropertiesDialog() {
|
|||
private lateinit var mPropertyView: ViewGroup
|
||||
private lateinit var mResources: Resources
|
||||
private lateinit var mActivity: Activity
|
||||
private lateinit var mDialogView: View
|
||||
private var mCountHiddenItems = false
|
||||
|
||||
/**
|
||||
* A File Properties dialog constructor with an optional parameter, usable at 1 file selected
|
||||
|
@ -43,30 +45,49 @@ class PropertiesDialog() {
|
|||
mActivity = activity
|
||||
mInflater = LayoutInflater.from(activity)
|
||||
mResources = activity.resources
|
||||
val view = mInflater.inflate(R.layout.dialog_properties, null)
|
||||
mPropertyView = view.properties_holder!!
|
||||
mDialogView = mInflater.inflate(R.layout.dialog_properties, null)
|
||||
mCountHiddenItems = countHiddenItems
|
||||
mPropertyView = mDialogView.properties_holder!!
|
||||
addProperties(path)
|
||||
|
||||
val fileDirItem = FileDirItem(path, path.getFilenameFromPath(), activity.getIsPathDirectory(path))
|
||||
val builder = AlertDialog.Builder(mActivity)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
|
||||
if (!path.startsWith("content://")) {
|
||||
builder.setNeutralButton(R.string.remove_exif, null)
|
||||
}
|
||||
|
||||
builder.create().apply {
|
||||
mActivity.setupDialogStuff(mDialogView, this, R.string.properties)
|
||||
getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener {
|
||||
removeEXIF(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addProperties(path: String) {
|
||||
val fileDirItem = FileDirItem(path, path.getFilenameFromPath(), mActivity.getIsPathDirectory(path))
|
||||
addProperty(R.string.name, fileDirItem.name)
|
||||
addProperty(R.string.path, fileDirItem.getParentPath())
|
||||
addProperty(R.string.size, "…", R.id.properties_size)
|
||||
|
||||
ensureBackgroundThread {
|
||||
val fileCount = fileDirItem.getProperFileCount(activity, countHiddenItems)
|
||||
val size = fileDirItem.getProperSize(activity, countHiddenItems).formatSize()
|
||||
val fileCount = fileDirItem.getProperFileCount(mActivity, mCountHiddenItems)
|
||||
val size = fileDirItem.getProperSize(mActivity, mCountHiddenItems).formatSize()
|
||||
|
||||
val directChildrenCount = if (fileDirItem.isDirectory) {
|
||||
fileDirItem.getDirectChildrenCount(activity, countHiddenItems).toString()
|
||||
fileDirItem.getDirectChildrenCount(mActivity, mCountHiddenItems).toString()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
activity.runOnUiThread {
|
||||
(view.findViewById<LinearLayout>(R.id.properties_size).property_value as TextView).text = size
|
||||
this.mActivity.runOnUiThread {
|
||||
(mDialogView.findViewById<LinearLayout>(R.id.properties_size).property_value as TextView).text = size
|
||||
|
||||
if (fileDirItem.isDirectory) {
|
||||
(view.findViewById<LinearLayout>(R.id.properties_file_count).property_value as TextView).text = fileCount.toString()
|
||||
(view.findViewById<LinearLayout>(R.id.properties_direct_children_count).property_value as TextView).text = directChildrenCount.toString()
|
||||
(mDialogView.findViewById<LinearLayout>(R.id.properties_file_count).property_value as TextView).text = fileCount.toString()
|
||||
(mDialogView.findViewById<LinearLayout>(R.id.properties_direct_children_count).property_value as TextView).text =
|
||||
directChildrenCount.toString()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,27 +96,27 @@ class PropertiesDialog() {
|
|||
val uri = MediaStore.Files.getContentUri("external")
|
||||
val selection = "${MediaStore.MediaColumns.DATA} = ?"
|
||||
val selectionArgs = arrayOf(path)
|
||||
val cursor = activity.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
val cursor = mActivity.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
cursor?.use {
|
||||
if (cursor.moveToFirst()) {
|
||||
val dateModified = cursor.getLongValue(MediaStore.Images.Media.DATE_MODIFIED) * 1000L
|
||||
updateLastModified(activity, view, dateModified)
|
||||
updateLastModified(mActivity, mDialogView, dateModified)
|
||||
} else {
|
||||
updateLastModified(activity, view, fileDirItem.getLastModified(activity))
|
||||
updateLastModified(mActivity, mDialogView, fileDirItem.getLastModified(mActivity))
|
||||
}
|
||||
}
|
||||
|
||||
val exif = if (isNougatPlus() && activity.isPathOnOTG(fileDirItem.path)) {
|
||||
ExifInterface((activity as BaseSimpleActivity).getFileInputStreamSync(fileDirItem.path)!!)
|
||||
val exif = if (isNougatPlus() && mActivity.isPathOnOTG(fileDirItem.path)) {
|
||||
ExifInterface((mActivity as BaseSimpleActivity).getFileInputStreamSync(fileDirItem.path)!!)
|
||||
} else if (isNougatPlus() && fileDirItem.path.startsWith("content://")) {
|
||||
try {
|
||||
ExifInterface(activity.contentResolver.openInputStream(Uri.parse(fileDirItem.path))!!)
|
||||
ExifInterface(mActivity.contentResolver.openInputStream(Uri.parse(fileDirItem.path))!!)
|
||||
} catch (e: Exception) {
|
||||
return@ensureBackgroundThread
|
||||
}
|
||||
} else if (activity.isRestrictedSAFOnlyRoot(path)) {
|
||||
} else if (mActivity.isRestrictedSAFOnlyRoot(path)) {
|
||||
try {
|
||||
ExifInterface(activity.contentResolver.openInputStream(activity.getAndroidSAFUri(path))!!)
|
||||
ExifInterface(mActivity.contentResolver.openInputStream(mActivity.getAndroidSAFUri(path))!!)
|
||||
} catch (e: Exception) {
|
||||
return@ensureBackgroundThread
|
||||
}
|
||||
|
@ -105,14 +126,14 @@ class PropertiesDialog() {
|
|||
|
||||
val latLon = FloatArray(2)
|
||||
if (exif.getLatLong(latLon)) {
|
||||
activity.runOnUiThread {
|
||||
mActivity.runOnUiThread {
|
||||
addProperty(R.string.gps_coordinates, "${latLon[0]}, ${latLon[1]}")
|
||||
}
|
||||
}
|
||||
|
||||
val altitude = exif.getAltitude(0.0)
|
||||
if (altitude != 0.0) {
|
||||
activity.runOnUiThread {
|
||||
mActivity.runOnUiThread {
|
||||
addProperty(R.string.altitude, "${altitude}m")
|
||||
}
|
||||
}
|
||||
|
@ -125,58 +146,52 @@ class PropertiesDialog() {
|
|||
addProperty(R.string.files_count, "…", R.id.properties_file_count)
|
||||
}
|
||||
fileDirItem.path.isImageSlow() -> {
|
||||
fileDirItem.getResolution(activity)?.let { addProperty(R.string.resolution, it.formatAsResolution()) }
|
||||
fileDirItem.getResolution(mActivity)?.let { addProperty(R.string.resolution, it.formatAsResolution()) }
|
||||
}
|
||||
fileDirItem.path.isAudioSlow() -> {
|
||||
fileDirItem.getDuration(activity)?.let { addProperty(R.string.duration, it) }
|
||||
fileDirItem.getTitle(activity)?.let { addProperty(R.string.song_title, it) }
|
||||
fileDirItem.getArtist(activity)?.let { addProperty(R.string.artist, it) }
|
||||
fileDirItem.getAlbum(activity)?.let { addProperty(R.string.album, it) }
|
||||
fileDirItem.getDuration(mActivity)?.let { addProperty(R.string.duration, it) }
|
||||
fileDirItem.getTitle(mActivity)?.let { addProperty(R.string.song_title, it) }
|
||||
fileDirItem.getArtist(mActivity)?.let { addProperty(R.string.artist, it) }
|
||||
fileDirItem.getAlbum(mActivity)?.let { addProperty(R.string.album, it) }
|
||||
}
|
||||
fileDirItem.path.isVideoSlow() -> {
|
||||
fileDirItem.getDuration(activity)?.let { addProperty(R.string.duration, it) }
|
||||
fileDirItem.getResolution(activity)?.let { addProperty(R.string.resolution, it.formatAsResolution()) }
|
||||
fileDirItem.getArtist(activity)?.let { addProperty(R.string.artist, it) }
|
||||
fileDirItem.getAlbum(activity)?.let { addProperty(R.string.album, it) }
|
||||
fileDirItem.getDuration(mActivity)?.let { addProperty(R.string.duration, it) }
|
||||
fileDirItem.getResolution(mActivity)?.let { addProperty(R.string.resolution, it.formatAsResolution()) }
|
||||
fileDirItem.getArtist(mActivity)?.let { addProperty(R.string.artist, it) }
|
||||
fileDirItem.getAlbum(mActivity)?.let { addProperty(R.string.album, it) }
|
||||
}
|
||||
}
|
||||
|
||||
if (fileDirItem.isDirectory) {
|
||||
addProperty(R.string.last_modified, fileDirItem.getLastModified(activity).formatDate(activity))
|
||||
addProperty(R.string.last_modified, fileDirItem.getLastModified(mActivity).formatDate(mActivity))
|
||||
} else {
|
||||
addProperty(R.string.last_modified, "…", R.id.properties_last_modified)
|
||||
try {
|
||||
addExifProperties(path, activity)
|
||||
addExifProperties(path, mActivity)
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e)
|
||||
mActivity.showErrorToast(e)
|
||||
return
|
||||
}
|
||||
|
||||
if (activity.baseConfig.appId.removeSuffix(".debug") == "com.simplemobiletools.filemanager.pro") {
|
||||
if (mActivity.baseConfig.appId.removeSuffix(".debug") == "com.simplemobiletools.filemanager.pro") {
|
||||
addProperty(R.string.md5, "…", R.id.properties_md5)
|
||||
ensureBackgroundThread {
|
||||
val md5 = if (activity.isRestrictedSAFOnlyRoot(path)) {
|
||||
activity.contentResolver.openInputStream(activity.getAndroidSAFUri(path))?.md5()
|
||||
val md5 = if (mActivity.isRestrictedSAFOnlyRoot(path)) {
|
||||
mActivity.contentResolver.openInputStream(mActivity.getAndroidSAFUri(path))?.md5()
|
||||
} else {
|
||||
File(path).md5()
|
||||
}
|
||||
|
||||
activity.runOnUiThread {
|
||||
mActivity.runOnUiThread {
|
||||
if (md5 != null) {
|
||||
(view.findViewById<LinearLayout>(R.id.properties_md5).property_value as TextView).text = md5
|
||||
(mDialogView.findViewById<LinearLayout>(R.id.properties_md5).property_value as TextView).text = md5
|
||||
} else {
|
||||
view.findViewById<LinearLayout>(R.id.properties_md5).beGone()
|
||||
mDialogView.findViewById<LinearLayout>(R.id.properties_md5).beGone()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this, R.string.properties)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateLastModified(activity: Activity, view: View, timestamp: Long) {
|
||||
|
@ -196,8 +211,9 @@ class PropertiesDialog() {
|
|||
mActivity = activity
|
||||
mInflater = LayoutInflater.from(activity)
|
||||
mResources = activity.resources
|
||||
val view = mInflater.inflate(R.layout.dialog_properties, null)
|
||||
mPropertyView = view.properties_holder
|
||||
mDialogView = mInflater.inflate(R.layout.dialog_properties, null)
|
||||
mCountHiddenItems = countHiddenItems
|
||||
mPropertyView = mDialogView.properties_holder
|
||||
|
||||
val fileDirItems = ArrayList<FileDirItem>(paths.size)
|
||||
paths.forEach {
|
||||
|
@ -219,15 +235,15 @@ class PropertiesDialog() {
|
|||
val fileCount = fileDirItems.sumByInt { it.getProperFileCount(activity, countHiddenItems) }
|
||||
val size = fileDirItems.sumByLong { it.getProperSize(activity, countHiddenItems) }.formatSize()
|
||||
activity.runOnUiThread {
|
||||
(view.findViewById<LinearLayout>(R.id.properties_size).property_value as TextView).text = size
|
||||
(view.findViewById<LinearLayout>(R.id.properties_file_count).property_value as TextView).text = fileCount.toString()
|
||||
(mDialogView.findViewById<LinearLayout>(R.id.properties_size).property_value as TextView).text = size
|
||||
(mDialogView.findViewById<LinearLayout>(R.id.properties_file_count).property_value as TextView).text = fileCount.toString()
|
||||
}
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this, R.string.properties)
|
||||
activity.setupDialogStuff(mDialogView, this, R.string.properties)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,6 +282,20 @@ class PropertiesDialog() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun removeEXIF(path: String) {
|
||||
ConfirmationDialog(mActivity, "", R.string.remove_exif_confirmation) {
|
||||
try {
|
||||
ExifInterface(path).removeValues()
|
||||
mActivity.toast(R.string.exif_removed)
|
||||
|
||||
mPropertyView.properties_holder.removeAllViews()
|
||||
addProperties(path)
|
||||
} catch (e: Exception) {
|
||||
mActivity.showErrorToast(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSameParent(fileDirItems: List<FileDirItem>): Boolean {
|
||||
var parent = fileDirItems[0].getParentPath()
|
||||
for (file in fileDirItems) {
|
||||
|
|
|
@ -30,7 +30,8 @@ fun ExifInterface.copyTo(destination: ExifInterface, copyOrientation: Boolean =
|
|||
ExifInterface.TAG_ISO_SPEED_RATINGS,
|
||||
ExifInterface.TAG_MAKE,
|
||||
ExifInterface.TAG_MODEL,
|
||||
ExifInterface.TAG_WHITE_BALANCE)
|
||||
ExifInterface.TAG_WHITE_BALANCE
|
||||
)
|
||||
|
||||
if (copyOrientation) {
|
||||
attributes.add(ExifInterface.TAG_ORIENTATION)
|
||||
|
@ -49,9 +50,7 @@ fun ExifInterface.copyTo(destination: ExifInterface, copyOrientation: Boolean =
|
|||
}
|
||||
}
|
||||
|
||||
fun ExifInterface.removeValues(path: String) {
|
||||
val newExif = ExifInterface(path)
|
||||
|
||||
fun ExifInterface.removeValues() {
|
||||
val attributes = arrayListOf(
|
||||
// ExifInterface.TAG_ORIENTATION, // do not remove the orientation, it could lead to unexpected behaviour at displaying the file
|
||||
ExifInterface.TAG_APERTURE_VALUE,
|
||||
|
@ -80,10 +79,10 @@ fun ExifInterface.removeValues(path: String) {
|
|||
)
|
||||
|
||||
attributes.forEach {
|
||||
newExif.setAttribute(it, null)
|
||||
setAttribute(it, null)
|
||||
}
|
||||
|
||||
newExif.saveAttributes()
|
||||
saveAttributes()
|
||||
}
|
||||
|
||||
fun ExifInterface.getExifProperties(): String {
|
||||
|
|
|
@ -254,7 +254,6 @@
|
|||
<string name="altitude">Altitude</string>
|
||||
<string name="remove_exif">Remove EXIF</string>
|
||||
<string name="remove_exif_confirmation">Are you sure you want to remove EXIF values like GPS coordinates, camera model etc?</string>
|
||||
<string name="remove_exif_confirmation">Are you sure you want to remove EXIF values like GPS coordinates, camera model etc?</string>
|
||||
<string name="exif_removed">EXIF values removed successfully</string>
|
||||
|
||||
<!-- Color customization -->
|
||||
|
|
Loading…
Reference in a new issue