是什么让某些安卓类"必须-keep"?安卓类、QUOT、keep

2023-09-06 13:19:46 作者:远赴惊鸿宴.

我注意到,模板 proguard.cfg 总是包含以下内容:

I noticed that the "template" proguard.cfg always contains the following:

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService

为什么这些特定的类,而不是别人?

Why these particular classes and not others?

这是必须不被优化出的ProGuard的类的完整列表?

Is this the complete list of classes that must not be "optimized out" by ProGuard?

推荐答案

总之,这些类都在proguard.cfg模板,因为这些类可以在AndrodiManifest.xml声明。

In short, those classes are in the proguard.cfg template because those classes can be declared in the AndrodiManifest.xml.

考虑这个最小的应用程序:

Consider this minimal application:

CustomTextView.java:

package com.example.android;

import android.content.Context;
import android.widget.TextView;

public class CustomTextView extends TextView {
    public CustomTextView(Context context) {
        super(context);
        setText("The class name of this class is not important");
    }
}

ExampleActivity.java:

package com.example.android;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class ExampleActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new CustomTextView(this));
        Log.i("ExampleActivity", "The class name of this class is important");
    }
}

的Andr​​oidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.example.android"
      android:versionCode="1"
      android:versionName="1.0">
    <application>
        <activity android:name=".ExampleActivity">
            <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
            </intent-filter>
        </activity>
    </application>
</manifest>

现在,如果没有行

-keep public class * extends android.app.Activity

在proguard.cfg文件,ProGuard的人也许会重命名为ExampleActivity A 。 它不知道AndroidManifest.xml中任何事情的,所以它不会触及清单的。由于Android操作系统使用的应用程序清单,以启动一个应用程序申报类名,Android操作系统将尝试实例为ExampleActivity ,但该类不存在,因为ProGuard的更名!

in the proguard.cfg file, proguard might be tempted to rename ExampleActivity to A. It does not know anything about AndroidManifest.xml though, so it will not touch the manifest. Since the Android OS uses class names declared in the application manifest to start an application, the Android OS will try to instantiate ExampleActivity, but that class won't exist since proguard renamed it!

CustomTextView 的情况下,它的优良的ProGuard的重新命名它说 B ,因为名称该类并不重要,因为它没有在清单中声明,只有$ C C的ProGuard的$引用时,它改变 CustomTextView 的类名称将会更新。

In the case of CustomTextView, it's fine for proguard to rename it to say B, because the name of the class is not important since it is not declared in the manifest, only referenced by code that proguard will update when it changes the class name of CustomTextView.

在这种或那种方式,从模板proguard.cfg文件中引用的所有类都可以在清单中声明,所以ProGuard的不能碰他们。

In one way or another, all classes referenced from the template proguard.cfg file can be declared in the manifest, so proguard must not touch them.