2016-06-24 4 views
2

Я работаю над библиотекой, которая генерирует файл класса на основе аннотированных классов и полей во время компиляции (при ударе по сборке). Пока все прекрасно (класс может быть сгенерирован). Однако у меня возникла проблема с тем, как найти такой сгенерированный класс при запуске приложения (к классу необходимо получить доступ в методе onCreate для Application).Получить имя пакета приложения Android во время обработки аннотаций

код выглядит примерно так:

- Application class of an Android app - 
@Override 
public void onCreate() { 
    super.onCreate(); 
    MyLib.setup(this); 
} 

А внутри класса MyLib, что-то вроде этого нужно сделать:

public void setup(Application app) { 
    String className = String.format("%s.%s", "packageName", "generatedClassName"); 
    Class<?> myGeneratedClass = Class.forName(className); 
    ... 
} 

Проблема заключается в том, я не знаю, как найти класс, не зная его имя пакета, а также не знает, как найти его имя пакета.

Я мог бы подумать, как это сделать, это передать имя пакета в одну из аннотаций типа @MyAnnotation («имя_пакета»), чтобы использовать ее при создании класса во время компиляции и получении этого класса во время выполнения.

Однако мне просто интересно, есть ли другие более чистые способы достижения этого. Есть ли какой-либо способ: 1. Получить имя пакета приложения во время обработки аннотации 2. Ищите класс во время выполнения, не зная его пакета (знаете только пакет приложений). Я попробовал Package.getPackages() в пределах MyLib.setup(). Однако это возвращает пустой массив.

ответ

3

Это хорошо изученная проблема. Самый простой подход заключается в том, чтобы ваши пользователи аннотировали пакет приложений (да, annotating a package is possible) или передали имя пакета приложений через javac parameter (у Android-приложений и новых версий плагина Android Gradle есть встроенная поддержка для них). Это дешево, и вы быстро пойдете.

Получение наименования пакета эвристически возможно, и для AndroidAnnotations есть кусок кода для этого (точнее, для finding AndroidManifest.xml и locating R.java), оба из которых могут выдавать пакет приложений. Остерегайтесь, эти методы не очень хороши. Обратите внимание, что в AndroidAnnotations имеется система плагинов, поэтому вы можете получить доступ к этой функции, не выполняя свою работу, написав плагин и заявив о зависимости от своего основного процессора.

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

+0

Большое спасибо за ваш ответ. Очень информативно. Я рад узнать, что у AndroidAnnotations есть эти методы. Я нашел вариант плагина очень интересным. Не могли бы вы дать немного больше информации об этом? благодаря –

0

класс Override Application

private static Context sContext; 

    @Override 
     protected void attachBaseContext(Context base) { 
     super.attachBaseContext(base); 
     sContext = base; 
    } 

    public static Context getAppContext() { 
     return sContext; 
    } 

Чтобы получить имя пакета

YourApplication.getAppContext().getPackageName(); 

Отредактировано: Чтобы получить имя пакета аннотированных элемента в классе простиралась от AbstractProcessor вы можете использовать этот

final String originalPackageName = element.getEnclosingElement().toString(); 

где el ement is TypeElement instance

+0

Я знаю, как это сделать, но, как я уже упоминал в вопросе, мне нужно получить имя пакета во время компиляции, что означает, что он должен быть доступен из обработчика аннотаций (т. Е. В рамках 'public boolean process (Установите аннотации, RoundEnvironment roundEnv) 'function.Но спасибо anw –

+0

Добавлено. Надеюсь, это поможет – thealeksandr

+0

Да, это может быть достигнуто, если я аннотирую класс Application и использую его для получения пакета. В моем случае я использовал аннотации для другого класса, и я не хотел добавлять еще одну аннотацию для класса Application только для того, чтобы получить свой пакет во время компиляции, потому что для этого требуется дополнительный шаг, который пользователь должен сделать, чтобы использовать библиотеку, которую я письмо. Я не уверен, что можно сделать это, не делая того, что вы упомянули, и того, что я упомянул в вопросе. Но все еще хочу искать другое решение, прежде чем я решит взять любой из этих двух вариантов. –