Google Play 服务使 apk 太大 [英] Google Play Services makes apk too big
问题描述
我已经安装了 Google Play 服务并创建了一个 Hello World 应用程序来测试一切正常,我认为应用程序大小太大:4.98 MB.我正在使用 Android Studio,并且已按照 android 开发人员网站中的详细说明进行操作.
这是我的 gradle 文件:
应用插件:'android'安卓 {compileSdkVersion 19构建工具版本19.0.1"默认配置{minSdk 版本 15目标SDK版本19版本代码 1版本名称1.0"}构建类型{释放 {runProguard 假proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'}}}依赖{编译文件树(目录:'libs',包括:['*.jar'])编译 'com.google.android.gms:play-services:4.3.23'}
编辑
这是我的 proguard 文件:
-keep class * extends java.util.ListResourceBundle {受保护的对象[][] getContents();}- 保持公共类 com.google.android.gms.common.internal.safeparcel.SafeParcelable {公共静态最终 *** NULL;}-keepnames @com.google.android.gms.common.annotation.KeepName 类 *-keepclassmembernames 类 * {@com.google.android.gms.common.annotation.KeepName *;}-keepnames 类 * 实现 android.os.Parcelable {公共静态最终**创造者;}
** 编辑 2 **
我已经使用最新版本的 Intellij Idea 安装了 Google Play 服务,现在 apk 是 3.52 MB.我不知道这是否是可以接受的尺寸.
这正常吗?
不,这不正常 - 我的 GPSTest 应用程序 包含 Google Play 地图服务在使用 Proguard 进行混淆后只有 808KB - 当前版本(添加另一个库后)在混淆后约为 1,497KB.
我建议使用以下步骤从命令行导出 APK,以避免 Android Studio 出现潜在问题:
- 在命令行转到项目的根目录
- 运行
gradlew assembleRelease
- 在
/app/build/apk
文件夹中找到经过签名和混淆的APK
如果您通过 Android Studio 导出 APK,请注意有一个 已知问题 默认情况下,Android Studio 将使用 assembleDebug
任务而不是 assembleRelease
任务导出.因此,build.gradle
文件中用于运行 Proguard 的任何特定于发布 buildType 的配置都不会被执行.
作为通过 Android Studio 导出的解决方法,您可以通过以下步骤更改默认构建变体:
- 在 Android Studio 中,打开查看->工具窗口->构建变体"
- 在打开的窗口中,将Build Variant"从
debug
更改为release
.
现在,当您执行Build->Generate Signed APK..."时,Android Studio 应该运行发行版 Build Variant,如果您在 build.gradle
中正确配置了 Proguard,它应该会运行 Proguard.您可以在正常调试应用的同时改回 debug
变体.
如果你想从 GPSTest 复制我的设置,这里是 proguard.cfg
:
-optimizationpasses 5-dontusemixedcaseclassnames-不要跳过非公共图书馆类-不要预验证-详细-优化 !code/simplification/arithmetic,!field/*,!class/merging/*- 保持公共类 * 扩展 android.app.Activity- 保持公共类 * 扩展 android.app.Application- 保持公共类 * 扩展 android.preference.Preference-keepclasseswithmembers 类 * {本机<方法>;}-keepclasseswithmembers 类 * {公共 <init>(android.content.Context, android.util.AttributeSet);}-keepclasseswithmembers 类 * {公共<init>(android.content.Context, android.util.AttributeSet, int);}-keepclassmembers 枚举 * {公共静态 **[] 值();公共静态 ** valueOf(java.lang.String);}-keep 类 * 实现 android.os.Parcelable {公共静态最终 android.os.Parcelable$Creator *;}-保持类 * 扩展 java.util.ListResourceBundle {受保护的对象[][] getContents();}-dontwarn **CompatHoneycomb-dontwarn **CompatCreatorHoneycombMR2-不要警告 **AccessibilityServiceInfoCompatJellyBeanMr2-不要警告 android.support.v4.view.**-不要警告 android.support.v4.media.**-不要警告 com.actionbarsherlock.internal.**-保持类android.support.v4.** { *;}-keepattributes *注解*- 保持公共类 * 扩展 android.view.View- 保持公共类 * 扩展 android.view.ViewGroup- 保持公共类 * 扩展 android.support.v4.app.Fragment-keepclassmembers 类 * 扩展 com.actionbarsherlock.ActionBarSherlock {<init>(android.app.Activity, int);}
... 和 build.gradle
:
应用插件:'android'安卓 {compileSdkVersion 19构建工具版本19.0.0"默认配置{minSdk 版本 8目标SDK版本19}如果(project.hasProperty(secure.properties")&&新文件(project.property("secure.properties")).exists()) {属性道具 = 新属性()props.load(new FileInputStream(file(project.property("secure.properties"))))签名配置{调试{存储文件文件(gpstest.debug.keystore")}释放 {存储文件文件(道具['key.store'])keyAlias 道具['key.alias']storePassword "askmeler"keyPassword "askmeler"}}} 别的 {签名配置{调试{存储文件文件(gpstest.debug.keystore")}释放 {//这里没有什么}}}构建类型{释放 {runProguard 真proguardFile 'proguard.cfg'签名配置signingConfigs.release}}}任务 askForPasswords <<{//必须创建 String 因为 System.readPassword() 返回 char[]//(并且在下面分配它会默默地失败)def storePw = new String(System.console().readPassword("\nKeystore 密码:"))def keyPw = new String(System.console().readPassword("Key password:"))android.signingConfigs.release.storePassword = storePwandroid.signingConfigs.release.keyPassword = keyPw}tasks.whenTaskAdded { theTask ->if (theTask.name.equals("packageRelease")) {theTask.dependsOn "askForPasswords"}}依赖{编译项目(':ShowcaseViewLibrary')编译 'com.google.android.gms:play-services:3.2.65'编译'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'编译'org.jraf:android-switch-backport:1.2'编译 'com.google.maps.android:android-maps-utils:0.2.1'}
如果您想将其用作示例,则整个 GPSTest 源代码可在 Github 上获得.>
编辑
在使用 Google Play 服务 v6.5 或更高版本的功能时帮助缩小 APK 的另一种方法是仅包含您实际使用的 Google Play 服务中功能的库.
例如,如果您使用的唯一 Google Play 服务 API 是 Maps API v2,而不是在 build.gradle
中包含整个 Google Play 服务库:
编译'com.google.android.gms:play-services:7.8.0'
...您可以只包含 Maps API v2 部分:
编译'com.google.android.gms:play-services-maps:7.8.0'
请参阅 Google Play 服务 -有选择地将 API 编译到您的可执行文件中" 部分以了解您可以拆分哪些 API 的详细信息.以下是截至 2015 年 9 月的列表:
- Google+
com.google.android.gms:play-services-plus:7.8.0
- Google 帐户登录
com.google.android.gms:play-services-identity:7.8.0
- Google Actions,基本客户端库
com.google.android.gms:play-services-base:7.8.0
- Google 应用索引
com.google.android.gms:play-services-appindexing:7.8.0
- Google 应用邀请
com.google.android.gms:play-services-appinvite:7.8.0
- Google Analytics
com.google.android.gms:play-services-analytics:7.8.0
- Google Cast
com.google.android.gms:play-services-cast:7.8.0
- Google Cloud Messaging
com.google.android.gms:play-services-gcm:7.8.0
- Google 云端硬盘
com.google.android.gms:play-services-drive:7.8.0
- Google Fit
com.google.android.gms:play-services-fitness:7.8.0
- Google 位置、活动识别和地点
com.google.android.gms:playservices-location:7.8.0
- Google 地图
com.google.android.gms:play-services-maps:7.8.0
- Google 移动广告
com.google.android.gms:play-services-ads:7.8.0
- Mobile Vision
com.google.android.gms:play-services-vision:7.8.0
- Google Nearby
com.google.android.gms:play-services-nearby:7.8.0
- Google 全景查看器
com.google.android.gms:play-services-panorama:7.8.0
- Google Play 游戏服务
com.google.android.gms:play-services-games:7.8.0
- SafetyNet
com.google.android.gms:play-services-safetynet:7.8.0
- Google 电子钱包
com.google.android.gms:play-services-wallet:7.8.0
- Android Wear
com.google.android.gms:play-services-wearable:7.8.0
I have installed Google Play Services and created a Hello World app to test that everything is working fine and I think the application size is too big: 4.98 MB. I'm using Android Studio and I've followed the instructions detailed in the android developers web.
This is my gradle file:
apply plugin: 'android'
android {
compileSdkVersion 19
buildToolsVersion "19.0.1"
defaultConfig {
minSdkVersion 15
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.google.android.gms:play-services:4.3.23'
}
EDIT
This is my proguard file:
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents();
}
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
public static final *** NULL;
}
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
@com.google.android.gms.common.annotation.KeepName *;
}
-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}
** EDIT 2 **
I've installed Google Play Services using the last version of Intellij Idea, and now the apk is 3.52 MB. I don't know if this is an acceptable size.
Is this normal?
No, that's not normal - earlier builds of my GPSTest app that included Google Play Services for maps were only 808KB after being obfuscated using Proguard- current version (after adding another library) is around 1,497KB after obfuscation.
I would recommend exporting the APK from the command line using the following steps to avoid potential issues with Android Studio:
- Go to root of the project at the command line
- Run
gradlew assembleRelease
- Find the signed and obfuscated APK in
/app/build/apk
folder
If you are exporting the APK via Android Studio, be aware that there is a known issue where Android Studio will export using the assembleDebug
task instead of the assembleRelease
task by default. As a result, any configurations in your build.gradle
file for running Proguard that are specific to the release buildType won't be executed.
As a workaround for exporting via Android Studio, you can change the default Build Variant via the following steps:
- In Android Studio, open "View->Tool Windows->Build Variants"
- In the window that opens, change "Build Variant" from
debug
torelease
.
Now when you do "Build->Generate Signed APK...", Android Studio should run the release Build Variant, which should run Proguard if you have it configured correctly in build.gradle
. You can change back to debug
variant while debugging your app on a normal basis.
If you want to replicate my settings from GPSTest, here's the proguard.cfg
:
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.preference.Preference
-keepclasseswithmembers class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents();
}
-dontwarn **CompatHoneycomb
-dontwarn **CompatCreatorHoneycombMR2
-dontwarn **AccessibilityServiceInfoCompatJellyBeanMr2
-dontwarn android.support.v4.view.**
-dontwarn android.support.v4.media.**
-dontwarn com.actionbarsherlock.internal.**
-keep class android.support.v4.** { *; }
-keepattributes *Annotation*
-keep public class * extends android.view.View
-keep public class * extends android.view.ViewGroup
-keep public class * extends android.support.v4.app.Fragment
-keepclassmembers class * extends com.actionbarsherlock.ActionBarSherlock {
<init>(android.app.Activity, int);
}
... and build.gradle
:
apply plugin: 'android'
android {
compileSdkVersion 19
buildToolsVersion "19.0.0"
defaultConfig {
minSdkVersion 8
targetSdkVersion 19
}
if (project.hasProperty("secure.properties")
&& new File(project.property("secure.properties")).exists()) {
Properties props = new Properties()
props.load(new FileInputStream(file(project.property("secure.properties"))))
signingConfigs {
debug {
storeFile file("gpstest.debug.keystore")
}
release {
storeFile file(props['key.store'])
keyAlias props['key.alias']
storePassword "askmelater"
keyPassword "askmelater"
}
}
} else {
signingConfigs {
debug {
storeFile file("gpstest.debug.keystore")
}
release {
// Nothing here
}
}
}
buildTypes {
release {
runProguard true
proguardFile 'proguard.cfg'
signingConfig signingConfigs.release
}
}
}
task askForPasswords << {
// Must create String because System.readPassword() returns char[]
// (and assigning that below fails silently)
def storePw = new String(System.console().readPassword("\nKeystore password: "))
def keyPw = new String(System.console().readPassword("Key password: "))
android.signingConfigs.release.storePassword = storePw
android.signingConfigs.release.keyPassword = keyPw
}
tasks.whenTaskAdded { theTask ->
if (theTask.name.equals("packageRelease")) {
theTask.dependsOn "askForPasswords"
}
}
dependencies {
compile project(':ShowcaseViewLibrary')
compile 'com.google.android.gms:play-services:3.2.65'
compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
compile 'org.jraf:android-switch-backport:1.2'
compile 'com.google.maps.android:android-maps-utils:0.2.1'
}
Entire GPSTest source code is available on Github if you want to use it as a sample.
EDIT
Another way to help shrink your APK when using features from Google Play Services v6.5 or higher is to include only the library for the feature in Google Play Services that you're actually using.
For example, if the only Google Play Services API you're using is the Maps API v2, instead of including the entire Google Play Services library in build.gradle
:
compile 'com.google.android.gms:play-services:7.8.0'
...you can just include the Maps API v2 portion:
compile 'com.google.android.gms:play-services-maps:7.8.0'
See the Google Play Services - "Selectively compiling APIs into your executable" section for details on what APIs you can split out. Here's a list as of Sept. 2015:
- Google+
com.google.android.gms:play-services-plus:7.8.0
- Google Account Login
com.google.android.gms:play-services-identity:7.8.0
- Google Actions, Base Client Library
com.google.android.gms:play-services-base:7.8.0
- Google App Indexing
com.google.android.gms:play-services-appindexing:7.8.0
- Google App Invites
com.google.android.gms:play-services-appinvite:7.8.0
- Google Analytics
com.google.android.gms:play-services-analytics:7.8.0
- Google Cast
com.google.android.gms:play-services-cast:7.8.0
- Google Cloud Messaging
com.google.android.gms:play-services-gcm:7.8.0
- Google Drive
com.google.android.gms:play-services-drive:7.8.0
- Google Fit
com.google.android.gms:play-services-fitness:7.8.0
- Google Location, Activity Recognition, and Places
com.google.android.gms:playservices-location:7.8.0
- Google Maps
com.google.android.gms:play-services-maps:7.8.0
- Google Mobile Ads
com.google.android.gms:play-services-ads:7.8.0
- Mobile Vision
com.google.android.gms:play-services-vision:7.8.0
- Google Nearby
com.google.android.gms:play-services-nearby:7.8.0
- Google Panorama Viewer
com.google.android.gms:play-services-panorama:7.8.0
- Google Play Game services
com.google.android.gms:play-services-games:7.8.0
- SafetyNet
com.google.android.gms:play-services-safetynet:7.8.0
- Google Wallet
com.google.android.gms:play-services-wallet:7.8.0
- Android Wear
com.google.android.gms:play-services-wearable:7.8.0
这篇关于Google Play 服务使 apk 太大的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!