Android使用Zip4j實(shí)現(xiàn)加密壓縮功能
一、為什么選擇Zip4j?
Zip4j是一個功能強(qiáng)大的Java庫,專為處理加密ZIP文件而設(shè)計(jì),相比Android原生Zip工具具有顯著優(yōu)勢:
| 特性 | Android原生Zip | Zip4j |
|---|---|---|
| 加密支持 | 無 | AES和標(biāo)準(zhǔn)ZIP加密 |
| 密碼保護(hù) | 不支持 | 支持 |
| 大文件處理 | 有限 | 優(yōu)秀 |
| 壓縮級別控制 | 無 | 9級可調(diào) |
| 文件覆蓋處理 | 基礎(chǔ) | 高級選項(xiàng) |
| 進(jìn)度回調(diào) | 無 | 支持 |
二、環(huán)境配置
1. 添加依賴
在模塊級build.gradle.kts中添加:
dependencies {
implementation("net.lingala.zip4j:zip4j:2.11.5")
// 最新版本請查看:https://github.com/srikanth-lingala/zip4j
}
2. 權(quán)限配置
在AndroidManifest.xml中添加存儲權(quán)限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"/> <!-- Android 9及以下需要 -->
<!-- 對于Android 10+,使用Scoped Storage -->
<application
android:requestLegacyExternalStorage="true"
... >
</application>
三、核心功能實(shí)現(xiàn)
1. 基礎(chǔ)加密壓縮工具類
import android.content.Context
import net.lingala.zip4j.ZipFile
import net.lingala.zip4j.model.ZipParameters
import net.lingala.zip4j.model.enums.CompressionLevel
import net.lingala.zip4j.model.enums.CompressionMethod
import net.lingala.zip4j.model.enums.EncryptionMethod
import java.io.File
class ZipEncryptor(private val context: Context) {
/**
* 加密壓縮文件或文件夾
* @param sourcePath 源路徑(文件或文件夾)
* @param zipFilePath 生成的ZIP文件路徑
* @param password 加密密碼
* @param encryptionMethod 加密方法(默認(rèn)AES-256)
*/
fun encryptAndCompress(
sourcePath: String,
zipFilePath: String,
password: String,
encryptionMethod: EncryptionMethod = EncryptionMethod.AES
) {
val sourceFile = File(sourcePath)
val zipFile = ZipFile(zipFilePath, password.toCharArray())
val parameters = ZipParameters().apply {
compressionMethod = CompressionMethod.DEFLATE
compressionLevel = CompressionLevel.NORMAL
isEncryptFiles = true
this.encryptionMethod = encryptionMethod
}
when {
sourceFile.isFile -> zipFile.addFile(sourceFile, parameters)
sourceFile.isDirectory -> zipFile.addFolder(sourceFile, parameters)
else -> throw IllegalArgumentException("無效的源路徑: $sourcePath")
}
}
/**
* 安全解壓加密ZIP文件
* @param zipFilePath ZIP文件路徑
* @param destDirectory 解壓目標(biāo)目錄
* @param password 解密密碼
*/
fun decryptAndExtract(
zipFilePath: String,
destDirectory: String,
password: String
) {
val zipFile = ZipFile(zipFilePath, password.toCharArray())
zipFile.extractAll(destDirectory)
}
}
2. 帶進(jìn)度回調(diào)的高級壓縮
import net.lingala.zip4j.progress.ProgressMonitor
class AdvancedZipEncryptor(context: Context) : ZipEncryptor(context) {
/**
* 帶進(jìn)度回調(diào)的加密壓縮
* @param progressCallback 進(jìn)度回調(diào) (當(dāng)前字節(jié)數(shù), 總字節(jié)數(shù))
*/
fun encryptWithProgress(
sourcePath: String,
zipFilePath: String,
password: String,
progressCallback: (Long, Long) -> Unit
) {
val zipFile = ZipFile(zipFilePath, password.toCharArray())
val parameters = ZipParameters().apply {
isEncryptFiles = true
encryptionMethod = EncryptionMethod.AES
}
val sourceFile = File(sourcePath)
// 啟動進(jìn)度監(jiān)控線程
Thread {
var lastProgress = 0L
while (true) {
val progress = zipFile.progressMonitor
if (progress.state == ProgressMonitor.State.BUSY) {
if (progress.workCompleted > lastProgress) {
progressCallback(progress.workCompleted, progress.totalWork)
lastProgress = progress.workCompleted
}
} else if (progress.state == ProgressMonitor.State.READY) {
break
}
Thread.sleep(100)
}
}.start()
// 執(zhí)行壓縮操作
when {
sourceFile.isFile -> zipFile.addFile(sourceFile, parameters)
sourceFile.isDirectory -> zipFile.addFolder(sourceFile, parameters)
}
}
}
3. 多文件選擇性加密壓縮
fun encryptSelectedFiles(
filePaths: List<String>,
zipFilePath: String,
password: String
) {
val zipFile = ZipFile(zipFilePath, password.toCharArray())
val parameters = ZipParameters().apply {
isEncryptFiles = true
encryptionMethod = EncryptionMethod.AES
}
val files = filePaths.map { File(it) }
zipFile.addFiles(files, parameters)
}
四、Android存儲適配
針對不同Android版本處理存儲權(quán)限:
import android.os.Build
import android.os.Environment
import androidx.core.content.ContextCompat
fun getSafeStoragePath(context: Context, folderName: String): File {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Android 10+ 使用應(yīng)用專屬目錄
File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), folderName)
} else {
// Android 9及以下使用傳統(tǒng)存儲
File(Environment.getExternalStorageDirectory(), "Documents/$folderName")
}.apply { mkdirs() }
}
五、完整使用示例
1. 壓縮照片并加密
fun compressPhotos(context: Context) {
val zipUtil = ZipEncryptor(context)
val photosDir = getSafeStoragePath(context, "Photos")
val zipPath = File(getSafeStoragePath(context, "Archives"), "photos_encrypted.zip").absolutePath
try {
zipUtil.encryptAndCompress(
sourcePath = photosDir.absolutePath,
zipFilePath = zipPath,
password = "Secure@Password123!",
encryptionMethod = EncryptionMethod.AES
)
Toast.makeText(context, "照片加密壓縮完成", Toast.LENGTH_SHORT).show()
} catch (e: Exception) {
Log.e("ZipError", "壓縮失敗: ${e.message}")
Toast.makeText(context, "壓縮失敗: ${e.message}", Toast.LENGTH_LONG).show()
}
}
2. 帶進(jìn)度條的大文件壓縮
fun compressLargeFileWithProgress(context: Context, progressBar: ProgressBar) {
val advancedZip = AdvancedZipEncryptor(context)
val largeFilePath = getSafeStoragePath(context, "Videos").resolve("large_video.mp4").absolutePath
val zipPath = File(getSafeStoragePath(context, "Archives"), "video_encrypted.zip").absolutePath
advancedZip.encryptWithProgress(
sourcePath = largeFilePath,
zipFilePath = zipPath,
password = "StrongPassword!456"
) { current, total ->
// 更新UI進(jìn)度
runOnUiThread {
progressBar.max = total.toInt()
progressBar.progress = current.toInt()
}
}
}
3. 解壓加密文件
fun extractEncryptedZip(context: Context) {
val zipUtil = ZipEncryptor(context)
val zipPath = File(getSafeStoragePath(context, "Archives"), "photos_encrypted.zip").absolutePath
val extractDir = getSafeStoragePath(context, "ExtractedPhotos")
try {
zipUtil.decryptAndExtract(
zipFilePath = zipPath,
destDirectory = extractDir.absolutePath,
password = "Secure@Password123!"
)
Toast.makeText(context, "文件解壓成功", Toast.LENGTH_SHORT).show()
} catch (e: Exception) {
Log.e("ZipError", "解壓失敗: ${e.message}")
Toast.makeText(context, "解壓失敗: 密碼錯誤或文件損壞", Toast.LENGTH_LONG).show()
}
}
六、高級配置選項(xiàng)
1. 自定義壓縮參數(shù)
fun getCustomZipParameters(): ZipParameters {
return ZipParameters().apply {
compressionMethod = CompressionMethod.DEFLATE
compressionLevel = CompressionLevel.MAXIMUM // 最高壓縮率
isEncryptFiles = true
encryptionMethod = EncryptionMethod.AES
aesKeyStrength = AesKeyStrength.KEY_STRENGTH_256 // 256位AES加密
// 文件覆蓋選項(xiàng)
fileExistsInZipMode = FileExistsInZipMode.OVERWRITE
// 設(shè)置文件注釋
fileComment = "Created on ${SimpleDateFormat("yyyy-MM-dd").format(Date())}"
// 設(shè)置解壓后文件屬性(Unix系統(tǒng))
unixFileAttributes = 644
}
}
2. 分卷壓縮(適合大文件)
fun splitZipCreation(context: Context) {
val sourceFile = getSafeStoragePath(context, "Database").resolve("backup.db")
val zipPath = File(getSafeStoragePath(context, "Archives"), "db_backup.zip").absolutePath
val zipFile = ZipFile(zipPath, "backupPassword123!".toCharArray())
val parameters = ZipParameters().apply {
isEncryptFiles = true
encryptionMethod = EncryptionMethod.AES
}
// 設(shè)置分卷大小(100MB)
zipFile.isSplitArchive = true
zipFile.splitLength = 100 * 1024 * 1024 // 100MB
zipFile.addFile(sourceFile, parameters)
}
七、常見問題解決方案
1. 密碼強(qiáng)度問題
錯誤信息:net.lingala.zip4j.exception.ZipException: Password is too weak
解決方案:
fun isStrongPassword(password: String): Boolean {
// 至少8位,包含大小寫字母、數(shù)字和特殊字符
val pattern = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}$".toRegex()
return pattern.matches(password)
}
2. 存儲權(quán)限問題
錯誤信息:java.io.FileNotFoundException: ... (Permission denied)
解決方案:
// 在Activity中請求權(quán)限
private fun requestStoragePermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
STORAGE_PERMISSION_CODE
)
} else {
// Android 10+ 不需要請求存儲權(quán)限
startCompression()
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == STORAGE_PERMISSION_CODE &&
grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startCompression()
} else {
Toast.makeText(this, "需要存儲權(quán)限才能執(zhí)行此操作", Toast.LENGTH_LONG).show()
}
}
3. 內(nèi)存優(yōu)化
處理大文件時使用流式壓縮避免OOM:
fun streamCompression(sourceFile: File, zipPath: String, password: String) {
val zipFile = ZipFile(zipPath, password.toCharArray())
val parameters = ZipParameters().apply {
isEncryptFiles = true
encryptionMethod = EncryptionMethod.AES
}
FileInputStream(sourceFile).use { fis ->
zipFile.addStream(fis, parameters)
}
}
八、性能優(yōu)化建議
1.壓縮級別選擇:
CompressionLevel.FASTEST:速度最快,壓縮率低CompressionLevel.NORMAL:平衡模式(默認(rèn))CompressionLevel.MAXIMUM:最高壓縮率,速度慢
2.多線程壓縮(Zip4j 2.x+):
zipFile.setRunInThread(true) // 啟用后臺線程壓縮
3.文件篩選(避免壓縮不必要文件):
parameters.fileExclusionFilters = listOf(
FileFilter { file -> file.name.endsWith(".tmp") },
FileFilter { file -> file.name.startsWith("temp_") }
)
九、總結(jié)與最佳實(shí)踐
關(guān)鍵點(diǎn)總結(jié)
- 安全優(yōu)先:始終使用AES-256加密保護(hù)敏感數(shù)據(jù)
- 密碼策略:強(qiáng)制用戶使用強(qiáng)密碼(8+字符,混合類型)
- 存儲適配:正確處理Android不同版本的存儲權(quán)限
- 進(jìn)度反饋:對大文件操作提供進(jìn)度顯示
- 錯誤處理:優(yōu)雅處理密碼錯誤、文件損壞等情況
- 資源管理:及時關(guān)閉文件流,避免資源泄漏
推薦實(shí)踐
fun safeZipOperation(context: Context) {
try {
// 1. 驗(yàn)證源文件存在
val sourceFile = File(sourcePath)
if (!sourceFile.exists()) throw FileNotFoundException("源文件不存在")
// 2. 驗(yàn)證目標(biāo)路徑可寫
val zipFile = File(zipPath)
if (zipFile.exists() && !zipFile.canWrite()) throw IOException("目標(biāo)文件不可寫")
// 3. 驗(yàn)證密碼強(qiáng)度
if (!isStrongPassword(password)) throw IllegalArgumentException("密碼強(qiáng)度不足")
// 4. 執(zhí)行壓縮
val zipUtil = ZipEncryptor(context)
zipUtil.encryptAndCompress(sourcePath, zipPath, password)
// 5. 驗(yàn)證結(jié)果
if (!zipFile.exists() || zipFile.length() == 0L) {
throw IOException("壓縮文件創(chuàng)建失敗")
}
// 6. 清理臨時文件(如果需要)
// ...
} catch (e: Exception) {
Log.e("ZipOperation", "操作失敗", e)
// 通知用戶并提供解決方案
}
}
Zip4j為Android提供了強(qiáng)大的加密壓縮能力,合理使用可以顯著提升應(yīng)用的數(shù)據(jù)安全性。建議在實(shí)際項(xiàng)目中根據(jù)具體需求選擇合適的壓縮參數(shù)和加密級別,并在關(guān)鍵操作中添加適當(dāng)?shù)娜罩居涗浐彤惓L幚怼?/p>
到此這篇關(guān)于Android使用Zip4j實(shí)現(xiàn)加密壓縮功能的文章就介紹到這了,更多相關(guān)Android Zip4j加密壓縮內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android中使用Bitmap類將矩形圖片轉(zhuǎn)為圓形的方法
這篇文章主要介紹了Android中使用Bitmap類將矩形圖片轉(zhuǎn)為圓形的方法,同時文中也介紹了如何利用矩形直接來畫圓角,需要的朋友可以參考下2016-03-03
Android監(jiān)聽Home鍵和Back鍵的區(qū)別介紹
這篇文章主要介紹了Android監(jiān)聽Home鍵和Back鍵的區(qū)別介紹,本文還同時給出了Home鍵監(jiān)聽的實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-06-06
ExpandableListView實(shí)現(xiàn)簡單二級列表
這篇文章主要為大家詳細(xì)介紹了ExpandableListView實(shí)現(xiàn)簡單二級列表,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-11-11
Android實(shí)現(xiàn)一個完美的倒計(jì)時功能
在Adroid應(yīng)用中,倒計(jì)時的功能使用的很多,例如點(diǎn)擊獲取短信驗(yàn)證碼之后的倒計(jì)時等等,這篇文章主要給大家介紹了關(guān)于利用Android如何實(shí)現(xiàn)一個完美的倒計(jì)時功能的相關(guān)資料,需要的朋友可以參考下2021-11-11
Android AutoWrapTextView中英文排版問題的解決方法
這篇文章主要給大家介紹了關(guān)于Android AutoWrapTextView中英文排版問題的解決方法,文中介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。2017-05-05
Android在WebView中調(diào)用系統(tǒng)下載的方法
這篇文章主要為大家詳細(xì)介紹了Android在WebView中調(diào)用系統(tǒng)下載的簡單使用,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-05-05
Android屬性動畫實(shí)現(xiàn)布局的下拉展開效果
這篇文章主要為大家詳細(xì)介紹了Android屬性動畫實(shí)現(xiàn)布局的下拉展開效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-07-07

