Как подготовить закрытый исходный SDK модуль на Android Studio?


Фон

Я работаю над приложением, которое стало очень популярным, настолько, что часть его должна стать SDK (который будет доступен для разработчиков), и приложение разделится на 2 приложения (оба используют SDK).

Согласно тому, что я знаю, существует несколько способов создания модуля SDK (ранее называвшегося "project" на Eclipse):

  1. Полностью открытые источники (библиотека Android) - все источники и ресурсы являются открытыми и могут быть изменены. Один примером может быть SDK Facebook и множество РЕПО на Github.

  2. Один файл Jar, который может быть закрыт исходным кодом.

Проблема

К сожалению, я не могу сделать SDK открытым исходным кодом,и он должен быть относительно защищен от посторонних глаз (запутанный и т. д...).

Проблема здесь в том, что SDK должен использовать некоторые собственные ресурсы (drawables, strings,...), и до сих пор (потому что у меня не было большого опыта в создании SDK) я нашел 2 способа обработки ресурсы для SDK:

  1. Используйте отражение и / или " контекст.getResources ().getIdentifier". Это довольно грязно, так как я теряю все использование кода "R". Кроме того, у него есть проблемы с "styleable", как я уже писал здесь. Это также затрудняет поиск неиспользуемых ресурсов.

  2. Еще хуже способы: поместить ресурсы в папку assets, поместить файлы странным образом внутри файла jar, ...

Обратите внимание, что часть SDK включает пользовательские представления (например, классы, которые расширяются из TextView), поэтому даже если я разделю SDk на 2 модуля - ресурсы и файлы java, у обоих могут быть проблемы зависимостей (каждый использует другой).

Вопрос

Можно ли как-то решить этот вопрос?

Возможно ли, чтобы кодовая часть SDK оставалась закрытой, достигала файла "R", как обычно, и упрощала его как для меня, так и для тех, кто использует SDK ?

Как бы я тогда сгенерировал файл jar как являющийся запутался через Android Studio? и можно ли подготовить его для последующего использования через gradle?

Можно ли превратить Android-библиотеку SDK в запутанный jar-файл и не беспокоиться о файле "R"? Я спрашиваю об этом, потому что таким образом я мог бы наслаждаться обоими мирами: для наших приложений он оставался бы открытым, а для сторонних приложений-закрытым.


EDIT: видя, что это должно быть легко, я попробовал это сам. Я создал совершенно новый POC проект, который имеет модуль библиотеки Android под названием "sdkmodule", и добавил к нему этот класс:

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 в его макете), что и само приложение, но с другим значением, но когда я достиг этого действия, я увидел, что оно используется приложением.

Вот проект, заархивированный (не обращайте внимания на название проекта). Папка, я тоже хотел попробовать вкусы):

https://drive.google.com/file/d/0B-PZZGk2vPohX25WUDNKTmotUTg/view?usp=sharing
2 2

2 ответа:

ФорматAndroid Archive (AAR) делает то, что вы хотите. Он похож на jar-файл для Android и содержит скомпилированный код, но включает в себя собственные ресурсы и манифест. Вы также можете включить обфускацию в процесс сборки. По умолчанию текущая версия Android Studio (1.2 )и Gradle автоматически строятся.Файлы AAR для всех библиотечных модулей, созданных в проекте.

Вы можете превратить модуль приложения в библиотечный проект, который будет публиковать файл AAR просто путем изменение apply plugin: 'com.android.application' в apply plugin: 'com.android.library' в файле Gradle вашего модуля. То.Файл AAR будет помещен в вашу папку MODULENAME/build/outputs/aar после каждой сборки. Некотораядополнительная информация доступна здесь .

Правка 1, после обновления вопроса:

Ресурсы в вашем AAR консолидируются с модулем приложения, когда будет скомпилирован окончательный APK. Это, вероятно, сделано специально, чтобы люди, использующие стороннюю библиотеку, могли настраивать ее ресурсы при создании. их приложение, без необходимости перестраивать библиотеку. Я думаю, что самый простой способ решить проблему конфликта ресурсов - это просто назвать ваши ресурсы sdkmodule чем-то более уникальным. Почему бы не сделать строковый ключ R.string.com_example_sdk_name или что-то в этом роде?

Нет, библиотеки AAR не запутываются по умолчанию, но вы можете настроить ProGuard в файле сборки Gradle для вашей библиотеки AAR, чтобы позаботиться об этом. Другие инструменты также доступны.

Ответ на вашу проблему заключается в том, чтобы упаковать и распространить Вашу библиотеку в виде AAR bundle

Этот формат позволяет предоставить запутанный SDK jar с его ресурсами и файлом сопоставления R.

Этот формат является стандартным и полностью поддерживаетсяmaven-android-plugin (фактически это замена старого формата APKLib, который поддерживает только распространение исходных файлов).

Конечно, он также поддерживается Gradle и Android Studio.