Android使用Zip4j實(shí)現(xiàn)加密壓縮功能
一、為什么選擇Zip4j?
Zip4j是一個(gè)功能強(qiáng)大的Java庫,專為處理加密ZIP文件而設(shè)計(jì),相比Android原生Zip工具具有顯著優(yōu)勢:
| 特性 | Android原生Zip | Zip4j |
|---|---|---|
| 加密支持 | 無 | AES和標(biāo)準(zhǔn)ZIP加密 |
| 密碼保護(hù) | 不支持 | 支持 |
| 大文件處理 | 有限 | 優(yōu)秀 |
| 壓縮級(jí)別控制 | 無 | 9級(jí)可調(diào) |
| 文件覆蓋處理 | 基礎(chǔ) | 高級(jí)選項(xiàng) |
| 進(jìn)度回調(diào) | 無 | 支持 |
二、環(huán)境配置
1. 添加依賴
在模塊級(jí)build.gradle.kts中添加:
dependencies {
implementation("net.lingala.zip4j:zip4j:2.11.5")
// 最新版本請查看:https://github.com/srikanth-lingala/zip4j
}
2. 權(quán)限配置
在AndroidManifest.xml中添加存儲(chǔ)權(quán)限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"/> <!-- Android 9及以下需要 -->
<!-- 對(duì)于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)的高級(jí)壓縮
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)
// 啟動(dòng)進(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存儲(chǔ)適配
針對(duì)不同Android版本處理存儲(chǔ)權(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)存儲(chǔ)
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, "解壓失敗: 密碼錯(cuò)誤或文件損壞", Toast.LENGTH_LONG).show()
}
}
六、高級(jí)配置選項(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è)置分卷大?。?00MB)
zipFile.isSplitArchive = true
zipFile.splitLength = 100 * 1024 * 1024 // 100MB
zipFile.addFile(sourceFile, parameters)
}
七、常見問題解決方案
1. 密碼強(qiáng)度問題
錯(cuò)誤信息: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. 存儲(chǔ)權(quán)限問題
錯(cuò)誤信息: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+ 不需要請求存儲(chǔ)權(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, "需要存儲(chǔ)權(quán)限才能執(zhí)行此操作", Toast.LENGTH_LONG).show()
}
}
3. 內(nèi)存優(yōu)化
處理大文件時(shí)使用流式壓縮避免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.壓縮級(jí)別選擇:
CompressionLevel.FASTEST:速度最快,壓縮率低CompressionLevel.NORMAL:平衡模式(默認(rèn))CompressionLevel.MAXIMUM:最高壓縮率,速度慢
2.多線程壓縮(Zip4j 2.x+):
zipFile.setRunInThread(true) // 啟用后臺(tái)線程壓縮
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+字符,混合類型)
- 存儲(chǔ)適配:正確處理Android不同版本的存儲(chǔ)權(quán)限
- 進(jìn)度反饋:對(duì)大文件操作提供進(jìn)度顯示
- 錯(cuò)誤處理:優(yōu)雅處理密碼錯(cuò)誤、文件損壞等情況
- 資源管理:及時(shí)關(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. 清理臨時(shí)文件(如果需要)
// ...
} catch (e: Exception) {
Log.e("ZipOperation", "操作失敗", e)
// 通知用戶并提供解決方案
}
}
Zip4j為Android提供了強(qiáng)大的加密壓縮能力,合理使用可以顯著提升應(yīng)用的數(shù)據(jù)安全性。建議在實(shí)際項(xiàng)目中根據(jù)具體需求選擇合適的壓縮參數(shù)和加密級(jí)別,并在關(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檢測手機(jī)中存儲(chǔ)卡及剩余空間大小的方法(基于Environment,StatFs及DecimalFormat
這篇文章主要介紹了Android檢測手機(jī)中存儲(chǔ)卡及剩余空間大小的方法,基于Environment,StatFs及DecimalFormat實(shí)現(xiàn)該功能,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2016-01-01
Android Activity跳轉(zhuǎn)動(dòng)畫效果
這篇文章主要介紹了Android Activity跳轉(zhuǎn)動(dòng)畫效果,本文圖文并茂給大家介紹的非常詳細(xì),需要的朋友可以參考下2017-02-02
Android中使用listview實(shí)現(xiàn)qq/微信好友列表
本文主要介紹了android中使用listview實(shí)現(xiàn)qq/微信好友列表(頭像,昵稱,個(gè)性簽名)的相關(guān)知識(shí)。具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-04-04
Android中判斷網(wǎng)絡(luò)連接狀態(tài)的方法
App判斷用戶是否聯(lián)網(wǎng)是很普遍的需求,這篇文章主要介紹了Android中判斷網(wǎng)絡(luò)連接狀態(tài)的方法,感興趣的朋友可以參考一下2016-02-02
Android仿支付寶笑臉?biāo)⑿录虞d動(dòng)畫的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android仿支付寶笑臉?biāo)⑿录虞d動(dòng)畫的實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2016-11-11
深入探究Android動(dòng)態(tài)代理的原理及用途
動(dòng)態(tài)代理是一種在編程中非常有用的設(shè)計(jì)模式,它允許你在運(yùn)行時(shí)創(chuàng)建一個(gè)代理對(duì)象來代替原始對(duì)象,以便在方法調(diào)用前后執(zhí)行額外的邏輯,本文將深入探討Android動(dòng)態(tài)代理的原理、用途和實(shí)際示例2023-09-09
Android關(guān)鍵字persistent詳細(xì)分析
這篇文章主要介紹了Android關(guān)鍵字persistent的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下2021-04-04
Android編程之SurfaceView實(shí)例詳解
這篇文章主要介紹了Android編程之SurfaceView用法,簡要分析了View和SurfaceView的區(qū)別,并結(jié)合實(shí)例形式分析了SurfaceView的具體使用步驟與相關(guān)技巧,需要的朋友可以參考下2016-02-02
Android SharedPreferences存儲(chǔ)用法詳解
這篇文章主要為大家詳細(xì)介紹了Android SharedPreferences存儲(chǔ)用法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
Android調(diào)用系統(tǒng)圖片裁剪限定尺寸及7.0照相問題的解決方法
這篇文章主要介紹了Android調(diào)用系統(tǒng)圖片裁剪限定尺寸,及7.0照相問題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07

