Android端Pydroid运行EXIF修改脚本遇PermissionError求助
解决方案:Android上批量更新WhatsApp图片EXIF数据
一、Pydroid环境下解决权限问题
1. 正确的权限申请方式
Pydroid自带专属的权限模块,无需使用Kivy的android包,替换成以下代码申请权限:
from pydroid.permissions import request_permissions, Permission # 申请读写外部存储权限 request_permissions([Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE])
2. 适配Android 10+存储限制
- 手动开启全文件访问权限:前往系统设置 → 应用 → Pydroid → 权限 → 开启「所有文件访问权限」,这是最简单的适配方式。
- 若开启后仍报错,说明Scoped Storage限制了直接路径写入,可临时将图片复制到Pydroid的私有缓存目录修改,再移回原路径。
3. 脚本优化
piexif仅支持JPG/JPEG格式的EXIF写入,PNG/GIF格式不支持,建议移除脚本中的对应判断:if fname.lower().endswith(('.jpg', '.jpeg')):- 添加异常捕获,避免单文件处理失败导致脚本终止:
try: exif_dict = piexif.load(img_path) # 后续EXIF修改逻辑 except Exception as e: print(f"处理{img_path}失败: {str(e)}") continue
二、Java方案(适配全Android版本)
如果Python方案仍受限于权限,可使用Java实现,直接适配Android存储机制:
1. 配置权限(AndroidManifest.xml)
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" /> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:minSdkVersion="30" />
2. 核心更新代码
使用Android原生ExifInterface类批量修改EXIF:
import android.media.ExifInterface; import android.os.Build; import android.os.Environment; import android.provider.Settings; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; public class ExifUpdateActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 先申请权限 requestPermissionsIfNeeded(); } private void requestPermissionsIfNeeded() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (!Environment.isExternalStorageManager()) { Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); startActivity(intent); } else { startUpdateExif(); } } else { if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100); } else { startUpdateExif(); } } } private void startUpdateExif() { String dirPath = "/storage/emulated/0/Android/media/com.whatsapp/WhatsApp/Media/WhatsApp Images"; File rootDir = new File(dirPath); if (!rootDir.exists()) return; SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss"); int updateCount = 1; scanDirectory(rootDir, dateFormat, updateCount); } private void scanDirectory(File dir, SimpleDateFormat dateFormat, int count) { File[] files = dir.listFiles(); if (files == null) return; for (File file : files) { if (file.isDirectory()) { scanDirectory(file, dateFormat, count); continue; } String fileName = file.getName().toLowerCase(); if (!fileName.endsWith(".jpg") && !fileName.endsWith(".jpeg")) continue; try { ExifInterface exif = new ExifInterface(file.getAbsolutePath()); String originalDate = exif.getAttribute(ExifInterface.TAG_DATETIME_ORIGINAL); if (originalDate == null || originalDate.isEmpty()) { long fileModifyTime = file.lastModified(); String newDateStr = dateFormat.format(new Date(fileModifyTime)); exif.setAttribute(ExifInterface.TAG_DATETIME_ORIGINAL, newDateStr); exif.saveAttributes(); System.out.println("[" + count + "] 已更新: " + file.getAbsolutePath() + " → " + newDateStr); count++; } } catch (IOException e) { e.printStackTrace(); System.out.println("处理失败: " + file.getAbsolutePath()); } } } }
内容的提问来源于stack exchange,提问作者Filip Szczybura
相关产品推荐
相关产品推荐

