使用 Proguard 删除 Google Play Services 库中未使用的类

Posted

技术标签:

【中文标题】使用 Proguard 删除 Google Play Services 库中未使用的类【英文标题】:Using Proguard to remove unused classes in Google Play Services library 【发布时间】:2015-02-24 08:38:33 【问题描述】:

我正在尝试从 Google Play Services 库中删除未使用的类。我创建了具有单个空活动的全新 android 项目。该项目不使用来自Google Play Services 库的任何内容。所以我希望,当我构建版本(包括在我的配置中运行 proguard)时,与有/没有 play-services 依赖项的构建相比,我会发现二进制大小没有区别。但实际上,我看到 apk 大小的差异约为 700 KB。

我找到了relatively complex solution, using gradle script,其中涉及重新打包 play-services.jar 文件。此外,此解决方案需要明确指定每个不会使用的包。但我不明白为什么proguard 不适合我的情况?

build.gradle:

apply plugin: 'com.android.application'

android 
    compileSdkVersion 21
    buildToolsVersion "21.1.1"

    defaultConfig 
        minSdkVersion 10
        targetSdkVersion 21
    

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


dependencies 
    // !!! when I comment the line below, release APK is 700 KB smaller !!! //
    compile 'com.google.android.gms:play-services:6.5.87'

proguard-rules.pro:

-assumenosideeffects class android.util.Log 
    public static *** d(...);

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.test.noplayservices">
    <application android:allowBackup="true"
                 android:label="@string/app_name"
                 android:icon="@drawable/ic_launcher"
                 android:theme="@style/AppTheme">
        <activity android:name=".ui.activities.MainActivity" android:icon="@drawable/ic_launcher">
            <intent-filter>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

MainActivity.java:

package com.test.noplayservices.ui.activities;

import android.app.Activity;
import android.os.Bundle;
import com.test.noplayservices.R;

public class MainActivity extends Activity 
    @Override
    public void onCreate(Bundle savedInstance) 
        super.onCreate(savedInstance);
        setContentView(R.layout.main_activity);
    

【问题讨论】:

Proguard 会删除未使用的类,但我不确定它是否会删除 public static 数据,或者 static initializers 会发生什么情况。我敢打赌这些课程没有被删除。作为 google play 服务的一个庞大的库,其所有类都相互关联,我想该方法将类似于您所指出的:只需尝试从库 jar 中提取您需要的类。顺便说一句-我使用的旧罐子比现在的小得多,去年它们的大小增长了 3 倍。 另外,您可以做的是将您的 700kb APK 上传到像 decompileandroid.com 这样的网站,将您的 APK 反编译为源代码,然后查看包含哪些 GPS 类并尝试了解原因.至少您可以定义规则来排除这些类。记得禁用混淆以清楚地看到包含的类! 您可能还想添加shrinkResources true - 请参阅here @miav 谢谢!这正是我需要的! @miav,不幸的是,它并没有真正改变什么。实际上,从play-services 我只需要adsanalyticsads 可作为独立包提供,但 analyticsbase 包的一部分,其中包含 600KB 资源(adsanalytics 均未使用这些资源)。所以我预计 shirnkResources 将删除大部分 600KB,但它没有。我还有 700KB APK 【参考方案1】:

从 Google Play 服务 6.5 版及更高版本开始,您可以选择要使用的单个 API,然后只导入这些 API。也许这会帮助您稍微减小 APK 的大小。这是一个列表:

Google+                         com.google.android.gms:play-services-plus:6.5.+
Google Account Login            com.google.android.gms:play-services-identity:6.5.+
Google Activity Recognition     com.google.android.gms:play-services-location:6.5.+
Google App Indexing             com.google.android.gms:play-services-appindexing:6.5.+
Google Cast                     com.google.android.gms:play-services-cast:6.5.+
Google Drive                    com.google.android.gms:play-services-drive:6.5.+
Google Fit                      com.google.android.gms:play-services-fitness:6.5.+
Google Maps                     com.google.android.gms:play-services-maps:6.5.+
Google Mobile Ads               com.google.android.gms:play-services-ads:6.5.+
Google Panorama Viewer          com.google.android.gms:play-services-panorama:6.5.+
Google Play Game services       com.google.android.gms:play-services-games:6.5.+
Google Wallet                   com.google.android.gms:play-services-wallet:6.5.+
Android Wear                    com.google.android.gms:play-services-wearable:6.5.+
Google Actions
Google Analytics
Google Cloud Messaging          com.google.android.gms:play-services-base:6.5.+

你可以看到更多关于这个here。

【讨论】:

这个解决方案加上@miav 建议的shrinkResources 应该可以完成工作!谢谢!

以上是关于使用 Proguard 删除 Google Play Services 库中未使用的类的主要内容,如果未能解决你的问题,请参考以下文章

Proguard 使用 Google Play 服务库返回错误

使用 Proguard 在 dist 上混淆 Play 2 Web 应用程序?

使用 google-play-services 进行 Proguard

使用 proguard 混淆后,使用 google guice 注入不再起作用

Google Drive API 不能很好地与 ProGuard (NPE) 配合使用

Android Studio 中带有 Proguard 的 Google Play 服务