【转】制做不暴露源码的Android Library Project

        Android Library Project(库工程)是一个能够被其余Android工程所引用的工程。那为何须要使用这个工程呢,打个比方,咱们在开发Android项目的时候,经常会遇到这样的问题,几个Android项目的开发过程当中,会有能够重复利用的代码段或者资源。若是每一个项目都要重复编写或者添加这些代码或者资源,将会很是的影响效率。为了不重复发明轮子,咱们能够将这些重复的资源添加到Android Library Project中。那么之后,咱们要复用这些东西的时候,只要在当前项目中引用这个Android Library Project就能够了。java

       固然咱们的Android Library Project不单单是给咱们本身使用,若是咱们要把这个Android Lib Project共享给别人,可是又不但愿暴露本身的源代码,那么,这就是咱们这篇文章要讲的内容。android

HOW

首先,这篇文章中咱们会提到三个项目。ide

LibraryProject : 咱们须要共享给别人的不包含源代码的工程。布局

LibraryProjectSource : LibraryProject包含源代码的版本。测试

AndroidProject : 引用LibraryProject的版本。ui

         和咱们开发正常的Android项目同样,咱们先创建一个项目,可是在开始正常的编码以前,咱们须要先弄清楚原理和注意事项:不暴露源码的方式是将LibraryProjectSource中的源代码打包成JAR包,而后添加到咱们要共享给他人的工程中。若是这个工程中没有引用到资源(res目录下的文件),那么就很容易实现了。可是若是有引用到资源(例如经过R.id.resource方式),咱们就能够能会遇到资源引用错乱的问题。编码

          打个比方,在AndroidProject中若是引用TextView能够会定位到一个ImageView上。这是由于,若是在源代码中有使用R.id.resource引用资源,在编译成JAR包的时候,R.id.resource会用R.java文件中相应的十六进制的int值替换。可是在AndroidProject文件中资源的会结合LibraryProject中的资源从新生成一个新的十六进制int值。而同一个资源,在LibraryProjectSource中的这个int值和AndroidProject中的就可能不相同了。spa

因此咱们必须实时的获取这个十六进制的数值。有两个方式能够选择:code

1.(推荐)经过android.content.res.Resources类的int getIdentifier(String name, String defType, String defPackage) . xml

        好比,咱们须要在Activity中设置布局,咱们要获得res/layout/目录下的 “main_layout.xml” 布局文件的ID.

   @Override     
   protected void onCreate(Bundle savedInstanceState) {
            ...
            int id = getResources().getIdentifier(“main_layout“, "layout", getPackageName());
            setContentView(id);
            ...
   }

注意:在编写Library代码的时候,就应该采用这样的方式去获取id值,而不是简单的用R.id.xxxx.


2.使用Java语言的反射机制。可是使用反射毕竟麻烦。

   Field field = R.layout.class.getField("main_layout");
   int i = field.getInt(new R.layout());
   return i;

PUBLISH

最后,咱们须要将编写好的源代码导成JAR包,添加到LibraryProject中。而后咱们就能够将这个工程共享给其余人了。具体步骤以下:

1. 将LibraryProjectSource的类文件导出:打开工程文件夹目录->打开bin目录->将与工程名相同的JAR文件复制出来。将原工程依赖的JAR包导出:打开工程文件夹目录->打开libs目录->其中的JAR文件复制出来。

2. 创建一个与 LibraryProjectSource 的包名相同的 LibraryProject(包名是Android系统辨识应用程序的标志),建立的时候不选择建立Activity,将这个工程做为Lib工程。

3. 将1中导出两种包复制到Lib工程的libs文件夹下,右键Lib工程->Properties->Android->勾选“Is Library”->肯定。将 LibraryProjectSource 文件夹下的资源文件复制到Lib工程下(主要是assets和res文件夹,替换原来的文件)。把原工程中AndroidManifest.xml替换此工程的AndroidManifest.xml。这样Lib Project就完成了。

以后,写一个Demo(AndroidProject)测试一下 LibraryProject 可否使用:

新建工程->右键工程->Properties->Android->Add->选择2中创建的LibraryProject->OK;

接着从LibraryProject导入1中导出的类文件:右键工程->Properties->Java Build Path->Add JARs->选中2中的Lib 工程下的libs文件下的与1中原工程同名的JAR包,再选择Order and Export,将加入的包打钩。

把Lib中的AndroidManifest.xml中必要的部分复制到Demo工程中,例如:原工程中须要用到的权限声明,activity,service,broadcast部分。

TIPS

打开工程文件夹目录->打开bin目录->将与工程名相同的JAR文件复制出来

当咱们从LibraryProjectSource中的bin目录下拷贝出自动生成的jar的时候,经过jd-gui简单的反编译一下,就会发现这个jar其实就是源码的打包,而且是原封不动的打包。。其实这就有违了咱们的初衷:隐藏源代码。

解决办法应该是:导出jar包以后,而后在进行混淆等操做。混淆jar包,能够用proguard等。

相关文章
相关标签/搜索