Android开发:将apk源代码编译成java library + resource形式

有时候我们希望能够将apk的源代码编译成一个java library的形式(做成一个模块),集成进另外一个apk里面,以避免用户在使用这个功能的时候要装两个apk。另外一个好处就是如果apk里面使用了大量非Android SDK中提供的API,而又需要被集成另外一个通过eclipse或者是通过Android Studio开发的应用程序时,可以很好地避免IDE编译不过的情况。下面主要是从有整个Android项目代码的情况,通过写Android.mk(makefile)来生成我们所需要的apk。

  •  生成java library的方法

以packages/apps/Launcher2为例:

LOCAL_PATH := $(call my-dir)

# ------------------------------------------------------
# LIB
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_STATIC_JAVA_LIBRARIES := \
    android-common \
    android-support-v13

LOCAL_SRC_FILES := \
    $(call all-java-files-under, src) \
    $(call all-renderscript-files-under, src)

LOCAL_RESOURCE_DIR := \
    $(LOCAL_PATH)/res

LOCAL_MODULE := Launcher2Lib

include $(BUILD_STATIC_JAVA_LIBRARY)

# ------------------------------------------------------
# APP
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_STATIC_JAVA_LIBRARIES := \
    Launcher2Lib

LOCAL_FULL_MANIFEST_FILE := \
    $(LOCAL_PATH)/AndroidManifest.xml

LOCAL_PACKAGE_NAME := Launcher2App

LOCAL_CERTIFICATE := shared
LOCAL_PRIVILEGED_MODULE := true

#LOCAL_OVERRIDES_PACKAGES := Home
LOCAL_PROGUARD_FLAG_FILES := proguard.flags

include $(BUILD_PACKAGE)

可以看到这个Android.mk包含两个模块:

  1. Lib: Launcher2Lib 是一个static java library
  2. App: launcher2App 是最终编译成的apk

单从library上看,我们最终需要res文件夹和 out/target/product/?/obj/JAVA_LIBRARIES/Launcher2Lib_intermediates/javalib.jar文件,如果你还使用到了AndroidManifest.xml中的资源,可能还需要AndroidManifest.xml (AndroidManifest.xml会通过aapt生成Manifest.java)

编译Library需要注意的是:

  1. 一定要指定LOCAL_RESOURCE_DIR, 不然编译会报错(不编译resource,进而不生成R.java),详见build/core/static_java_library.mk。
  2. 要特别注意R.java所在package的命名,特别是集成的app也有resource的情况。
  3. 可以通java rules重命名
  4. Library中引用到的R.id.xxx (不再是final static)不能放在switch语句中,否则会报错。
  • class/package name重命名 [2016-01-19 20:26:11 ]

生成的R.java/class, Manifest.java/class的重命名方法:在Android.mk中新增LOCAL_JARJAR_RULES,

LOCAL_JARJAR_RULES := \
    $(LOCAL_PATH)/jarjar-rules.txt

jarjar-rules.txt文件内容为:

rule com.android.launcher2.R* com.another.package.R@1
rule com.android.launcher2.Manifest* com.android.package.R@1

相关文档:https://code.google.com/p/jarjar/wiki/CommandLineDocs;相关代码在:external/jarjar

From the command-line

java -jar jarjar.jar [help]

Prints this help message.

java -jar jarjar.jar strings <cp>

Dumps all string literals in classpath <cp>. Line numbers will be included if the classes have debug information.

java -jar jarjar.jar find <level> <cp1> [<cp2>]

Prints dependencies on classpath <cp2> in classpath <cp1>. If <cp2> is omitted, <cp1> is used for both arguments.

The level argument must be class or jar. The former prints dependencies between individual classes, while the latter only prints jar->jar dependencies. A “jar” in this context is actually any classpath component, which can be a jar file, a zip file, or a parent directory (see below).

java -jar jarjar.jar process <rulesFile> <inJar> <outJar>

Transform the <inJar> jar file, writing a new jar file to <outJar>. Any existing file named by <outJar> will be deleted.

The transformation is defined by a set of rules in the file specified by the rules argument (see below).

Classpath format

The classpath argument is a colon or semi-colon delimited set (depending on platform) of directories, jar files, or zip files. See the following page for more details: http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/classpath.html

Mustang-style wildcards are also supported: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6268383

Rules file format

The rules file is a text file, one rule per line. Leading and trailing whitespace is ignored. There are three types of rules:

rule <pattern> <result>
zap <pattern>
keep <pattern>

The standard rule (rule) is used to rename classes. All references to the renamed classes will also be updated. If a class name is matched by more than one rule, only the first one will apply.

<pattern> is a class name with optional wildcards. ** will match against any valid class name substring. To match a single package component (by excluding . from the match), a single * may be used instead.

<result> is a class name which can optionally reference the substrings matched by the wildcards. A numbered reference is available for every * or ** in the <pattern>, starting from left to right: @1, @2, etc. A special @0 reference contains the entire matched class name.

The zap rule causes any matched class to be removed from the resulting jar file. All zap rules are processed before renaming rules.

The keep rule marks all matched classes as “roots”. If any keep rules are defined all classes which are not reachable from the roots via dependency analysis are discarded when writing the output jar. This is the last step in the process, after renaming and zapping.

发表评论

电子邮件地址不会被公开。 必填项已用*标注