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>