Android 原生 ExifInterface 僅支援讀寫標準 EXIF 標籤(如 TAG_DATETIME、TAG_GPS_LATITUDE 等),**無法新增自定義 Tag**(如 setAttribute("name", "android") 會失效)。若需在 JPEG 檔案中嵌入任意 XML/JSON 資料且不影響圖片正常顯示,業界通用做法是:**C/C++ 層操作 JPEG 段落 + JNI 橋接**。
ExifInterface 內部硬編碼支援的標籤集合,未暴露擴充機制。// 伪代碼:向 JPEG 寫入自定義 APP2 段落
bool writeCustomAppSegment(const char* jpegPath, const char* tag, const char* value) {
// 1. 讀取整個 JPEG 到記憶體
// 2. 解析段落結構:SOI (0xFFD8) -> APP0/APP1... -> SOS (0xFFDA) -> 掃描資料 -> EOI (0xFFD9)
// 3. 在第一個掃描段落 (SOS) 前插入新 APP2 段落:
// Marker: 0xFFE2 (APP2)
// Length: 2 + tagLen + 1 + valueLen (含長度欄位本身2字節)
// Data: tag + '\0' + value
// 4. 重寫檔案
return true;
}
成熟開源庫推薦:
// NativeLib.cpp
#include
#include "exiv2/exiv2.hpp"
extern "C" JNIEXPORT jboolean JNICALL
Java_com_example_ImageMetaWriter_writeCustomTag(
JNIEnv* env, jclass clazz,
jstring jpegPath, jstring tag, jstring value) {
const char* path = env->GetStringUTFChars(jpegPath, nullptr);
const char* t = env->GetStringUTFChars(tag, nullptr);
const char* v = env->GetStringUTFChars(value, nullptr);
bool ok = false;
try {
Exiv2::Image::AutoPtr img = Exiv2::ImageFactory::open(path);
img->readMetadata();
Exiv2::XmpData& xmp = img->xmpData();
xmp[std::string(t)] = std::string(v); // 寫入 XMP 自定義標籤
img->writeMetadata();
ok = true;
} catch (...) { ok = false; }
env->ReleaseStringUTFChars(jpegPath, path);
env->ReleaseStringUTFChars(tag, t);
env->ReleaseStringUTFChars(value, v);
return ok;
}
public class ImageMetaWriter {
static { System.loadLibrary("native-lib"); }
public static native boolean writeCustomTag(String jpegPath, String tag, String value);
// 使用範例
public void embedXmlToImage(File imageFile, String xmlContent) {
boolean ok = writeCustomTag(imageFile.getAbsolutePath(), "CustomXml", xmlContent);
if (!ok) throw new RuntimeException("寫入自定義 Tag 失敗");
}
}
xmp:CustomNamespace,相容性優於私有 APP 段落。mmap 或分塊讀寫,避免 OOM。採用 JNI + exiv2 方案,即可突破 Android ExifInterface 的限制,實現靈活、穩健的圖片自定義元資料寫入,滿足專業級影像應用需求。