如何在Android Studio上准备一个封闭源码的SDK模块? 背景

如何在Android Studio上准备一个封闭源码的SDK模块? 背景,android,android-studio,sdk,obfuscation,r.java-file,Android,Android Studio,Sdk,Obfuscation,R.java File,我正在开发一个非常流行的应用程序,它的一部分应该成为SDK(开发者可以使用),该应用程序将拆分为两个应用程序(都使用SDK) 据我所知,有多种方法可以创建SDK模块(以前在Eclipse上称为“项目”): 完全开源(Android库)-所有源代码和资源都是开源的,可以修改。Facebook的SDK和许多Github回购就是一个例子 一个Jar文件,可以关闭源代码 问题 遗憾的是,我不能使SDK开源,它应该相对地受到保护,而不是窥视(模糊等) 这里的问题是,SDK需要使用自己的一些资源(drawa

我正在开发一个非常流行的应用程序,它的一部分应该成为SDK(开发者可以使用),该应用程序将拆分为两个应用程序(都使用SDK)

据我所知,有多种方法可以创建SDK模块(以前在Eclipse上称为“项目”):

  • 完全开源(Android库)-所有源代码和资源都是开源的,可以修改。Facebook的SDK和许多Github回购就是一个例子

  • 一个Jar文件,可以关闭源代码

  • 问题 遗憾的是,我不能使SDK开源,它应该相对地受到保护,而不是窥视(模糊等)

    这里的问题是,SDK需要使用自己的一些资源(drawables、String等),到目前为止(因为我没有很多创建SDK的经验),我找到了两种方法来处理SDK的资源:

  • 使用反射和/或“context.getResources().getIdentifier”。这是相当混乱的,因为我完全失去了代码的“R”用法。此外,正如我所写的,它还存在“可样式化”的问题。这也使得很难找到未使用的资源

  • 更糟糕的方法是:将资源放在assets文件夹中,以奇怪的方式将文件放在jar文件中

  • 请注意,SDK的一部分包括自定义视图(例如,从TextView扩展的类),因此即使我将SDK拆分为两个模块—资源和java文件,它们都可能存在依赖性问题(每个都使用另一个)

    问题 有可能以某种方式解决这个问题吗

    SDK的代码部分是否可以保持封闭源代码,像往常一样访问“R”文件,并使我和使用SDK的人都能轻松使用

    然后,我将如何生成通过Android Studio进行模糊处理的jar文件?有没有可能准备好以后通过gradle使用

    我可以把SDK的Android库变成一个模糊的jar文件而不用担心“R”文件吗?我这样问是因为这样我可以享受两个世界:对于我们的应用程序,它将保持开源,而对于第三方应用程序,它将是封闭的


    编辑:考虑到这应该很容易,我自己也试过了。我创建了一个全新的POC项目,该项目有一个名为“sdkmodule”的Android库模块,并向其中添加了这个类:

    public class SdkClass
          {
          public String doIt(Context context)
            {
            return context.getResources().getString(R.string.app_name);
            }
          }
    
    然后,我让应用程序的模块使用这个模块,并在其中编写了以下代码:

      @Override
      protected void onCreate(Bundle savedInstanceState)
        {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SdkClass sdkClass=new SdkClass();
        Log.d("AppLog","string from SDK:"+sdkClass.doIt(this));
        Log.d("AppLog","string with same ID name from app:"+getResources().getString(R.string.app_name));
        }
    
    我所期望的是,第一个日志将打印SDK模块中的字符串,第二个日志将显示当前项目的字符串,但我得到了一个异常:

    java.lang.NoClassDefFoundError: Failed resolution of: Lcom/example/user/sdkmodule/R$string;
    
    在另一次尝试中,我得到了应用程序本身使用的相同字符串(使用SDK模块的字符串)。在另一次运行中,SDK按照我的要求生成了所需的字符串

    怎么可能呢?我该怎么办

    此外,我还尝试在SDK本身中创建第二个活动,并在其中创建了一个资源,该资源与应用程序本身具有相同的资源名称(用于布局中的textView),但具有不同的值,但当我到达此活动时,我看到了应用程序使用的资源名称

    这是一个项目,zipped(忽略文件夹的名称,我也想试试flavors):


    您的问题的答案是将您的库打包并作为

    此格式允许您提供一个模糊的SDK jar及其资源和R映射文件

    这种格式是一种标准格式,完全受支持(实际上它取代了旧的APKLib格式,后者只支持源文件的分发)

    当然,Gradle和Android Studio也支持它。

    它做你想做的事。它类似于特定于Android的JAR文件,包含编译后的代码,但包含自己的资源和清单。您还可以将模糊处理作为构建过程的一部分。默认情况下,当前版本的Android Studio(1.2)和Gradle会自动为您在项目中创建的所有库模块生成.AAR文件

    只需将模块的Gradle文件中的
    apply plugin:'com.android.application'
    更改为
    apply plugin:'com.android.library'
    ,即可将应用程序模块更改为将发布AAR文件的库项目。每次生成后,.AAR文件将放在
    MODULENAME/build/outputs/AAR
    文件夹中。一些

    更新问题后编辑1:

    编译最终APK时,AAR中的资源将与应用程序模块合并。应用程序资源将覆盖库的。这可能是出于设计,允许使用第三方库的用户在创建应用程序时自定义其资源,而无需重建库。我认为解决资源冲突问题的最简单方法就是将sdkmodule资源命名为更独特的名称。为什么不使用字符串键
    R.string.com\u example\u sdk\u name
    或其他什么


    不,默认情况下AAR库不会被混淆,但是您可以让您的AAR库处理这个问题。其他工具也可以使用。

    Android库项目的AAR格式已经可以与Android Studio和Gradle for Android一起使用一年多了。Maven用户也可以直接使用AAR。对于Eclipse/Ant来说,将AAR解包到库项目(使用编译过的JAR而不是源代码)并不是那么难,至少对于基本的东西来说是这样(这解释了过程)。Play Services SDK是以这种基本方式发布的,使用编译的Java字节码而不是源代码。假设我有一个可用的应用程序,它的哪个模块应该是SDK(或者如果您愿意,可以使用两个模块,一个用于资源,一个用于源代码),下一步应该做什么?您提供的网站是针对Eclipse的,它是用于使用AAR而不是准备AAR的(尽管这对kn来说也很重要)
    https://drive.google.com/file/d/0B-PZZGk2vPohX25WUDNKTmotUTg/view?usp=sharing