<span style="font-size:18px;">需求: app调用照相机拍摄若干张图片,<span style="color:#FF0000;">在图库中不显示这些图片,避免被拷贝篡改</span>。 在以后有wifi的环境下上传到服务器。 要求判断出这些图片被篡改过?</span>
按照安卓的设计, 在拍照后MediaScanner会扫出手机的所有照片并在图库中显示出来。
备注:我考虑过使用图片Exif属性判断图片被篡改过, 后来发现有工具可以修改Exif属性, 所以exif这条路走不通。
三种实现方式:
名称 | 缓存到sqlite | 校验MD5 | 保存到隐藏目录 |
实现方式 | 将图片数据存到数据库一张表的blob字段里 | 拍摄照片后将图片完整路径, 图片的MD5值存储到应用的database里, 在传输图片前比较图片文件的MD5值。 | 在sdcard下建立层次比较深的目录, 最终以".nomedia"格式命名文件夹, 在Android系统里以.作前缀是隐藏文件夹。 |
优点 | 只有本应用能读写,安全性高。 | 通过比较MD5值,能判断出文件是否被篡改。 | 实现简单,在手机图库里找不到这些图片, 在文件管理器也找不到隐藏目录。 如果目录层级很深, 一般很难被发现。 |
缺点 | 适合小图片如缩略图 | 计算MD5时要读图片文件, IO操作费时间耗内存。 | 理解android系统的可以写工具软件找到隐藏目录。 |
第一种: 保存到sqlite的blob类型字段, 在建表时创建一个类型为blob的字段, 将图片数据保存到该字段。(在此不贴代码了, 找度娘)。
第二种: 计算MD5值, 也可以是其它算法的校验值, 就是用文件数据生成一个字符串。
md5示例代码:
- import java.security.MessageDigest;
- import java.io.FileInputStream;
- import java.io.InputStream;
- public class MD5 {
- private static final char HEX_DIGITS[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F' };
- public static void main(String[] args)
- {
- System.out.println(md5sum("/init.rc"));
- }
- public static String toHexString(byte[] b) {
- sb = new
- i = 0; i < b.length; i++) {
- >>>
- sb.append(HEX_DIGITS[b[i] & 0x0f]);
- }
- return sb.toString();
- }
- public static String md5sum(String filename) {
- InputStream fis;
- buffer = new
- numRead = 0;
- MessageDigest md5;
- try{
- fis = new
- md5 = MessageDigest.getInstance("MD5");
- numRead=fis.read(buffer)) >
- md5.update(buffer,0,numRead);
- }
- fis.close();
- return toHexString(md5.digest());
- } catch (Exception e) {
- System.out.println("error");
- return null;
- }
- }
- }
第三种: 保存到手机隐藏目录, 记住目录层级越深越隐蔽。请注意目录名".nomedia", “.”是隐藏目录的前缀, 目录名随便定义。
参考代码:
public String getBaseDir(Context context) {
String baseDir = null;
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
baseDir = Environment.getExternalStorageDirectory() + "/" + FILE_NAME + "/";
} else {
baseDir = context.getCacheDir().getAbsolutePath() + "/" + FILE_NAME + "/";
}
File basedir = new File(baseDir);
if (!basedir.exists()) {
basedir.mkdirs();
}
return baseDir;
}
File mediaStorageDir = new File(
FileManager.getInstance().getBaseDir(this), ".nomedia");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}