Android中減小apk大小的方式

減小APK空間的方式:

一,矢量圖,不會因爲縮放而讓圖片質量下降,又可以減小apk的大小,但是有個限制,通常矢量圖常應用於小圖標,比如200*200以下的.

除去美工給出,還可以從Android studio中直接使用默認的一些資源.用法是,在資源上點右鍵 ->新建 -> Vector assert,其中有很多預製的矢量圖,

標準的矢量圖是<svg>爲根節點的,android中矢量圖僅支持<vector>爲根節點的,可以通過工具做個轉換,Android studio中 vector assert就可以把<svg>的轉爲<vector>的.

導入的矢量圖會存在drawable中.

ic_ac_unit_black_24dp.xml

也有第三方庫可以把svg轉成vector. svg2vector.jar

矢量圖應該是api21之後出現,所以會有一個跟之前版本的兼容性問題,這就導致一張ic_ac_unit_black_24dp.xml矢量圖會在多個適配目錄中生成對應的png文件,這反而增加了圖片的佔用空間,如果要僅在一個適配目錄生成對應png,可以在build.gradle中配置:

defaultConfig {
    vectorDrawables.useSupportLibrary = true
}

對於矢量圖,還可以直接修改矢量圖的xml文件,修改圖片顏色.但是更推薦通過Tint着色器去修改圖片的顏色,這樣可以用一個xml圖片文件,顯示出多個不同效果.

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scr="@drawable/ic_ac_unit_black_24dp"
        android:tint="@color/colorAccent"
        android:backgroundTint="@color/colorPrimary"
        android:foregroundTint="@color/colorPrimaryDark" />

那如果想實現選擇器的效果,Tint也可以實現.

要定義背景選擇器,但是這裏只使用一張圖片

ac_unit_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable ="@drawable/ic_ac_unit_black_24dp" android:state_pressed= "true"/>
    <item android:drawable="@drawable/ic_ac_unit_black_24dp"/>
</selector>

還要定義顏色選擇器

ac_unit_tint_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/colorPrimary" android:state_pressed="true"/>
    <item android:color="@color/colorAccent"/>
</selector>

 

    <ImageView
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:clickable="true"
        android:tint="@color/ac_unit_tint_selector"
        android:src="@drawable/ac_unit_selector"/>

二,移除無用的資源,因爲需求的頻繁變更,肯定會有很多文件是不在需要的.但是這些資源都會打包進apk,所以需要移除.

java代碼還可以註釋掉,但是xml註釋很不方便,

1,通過工具 Refactor -> Remove unused resource來移除,

這種移除方式,如果代碼中存在動態獲取資源Id的方法,不會被檢測到,相關的資源會被移除,所以不推薦

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getResources().getIdentifier("activity_main_back","layout",getPackageName());
    }

2, 通過lint工具,這個工具可以在移除時讓去選擇那些需要保留,用這個工具的前提是你對代碼熟悉,清楚那些資源是不會被需要的.

 

三,對與資源的國際化配置,即使是隻在國內使用的apk,也是應該配置的,因爲引入的第三方庫會給你國際化,

如默認創建的一個app:
 

可以通過配置保留部分語言.

defaultConfig {
    resConfigs "zh-rCN","en-rAU"
}

 四,動態庫的配置

so文件通常是ndk編譯的動態庫,因爲不能跨平臺,所以每個平臺需要對應的so庫.

這裏有一個ABI的概念,ABI是(Application binary interface)應用程序二進制接口的簡稱,從使用的指令集,內存對齊,到可用的系統函數庫,定義了二進制文件如何運行在相應的系統平臺上.

在Android 系統上,每一個CPU架構對應一個ABI:armeabi,armeabi-v7a,arm64-v8a,x86,x86_64,mips,mips64。

一般只需要配置armeabi-v7a就行.

    defaultConfig {
  
        ndk {
            abiFilters "armeabi-v7a"
        }
    }

五,代碼壓縮,就是把

minifyEnabled true
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

壓縮代碼時,也混淆了代碼,有時候可能會運行出錯,報類找不到異常,這是需要根據錯誤信息,通過

proguard-rules.pro'文件keep住某些文件,不做壓縮混淆處理.

六,資源壓縮

shrinkResources true 這個參數需要跟代碼壓縮的參數同時配置纔有效
    buildTypes {
        release {
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

默認是非嚴格模式,就是說如果代碼中通過

getResources().getIdentifier("activity_main_back","layout",getPackageName());

這中格式引用資源, 非嚴格檢查模式,就是以activity_main_back字符串開頭的資源都會保留不做處理,也即是 startwith.

可以通過配置文件使用嚴格模式,在raw目錄下創建keep.xml

<?xml version="1.0" encoding="utf-8"?>
<resources
    xmlns:tools="http://schemas.android.com/tools">
    tools:shrinkMode="strict"
</resources>

也可以通過tools:keep="",tools:discard=""指定保留,捨棄的文件.

七,資源的混淆,主要針對resource.arsc,及res目錄,混淆時把名稱變成了a,b,c,d...,更短了,並且把res下的圖片做了壓縮,所以減小了apk大小.

混淆的過程中res下的文件名稱改成了a,b,c等,那代碼中是是怎麼使用的?

在代碼中通過這類語句使用資源

setContentView(R.layout.activity_main);

實際是用到的R.java的定義,這裏id的定義是有規則的:

資源的整型數格式爲:0xpptteeee(16進制,p代表的是package,t代表的是type,e代表的是entry)。

- Package ID 包ID,系統爲0x01,應用程序資源爲0x7f。
- Type ID 資源的類型ID,資源的類型有animator、anim、color等等,每一種都會被賦予一個ID。
- Entry ID  資源在其所屬的資源類型中所出現的次序

package com.example.tinydrawable;

public final class R {
  public static final class anim {
           public static final int abc_fade_in=0x7f010000;
    public static final int abc_fade_out=0x7f010001;
    public static final int abc_grow_fade_in_from_bottom=0x7f010002;
  }
  public static final class color {
    public static final int abc_background_cache_hint_selector_material_dark=0x7f040000;
    public static final int abc_background_cache_hint_selector_material_light=0x7f040001;
    public static final int abc_btn_colored_borderless_text_material=0x7f040002;
    public static final int abc_btn_colored_text_material=0x7f040003;
  }
  public static final class drawable {
    public static final int abc_ab_share_pack_mtrl_alpha=0x7f060001;
    public static final int abc_vector_test=0x7f060056;
    public static final int ac_unit_selector=0x7f060057;
    }
}

所以實際使用的是一個id,那麼就有一個資源映射表resources.arsc,把id跟具體的資源對應起來,

實際使用是在這個映射表中根據id找到名稱,找到路徑,所以資源混淆後,因爲修改了文件名,路徑名,所以也會同步修改這個映射表中的名字,路徑值.

這個功能使用騰訊的開源工具,

https://github.com/shwenzhang/AndResGuard

安裝包立減1M--微信Android資源混淆打包工具

https://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=208135658&idx=1&sn=ac9bd6b4927e9e82f9fa14e396183a8f#rd

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章