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>
相关推荐
戏谑31 分钟前
Android 常用布局
android·view
拭心12 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
带电的小王14 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡15 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道15 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库16 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道16 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe17 小时前
Android Hook - 动态加载so库
android
居居飒17 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He20 小时前
桌面列表小部件不能点击的问题分析
android