Вызов небиблиотечного кода из библиотеки Android
С тех пор как Android представил библиотечные проекты, я конвертировал свое приложение в библиотеку, чтобы я мог сделать несколько версий с соответствующими настройками (например, бесплатная и профессиональная версия, использующая одну и ту же кодовую базу, но меняющая несколько вещей).
Изначально у меня были проблемы с разрешением доступа кода проекта библиотеки к полям в моих подпроектах. Другими словами, каждая из моих бесплатных и профессиональных версий имела класс с несколькими константами, которые библиотечный проект использовал бы для различения определенных функций.
В подпроекте я расширил основную деятельность библиотеки и добавил статический блок инициализации, который использует отражение для изменения значений полей в библиотеке.
public class MyMainActivityProVersion extends MyMainActivity {
public static final String TAG = Constants.APP_NAME + "/SubClass";
static {
try {
ConstantsHelper.setConstants(Constants.class);
} catch (Exception e) {
Log.d(TAG, "--- Constants not initialised! ---");
e.printStackTrace();
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
В этом коде ConstantsHelper находится в библиотеке, и я предоставляю Constants.class из моего подпроекта. Это инициализирует константы в проекте библиотеки.
Мой подход прекрасно работает, за исключением одного конкретного случая использования. Если приложение некоторое время не использовалось и оно "остановлено" операционной системой, статические поля в ConstantsHelper забываются.
Предполагается, что константы сбрасываются основным действием (как показано выше), но основное действие даже не запускается, потому что ОС возобновляет другое действие. Результатом этого является то, что инициализация констант забыта, и я не могу повторно инициализировать их, потому что возобновленная деятельность находится в библиотеке (которая не имеет сведений о подпроекте).
Как я могу "сказать" другим действиям в библиотеке вызывать код из подпроектов при возобновлении? В качестве альтернативы, есть ли способ гарантировать, что некоторый код в моем подпроекте вызывается при каждом резюме?
3 ответа
Боюсь, я так и не нашел хорошего ответа на этот вопрос. Я, вероятно, продолжу свое ужасное использование рефлексии и выясню какой-нибудь хакерский обходной путь.
Я чувствовал, что должен вернуться и, по крайней мере, указать, что я не решил эту проблему в пользу других, которые заходят на эту страницу.
Я думаю, что вы "обманываете", пытаясь обмениваться данными между двумя действиями через статических членов. Это работает, когда они находятся в одном или нескольких связанных загрузчиках классов. Здесь я считаю, что Android использует отдельные загрузчики классов для отдельных действий, но дочерние действия находятся в дочерних загрузчиках классов. Так ViewActivity
случается, что в состоянии видеть в родительском загрузчике классов и видеть статику для родителя. Позже я считаю, что родитель уходит, и поэтому ваш ребенок перезагружается MyMainActivity
локально, когда вы в следующий раз получите к нему доступ, и он не будет инициализирован так, как вы хотели. (Ну, если это не так, это что-то очень похожее на это объяснение.)
Я думаю, что есть более надежные альтернативы. Вы могли бы использовать LicenseChecker
API, чтобы решить, будете ли вы в бесплатной или платной версии, а не полагаться на детали жизненного цикла действия и загрузчика классов. Это, вероятно, будет лучше, так как защищает вас от других видов несанкционированного использования.
Вы можете решить эту проблему с помощью ресурсов Android. По сути, определите свои константы в файле значений XML-ресурсов в вашем проекте библиотеки.
Например, "lib project"\values \constants.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<bool name="const_free_version">false</bool>
<string name="const_a_constant">pippo</bool>
</resources>
Затем в вашем подпроекте вы можете переопределить значения lib-project, используя другой файл значений XML-ресурсов:
Например, "sub project"\values \constants.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<bool name="const_free_version">true</bool>
</resources>
В коде вашего проекта lib, когда вы ссылаетесь на R.bool.const_free_version, вы получаете фактическое значение, основанное на константных значениях подпроекта xml.
Обратите внимание, что вам не нужно переопределять все значения, определенные в проекте lib constants.xml, а только те, которые вам нужны, в вашем подпроекте.