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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值