APK體積壓縮整理記錄

moment發表於2019-03-22

包結構分析對比

瘦身前

before

瘦身後

after

包檔案對比

compare

型別 原始大小 當前大小 縮減型別
resource.arsc 1.9M 855.9KB 國際化資原始檔,當前僅保留zh
res/ 14.3M 6.7M 圖片轉為webp
assets 42M 21.1M 減少FFmpeg x86平臺編譯檔案
lib 28M 6.6M 減少x86平臺下的so檔案

1、圖片資源優化

tinypng

  • 優點:無相容性問題
  • 缺點:壓縮繁雜需上傳至網頁下載,不支援批量壓縮替換

webp

  • 優點:有批量新增工具cwebp,可實現批量替換,後期可考慮將webp壓縮新增到自動化打包流程中

  • 缺點:有相容性問題,WebP格式是從Android4.0版本開始支援;Android4.0到Android4.2.1之間的版本不支援無失真壓縮和透明格式的WebP圖片的編解碼

最終經過檢視使用者手機型號及版本範圍分佈決定使用webp優化圖片資源,當然如果通過Android studio 一個一個的將圖片轉換為webp顯然是非常耗時且易出錯的,Google官方提供了cwebp工具可以使用指令碼批量壓縮替換,具體語法如下:

execCommand("cwebp", "-q", "80", in, "-o", out)

-q 後面的80表示壓縮比率為原始檔的80%
in 此處傳入原始檔目錄進行替代
-o 後面的 out處傳入原始檔的輸出路徑

圖片批量替換為Webp

``golang``
package main

var fileRealPath string

func init() {
	fileRealPath = "/Users/aihuishou/Desktop/opt_rn/android"
	//fileRealPath = getCurrentDirectory()
}

func main() {
	getFileList(fileRealPath)
}

func getFileList(filep string) {
	err := filepath.Walk(filep, func(path string, f os.FileInfo, err error) error {
		if f == nil {
			return err
		}
		if f.IsDir() {
			return nil
		}

		png2webp(f.Name(), path)
		//deleteWebp(f.Name(),path)
		return nil
	})
	if err == nil {
		fmt.Println("轉換完畢")
	}
}

// 通過cwebp命令批量替換png圖片
func png2webp(name string, path string) {
	var isLauncher = strings.HasPrefix(name, "ic_launcher")

	var isPng = strings.HasSuffix(name, ".png")

	var isJpg = strings.HasSuffix(name, ".jpg")

	var is9png = strings.HasSuffix(name, ".9.png")

	// 對png和pjg同時進行處理,排除掉應用圖示及.9圖
	if isPng && !isLauncher && !is9png || isJpg {

		var out string
		if isJpg {
			out = strings.TrimSuffix(path, ".jpg") + ".webp"
		}
		if isPng {
			out = strings.TrimSuffix(path, ".png") + ".webp"
		}

		cmdErr := execCommand("cwebp", "-q", "80", path, "-o", out)

		if cmdErr {
			println(path, " 替換為 =======> ", out)
			del := os.Remove(path)
			if del == nil {
				println(path, " 刪除成功!")
			}
		}
	}
}

// 刪除當前目錄中的webp檔案
func deleteWebp(name string, path string) {
	var isweb = strings.HasSuffix(name, ".webp")

	if isweb {
		del := os.Remove(path)
		if del == nil {
			println(path, " 刪除成功!")
		}
	}
}

// 執行cwebp轉換命令
func execCommand(commandName string, params ...string) bool {
	cmd := exec.Command(commandName, params...)

	//顯示執行的命令
	fmt.Println(cmd.Args)

	stdout, err := cmd.StdoutPipe()

	if err != nil {
		fmt.Println(err)
		return false
	}

	cmd.Start()

	reader := bufio.NewReader(stdout)

	//實時迴圈讀取輸出流中的一行內容
	for {
		line, err2 := reader.ReadString('\n')
		if err2 != nil || io.EOF == err2 {
			break
		}
		fmt.Println(line)
	}

	cmd.Wait()
	return true
}

複製程式碼

2、主工程瘦身

  • 主工程刪除x86平臺支援
  • 主工程resConfigs設定為zh,僅支援中文語言包
defaultConfig {
        resConfigs "zh"
        ndk {
            abiFilters "armeabi-v7a"
        }
    }
複製程式碼
  • 主工程gif圖片壓縮

按照主工程GIF圖片實際展示大小進行適當壓縮


3、三方庫瘦身

因為工程中有視訊拼接功能所以新增了FFmpeg-Android庫檔案導致包體積急劇上升,根據專案目前需求可取消對x86平臺的支援

  • 下載FFmpeg-Android原始檔講asset中x86下的FFmpeg檔案刪除,設定ABI平臺僅支援armeabi-v7a
  • 刪除專案中歷史冗餘程式碼

後記

不同的專案可以根據不同的需求選擇不同的方法進行體積壓縮,下面總結常見的apk壓縮技巧

  • 冗餘程式碼和資原始檔清除

可優化內容如下:

程式碼清除(刪除工程中無用程式碼,使用第三方包時,儘量將自己使用的部分原始碼拷貝進專案)

圖片資源清除(在專案對解析度要求不是跟高的前提下可以只支援 xhdpi xxdpi xxxdpi 甚至可以只支援xxdpi xxxdpi兩中解析度 )

  • 圖片大小優化

webp
tinypng

  • 程式碼混淆
  • 資源混淆

AndResGuard

相關文章