Android - наличие полномочий поставщика в проекте приложения
Проект библиотеки андроида содержит несколько поставщиков, полномочия которых определены в классе контрактов:
public static final String CONTENT_AUTHORITY = "my.com.library.providers.tester";
private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
Теперь есть много проектов приложений, которые используют этот проект библиотеки. Проблема, с которой я в настоящее время сталкиваюсь, заключается в том, что для каждого проекта приложения мне нужно иметь отдельный филиал в проекте библиотеки для каждого приложения только для того, чтобы иметь уникальный контент. Это создает некоторые проблемы с управлением версиями (например, распространение признаков/исправлений ошибок из одной ветки на каждую другую ветку и т.д.). Вместо этого я хотел бы делегировать ответственность за определение полномочий контента для проекта приложения. Есть ли способ сделать это?
Ответы
Ответ 1
Приложение - это единственное, что абсолютно необходимо знать о полномочиях, поскольку оно объявляет <provider>
в манифесте с атрибутом android:authorities
.
Следовательно, в принципе, он должен "просто работать", пока вы удаляете из поставщика всю специфичную для авторизации логику, например:
- те статические члены данных (которые теперь переходят к хостинговому приложению)
-
UriMatcher
(сканируйте что-то самостоятельно, не проверяя полномочия, но фокусируясь на остальной части Uri
)
Если по какой-то причине вы абсолютно уверены, что ваш провайдер должен знать свои полномочия, приложение должно будет предоставить это провайдеру до того, как поставщик будет использован для реальной работы. Возможные способы сделать это:
-
Так как a ContentProvider
является естественным одноэлементным, назначьте его статическому члену данных, а затем предоставите ему строку полномочий с помощью настраиваемого метода из пользовательского класса Application
(поскольку поставщики сначала инициализируются, поэтому это должно работать)
-
Если вы поддерживаете только API уровня 11+, используйте Application
класс call()
call()
для
для предоставления полномочий ContentProvider
-
Предположим, что единственные реальные вызовы (например, query()
, insert()
) действительны и просто лениво инициализируют вашу власть на основе того, что входит в первую Uri
, которую вы видите
Ответ 2
Я знаю, что это старая тема, но сегодня столкнулась с этой проблемой, и мы развиваемся довольно долго, поэтому не были готовы пройти все статики в Контракте поставщика контента и изменить их, также потому, что наш поставщик контента и БД генерируются Механоидный плагин для Eclipse (Да, я тоже автор!:))
Решение, с которым я столкнулся, состояло в том, чтобы добавить статический инициализатор в наш сгенерированный контракт, который использует отражение для поиска класса и использует статическое поле CONTENT_AUTHORITY, если оно существует, если оно не возвращается к умолчанию:
public class QuxContract {
public static final String CONTENT_AUTHORITY = initAuthority();
private static String initAuthority() {
String authority = "com.example.app.data.qux";
try {
ClassLoader loader = QuxContract.class.getClassLoader();
Class<?> clz = loader.loadClass("com.example.app.data.QuxContentProviderAuthority");
Field declaredField = clz.getDeclaredField("CONTENT_AUTHORITY");
authority = declaredField.get(null).toString();
} catch (ClassNotFoundException e) {}
catch (NoSuchFieldException e) {}
catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
return authority;
}
private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
// ...
Теперь в каждом проекте, который ссылается на проект библиотеки, могут быть предоставлены собственные полномочия:
package com.example.app.data;
public class QuxContentProviderAuthority {
public static final String CONTENT_AUTHORITY = "com.example.app.data.baz";
}
Кроме того, не забудьте также изменить полномочия в манифесте