草庐IT

Android Studio - Proguard 'keep' 规则被忽略?

coder 2023-12-15 原文

我最近将我的 Android 项目从 Eclipse 迁移到了 Android Studio。

Android Studio 创建的调试版应用在设备上运行良好,但发布版在启动时崩溃。

这是我的应用程序的 build.gradle 文件:

apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "com.example.myapp"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 49
        versionName "1.3.1"
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    packagingOptions {
        //exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
    compile 'com.android.support:support-v13:23.1.1'
    compile 'org.apache.httpcomponents:httpmime:4.2.3'
    compile 'org.twitter4j:twitter4j-core:4.0.2'
    compile 'com.facebook.android:facebook-android-sdk:4.8.2'
    compile 'ch.acra:acra:4.7.0'
    compile 'com.google.android.gms:play-services-analytics:8.3.0'
    compile 'com.google.android.gms:play-services-ads:8.3.0'
    compile 'com.google.android.gms:play-services-plus:8.3.0'
    //compile 'com.google.android.gms:play-services:8.3.0'
    compile 'com.google.android.gms:play-services-gcm:8.3.0'
}

这是我的 proguard-rules.pro 文件:

# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in P:\Program Files\Android\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}



#
# My Classes - start
#

-keep public class com.example.myapp.SplashActivity
-keep public class com.example.myapp.FragmentActivityWithListener
-keep public class com.example.myapp.AbstractHelpActivity
-keep public class com.example.myapp.GetContentFromWebTask$CompletedListener
# Don't rename the MenuBuilder filename as this is referenced in our AbstractHelpActivity.java file
-keep public class android.support.v7.internal.view.menu.MenuBuilder
-keep class android.support.v7.widget.ShareActionProvider { *; }

#
# My Classes - end
#


#
# Twitter library - start
#

-dontwarn twitter4j.**
-keep class twitter4j.** { *; }

#
# Twitter library - end
#


#
# Google Play Service library - start
#

-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;
}

#
# Google Play Service library - end
#


#
# ACRA - start
#

#ACRA specifics
# Restore some Source file names and restore approximate line numbers in the stack traces,
# otherwise the stack traces are pretty useless
-keepattributes SourceFile,LineNumberTable

# ACRA needs "annotations" so add this...
# Note: This may already be defined in the default "proguard-android-optimize.txt"
# file in the SDK. If it is, then you don't need to duplicate it. See your
# "project.properties" file to get the path to the default "proguard-android-optimize.txt".
-keepattributes *Annotation*

# keep this class so that logging will show 'ACRA' and not a obfuscated name like 'a'.
# Note: if you are removing log messages elsewhere in this file then this isn't necessary
-keep class org.acra.ACRA {
    *;
}

# keep this around for some enums that ACRA needs
-keep class org.acra.ReportingInteractionMode {
    *;
}

-keepnames class org.acra.sender.HttpSender$** {
    *;
}

-keepnames class org.acra.ReportField {
    *;
}

# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter {
    public void addCustomData(java.lang.String,java.lang.String);
    public void putCustomData(java.lang.String,java.lang.String);
    public void removeCustomData(java.lang.String);
}

# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter {
    public void handleSilentException(java.lang.Throwable);
}

#
# ACRA - end
#


#
# Facebook - start
#
-keep class com.facebook.** { *; }
-keepattributes Signature
#
# Facebook - end
#

这是堆栈跟踪:

01-06 11:48:58.313 27667-27667/? E/ACRA: ACRA caught a RuntimeException for com.example.myapp
     java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.myapp/com.example.myapp.SplashActivity}: java.lang.ClassNotFoundException: Didn't find class "com.example.myapp.SplashActivity" on path: DexPathList[[zip file "/data/app/com.example.myapp-1/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2650)
         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2873)
         at android.app.ActivityThread.access$900(ActivityThread.java:181)
         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1482)
         at android.os.Handler.dispatchMessage(Handler.java:102)
         at android.os.Looper.loop(Looper.java:145)
         at android.app.ActivityThread.main(ActivityThread.java:6145)
         at java.lang.reflect.Method.invoke(Native Method)
         at java.lang.reflect.Method.invoke(Method.java:372)
         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
      Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.myapp.SplashActivity" on path: DexPathList[[zip file "/data/app/com.example.myapp-1/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
         at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
         at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
         at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
         at android.app.Instrumentation.newActivity(Instrumentation.java:1079)
         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2640)
         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2873) 
         at android.app.ActivityThread.access$900(ActivityThread.java:181) 
         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1482) 
         at android.os.Handler.dispatchMessage(Handler.java:102) 
         at android.os.Looper.loop(Looper.java:145) 
         at android.app.ActivityThread.main(ActivityThread.java:6145) 
         at java.lang.reflect.Method.invoke(Native Method) 
         at java.lang.reflect.Method.invoke(Method.java:372) 
         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) 
         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) 
        Suppressed: java.lang.NoClassDefFoundError: com.example.myapp.SplashActivity
         at dalvik.system.DexFile.defineClassNative(Native Method)
         at dalvik.system.DexFile.defineClass(DexFile.java:226)
         at dalvik.system.DexFile.loadClassBinaryName(DexFile.java:219)
         at dalvik.system.DexPathList.findClass(DexPathList.java:321)
         at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:54)
                ... 14 more
        Suppressed: java.lang.ClassNotFoundException: com.example.myapp.SplashActivity
         at java.lang.Class.classForName(Native Method)
         at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
         at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
         at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
                ... 13 more
      Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
01-06 11:48:58.363 27667-27667/? E/ACRA: Not adding buildConfig to log. Class Not found : com.example.myapp.BuildConfig. Please configure 'buildConfigClass' in your ACRA config
01-06 11:48:58.453 27667-27691/? E/ACRA: ACRA caught a InternalError for com.example.myapp
     java.lang.InternalError: Thread starting during runtime shutdown
         at java.lang.Thread.nativeCreate(Native Method)
         at java.lang.Thread.start(Thread.java:1063)
         at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:920)
         at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1336)
         at com.android.okhttp.ConnectionPool.get(ConnectionPool.java:211)
         at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:109)
         at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:368)
         at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:296)
         at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:399)
         at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:110)
         at org.acra.e.b.a(HttpRequest.java:122)
         at org.acra.sender.HttpSender.a(HttpSender.java:245)
         at org.acra.af.a(SendWorker.java:181)
         at org.acra.af.a(SendWorker.java:140)
         at org.acra.af.run(SendWorker.java:76)
01-06 11:48:58.483 27667-27691/? E/ACRA: Not adding buildConfig to log. Class Not found : com.example.myapp.BuildConfig. Please configure 'buildConfigClass' in your ACRA config
01-06 11:48:58.503 27667-27691/? E/AndroidRuntime: FATAL EXCEPTION: Thread-2863
               Process: com.example.myapp, PID: 27667
               java.lang.InternalError: Thread starting during runtime shutdown
                   at java.lang.Thread.nativeCreate(Native Method)
                   at java.lang.Thread.start(Thread.java:1063)
                   at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:920)
                   at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1336)
                   at com.android.okhttp.ConnectionPool.get(ConnectionPool.java:211)
                   at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:109)
                   at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:368)
                   at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:296)
                   at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:399)
                   at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:110)
                   at org.acra.e.b.a(HttpRequest.java:122)
                   at org.acra.sender.HttpSender.a(HttpSender.java:245)
                   at org.acra.af.a(SendWorker.java:181)
                   at org.acra.af.a(SendWorker.java:140)
                   at org.acra.af.run(SendWorker.java:76)
01-06 11:48:58.503 1038-1476/? W/ActivityManager:   Force finishing activity com.example.myapp/.SplashActivity

看来我在 proguard-rules.pro 文件中指定的 keep 规则没有被用作 com.example.myapp.SplashActivity 找不到类。

我检查了 Android Developers ProGuard页面,看起来我已经正确设置了所有内容,所以我不知道为什么它不起作用。

任何人都可以建议我需要做什么才能最终得到一个有效的混淆 apk 吗?

最佳答案

我发现了问题。它在我项目的 build.gradle 文件中:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()       // This is the default repo
        mavenCentral()  // This is the Maven Central repo
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.0'
        classpath 'com.google.gms:google-services:1.5.0-beta2'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()       // This is the default repo
        mavenCentral()  // This is the Maven Central repo
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

解决方案是将 classpath 'com.android.tools.build:gradle:1.3.0' 更改为 classpath 'com.android.tools.build:gradle:1.5。 0'.

(我通过创建一个新的测试项目并比较各个 build.gradle 文件中的值发现了这一点。)

顺便说一句,我的 proguard-rules.pro 文件的内容现在只是...

#
# Twitter - start
#

-dontwarn twitter4j.**
-keep class twitter4j.** { *; }

#
# Twitter - end
#


#
# Support library / ShareActionProvider - start
#

-keep class android.support.v7.internal.** { *; }
-keep interface android.support.v7.internal.** { *; }
-keep class android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }

#
# Support library / ShareActionProvider - start
#


#
# ACRA - start
#

#ACRA specifics
# Restore some Source file names and restore approximate line numbers in the stack traces,
# otherwise the stack traces are pretty useless
-keepattributes SourceFile,LineNumberTable

# ACRA needs "annotations" so add this...
# Note: This may already be defined in the default "proguard-android-optimize.txt"
# file in the SDK. If it is, then you don't need to duplicate it. See your
# "project.properties" file to get the path to the default "proguard-android-optimize.txt".
-keepattributes *Annotation*

# keep this class so that logging will show 'ACRA' and not a obfuscated name like 'a'.
# Note: if you are removing log messages elsewhere in this file then this isn't necessary
-keep class org.acra.ACRA {
    *;
}

# keep this around for some enums that ACRA needs
-keep class org.acra.ReportingInteractionMode {
    *;
}

-keepnames class org.acra.sender.HttpSender$** {
    *;
}

-keepnames class org.acra.ReportField {
    *;
}

# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter {
    public void addCustomData(java.lang.String,java.lang.String);
    public void putCustomData(java.lang.String,java.lang.String);
    public void removeCustomData(java.lang.String);
}

# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter {
    public void handleSilentException(java.lang.Throwable);
}

#
# ACRA - end
#

...所以我不需要很多旧指令或 Dhawal 在他的回答中建议的指令。

注意 - 我了解从 ACRA 4.8 开始不再需要 ACRA 指令。

关于Android Studio - Proguard 'keep' 规则被忽略?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34633319/

有关Android Studio - Proguard 'keep' 规则被忽略?的更多相关文章

  1. ruby-on-rails - rails : keeping DRY with ActiveRecord models that share similar complex attributes - 2

    这似乎应该有一个直截了当的答案,但在Google上花了很多时间,所以我找不到它。这可能是缺少正确关键字的情况。在我的RoR应用程序中,我有几个模型共享一种特定类型的字符串属性,该属性具有特殊验证和其他功能。我能想到的最接近的类似示例是表示URL的字符串。这会导致模型中出现大量重复(甚至单元测试中会出现更多重复),但我不确定如何让它更DRY。我能想到几个可能的方向...按照“validates_url_format_of”插件,但这只会让验证干给这个特殊的字符串它自己的模型,但这看起来很像重溶液为这个特殊的字符串创建一个ruby​​类,但是我如何得到ActiveRecord关联这个类模型

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  3. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  4. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  5. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  6. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  7. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  8. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

    我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

  9. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

  10. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

随机推荐