Android 文件加密解密(AES)

复制代码
private static final String ALGORITHM = "AES";

=========================文件加密=================================

复制代码
/**
 * 文件加密
 * @param secretKey 文件加密密钥
 * @param oldFiles 原始文件列表,需要加密的
 * @param newFiles 构造加密后的文件列表
 *(选择多个或者单个)多个文件加密
 */
@RequiresApi(api = Build.VERSION_CODES.O)
public  void newEncryptFiles(String secretKey, List<File> oldFiles, List<File> newFiles) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException {
    // 使用密钥字符串生成秘密密钥
    SecretKey secretKeySpec = new SecretKeySpec(secretKey.getBytes(), ALGORITHM);
    // 获取 AES 加密算法的实例
    Cipher cipher = Cipher.getInstance(ALGORITHM);
    // 使用秘密密钥初始化密码 cipher,设置为加密模式
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
    //循环复制文件
    curr = 1;
    for (int i = 0; i < oldFiles.size(); i++) {
        File oldFile = oldFiles.get(i);
        File newFile = newFiles.get(i);
        long m = oldFiles.get(i).length();
        int n = (int)(m/100);
        int s = 0;//每一份的进度
        // 创建输入流,读取源文件
        try (InputStream inputStream = new FileInputStream(oldFile);
             // 创建输出流,写入加密文件
             OutputStream outputStream = new FileOutputStream(newFile);
             // 创建密码输出流,连接到输出流,并使用密码 cipher 进行加密
             CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, cipher)
        ) {
            // 缓冲区大小
            byte[] buffer = new byte[4096];
            int bytesRead;
            // 读取源文件内容到缓冲区
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                // 将加密后的数据写入加密文件
                cipherOutputStream.write(buffer, 0, bytesRead);
                s += 1024;
                if(s >= n){//进度+1
                    handler.sendEmptyMessage(MSG_COPY_RUNNING);
                    prog ++;
                    s = 0;
                }
            }
        }
    }


}

=========================文件解密=========================

复制代码
SecretKey secretKeySpec = new SecretKeySpec("sin-17214455-@@@".getBytes(), ALGORITHM);
Cipher cipher = null;
try {
    cipher = Cipher.getInstance(ALGORITHM + "/ECB/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
    //获取源加密文件或文件夹路径
    File  encryptFile= new File(item.getPath() + File.separator +     item.getEncrypted_name());
    //获取目标解密文件或文件夹路径,解密过后生成的名称original_name
    File newFile = new File(item.getNewPath(), "original_name");
    // 创建输入流,读取加密文件
    FileInputStream inputStream = new FileInputStream(encryptFile);
    // 创建输出流,写入解密文件
    FileOutputStream outputStream = new FileOutputStream(newFile);
    // 创建密码输出流,连接到输出流,并使用密码 cipher 进行加密
    CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher);
    // 缓冲区大小
    byte[] buffer = new byte[4096];
    int bytesRead;
    // 读取源文件内容到缓冲区
    while ((bytesRead = cipherInputStream.read(buffer)) != -1) {
        // 将加密后的数据写入解密文件
        outputStream.write(buffer, 0, bytesRead);

    }
    outputStream.close();
    inputStream.close();
    cipherInputStream.close();
    if (!newFile.exists()) {
        newFile.createNewFile();
    }
   
    if (!newFile.getParentFile().exists()) {
        newFile.getParentFile().mkdirs();
    }
  //解密到这里就结束了打开文件,这里就根据自己的需求而定。下面是我自己的一个需求。
 // 打开文件,调用系统的打开选择的图片,text文件或者其他
    FileUtil.openFile(view.getContext(), newFile, ext);
} catch (IOException e) {
    throw new RuntimeException(e);
} catch (NoSuchFileToOpenException e) {
    ToastUtil.errorToast(view.getContext(), e.getMessage());
    throw new RuntimeException(e);
} catch (NoSuchPaddingException e) {
    throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
    throw new RuntimeException(e);
} catch (InvalidKeyException e) {
    throw new RuntimeException(e);
}
复制代码
/**
 * 调用系统应用打开文件
 * @param context context
 * @param file file对象
 * @param ext 扩展名()
 * @throws NoSuchFileToOpenException 没有文件异常
 */
public static void openFile(Context context, File file,String ext) throws NoSuchFileToOpenException {
    if(! file.exists()){
        throw new NoSuchFileToOpenException("文件不存在");
    }
    //根据扩展名,适配相应的type
    String type = getType(ext);
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_VIEW);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        Uri contentUri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".fileprovider", file);
        intent.setDataAndType(contentUri,type);
    } else {
        Uri uri = Uri.fromFile(file);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setDataAndType(uri,type);
    }
    context.startActivity(intent);
}
复制代码
/**
 * 根据扩展名适配打开类型
 * @param ext 文件扩展名
 * @return 打开类型
 */
public static String getType(String ext) {
    switch (ext){
        case "3gp":return "video/3gpp";
        case "apk":return "application/vnd.android.package-archive";
        case "asf":return "video/x-ms-asf";
        case "avi":return "video/x-msvideo";
        case "bin":return "application/octet-stream";
        case "bmp":return "image/bmp";
        case "c":return "text/plain";
        case "class":return "application/octet-stream";
        case "conf":return "text/plain";
        case "cpp":return "text/plain";
        case "doc":return "application/msword";
        case "docx":return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
        case "xls":return "application/vnd.ms-excel";
        case "xlsx":return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        case "exe":return "application/octet-stream";
        case "gif":return "image/gif";
        case "gtar":return "application/x-gtar";
        case "gz":return "application/x-gzip";
        case "h":return "text/plain";
        case "htm":return "text/html";
        case "html":return "text/html";
        case "jar":return "application/java-archive";
        case "java":return "text/plain";
        case "jpeg":return "image/jpeg";
        case "jpg":return "image/jpeg";
        case "js":return "application/x-javascript";
        case "log":return "text/plain";
        case "m3u":return "audio/x-mpegurl";
        case "m4a":return "audio/mp4a-latm";
        case "m4b":return "audio/mp4a-latm";
        case "m4p":return "audio/mp4a-latm";
        case "m4u":return "video/vnd.mpegurl";
        case "m4v":return "video/x-m4v";
        case "mov":return "video/quicktime";
        case "mp2":return "audio/x-mpeg";
        case "mp3":return "audio/x-mpeg";
        case "mp4":return "video/mp4";
        case "mpc":return "application/vnd.mpohun.certificate";
        case "mpe":return "video/mpeg";
        case "mpeg":return "video/mpeg";
        case "mpg":return "video/mpeg";
        case "mpg4":return "video/mp4";
        case "mpga":return "audio/mpeg";
        case "msg":return "application/vnd.ms-outlook";
        case "ogg":return "audio/ogg";
        case "pdf":return "application/pdf";
        case "png":return "image/png";
        case "pps":return "application/vnd.ms-powerpoint";
        case "ppt":return "application/vnd.ms-powerpoint";
        case "pptx":return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
        case "prop":return "text/plain";
        case "rc":return "text/plain";
        case "rmvb":return "audio/x-pn-realaudio";
        case "rtf":return "application/rtf";
        case "sh":return "text/plain";
        case "tar":return "application/x-tar";
        case "tgz":return "application/x-compressed";
        case "txt":return "text/plain";
        case "wav":return "audio/x-wav";
        case "wma":return "audio/x-ms-wma";
        case "wmv":return "audio/x-ms-wmv";
        case "wps":return "application/vnd.ms-works";
        case "xml":return "text/plain";
        case "z":return "application/x-compress";
        case "zip":return "application/x-zip-compressed";
        case "":
        default:return "*/*";
    }
}

在AndroidManiFest注册fileprovider

复制代码
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

在res目录下的xml里面创建files-path

复制代码
<?xml version="1.0" encoding="utf-8"?>
<paths>
    <files-path
        name="files"
        path="." />
    <cache-path
        name="cache"
        path="." />
<!--    <external-path-->
<!--        name="external_storage"-->
<!--        path="." />-->
    <external-path
        name="file_safe_root_path"
        path="." />
    <external-files-path
        name="external_files"
        path="." />
    <external-cache-path
        name="external_cache"
        path="." />
    <external-media-path
        name="external_media"
        path="." />
    <root-path
        name="root"
        path="." />
 
</paths>
相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc2 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone2 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui