В нескольких приложениях используется один и тот же контент-провайдер

Я разрабатываю набор приложений, которые отличаются только определенным брендингом (думаю, разные спортивные команды); однако я столкнулся с проблемой, когда я использую один проект библиотеки для всех специально заклейменных приложений и хочу использовать один и тот же ContentProvider для всех из них. Когда я создал ContentProvider, я объявил AUTHORITY как константу в classе (на пример кода примера), и я использую тот же самый авторитет в каждом конкретном приложении в файлах манифеста. Похоже, я не могу использовать один и тот же авторитет для каждого приложения, поскольку получаю эту ошибку при попытке установить второе приложение (я устанавливаю один брендированный только отлично, а второй устанавливаю):

WARN/PackageManager(66): Can't install because provider name com.xxx.Provider (in package com.xxx) is already used by com.zzz 

Я пробовал несколько подходов, но никто из них, похоже, не работает. Одна из идей, которую я еще не сделал, заключалась в создании библиотеки jar и просто опускании classа Provider, который у меня есть, и его настройке в каждом конкретном приложении. Любые идеи о том, как обойти эту проблему, не прибегая к этому?

ContentProviders идентифицируются авторитетом, поэтому он должен быть уникальным. Я не думаю, что в этом есть какие-то трюки.

Кроме того, в платформе Android есть ошибка, которая также предотвращает использование одного и того же имени classа для двух разных ContentProviders, даже если они имеют разные полномочия и содержатся в отдельных APK. См. Здесь ошибку.

Решение, которое я вам советую, заключается в создании абстрактного classа поставщика в проекте библиотеки, а затем его расширении с уникальным именем в каждом из отдельных приложений. Для этого вам, вероятно, понадобится создать скрипт для создания / изменения отдельных манифестатов и classов contentprovider.

Надеюсь это поможет.

Это старый вопрос, но я недавно искал что-то подобное. С ароматами Build, это действительно прямо сейчас.

Укажите BuildConfigField в файле gradle:

  productFlavors { free { applicationId "com.example.free" buildConfigField 'String', 'AUTHORITY', '"com.example.free.contentprovider"' } paid { applicationId "com.example.paid" buildConfigField 'String', 'AUTHORITY', '"com.example.paid.contentprovider"' } 

Укажите полномочия поставщика в манифесте:

   

Установите полномочия поставщика, используя переменную BuildConfigField:

  public static final String AUTHORITY = BuildConfig.AUTHORITY 

Допустим, ваш пакет для библиотеки – com.android.app.library бесплатный пакет com.android.app.free заплаченный пакет com.android.app.paid

В своем бесплатном проекте и оплачиваемом проекте создайте идентичный файл в пакете, который может быть чем угодно, но должен быть тем же.

Пример:

  1. Создайте новый пакет в своей бесплатной версии с помощью com.android.app.data

  2. Создайте файл с именем Authority.java и внутри (Authority.java):

    public class Authority {

     `public static final String CONTENT_AUTHORITY = "YOUR PROVIDER";` 

    }

  3. Повторите это для платной версии, не забудьте сохранить имя пакета одинаковым и имя classа.

Теперь в вашем файле контракта в вашей библиотеке используйте следующее:

 public static String AUTHORITY = initAuthority(); private static String initAuthority() { String authority = "something.went.wrong.if.this.is.used"; try { ClassLoader loader = Contract.class.getClassLoader(); Class clz = loader.loadClass("com.android.app.data.Authority"); 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; } public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); 

Теперь вы должны иметь возможность использовать два органа.

Кредит: Ian Warick (напишите код) Android – Владелец провайдера в проекте приложения. Отказ от ответственности. Я также разместил его здесь: проблема с полномочиями провайдера дубликатов Android. Не уверен, разрешено ли отвечать на один и тот же вопрос с тем же ответом.

ТЫ МОЖЕШЬ!

Как сказано в этом сообщении (объясняет, как Firebase инициализирует свою библиотеку, не предоставляя ей контекст из вашего метода Application#onCreate() ), вы можете использовать placeholder в своем манифесте, например:

   

Следующий способ можно использовать для пакета ContentProvider в библиотеке и установить полномочия ContentProvider во время выполнения, чтобы он мог быть включен в несколько проектов без конфликта ContentProvider. Это работает, потому что реальный «авторитет» происходит от AndroidManifest … не classа ContentProvider.

Начните с основной реализации ContentProvider. НАРУШЕНИЯ, CONTENT_URI и UriMatcher являются статическими, но не «окончательными» ….

 public class MyContentProvider extends ContentProvider { public static String AUTHORITY = "com.foo.bar.content"; public static Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); protected static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 

Затем переопределите метод attachInfo, так что, когда ContentProvider сначала инициализируется, ваш ContentProvider будет вызываться с помощью ProviderInfo, который почерпнут из AndroidManifest. Это произойдет до того, как будут сделаны любые возможные запросы, скорее всего, во время начальной настройки classа приложения. Используйте эту возможность, чтобы сбросить значения AUTHORITY, CONTENT_URI и UriMatcher на их «реальные» значения, как это предусмотрено приложением, использующим библиотеку ContentProvider.

  @Override public void attachInfo(Context context, ProviderInfo info) { super.attachInfo(context, info); AUTHORITY = info.authority; CONTENT_URI = Uri.parse("content://" + AUTHORITY); uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(AUTHORITY, AlarmTable.TABLENAME, ALARMS); uriMatcher.addURI(AUTHORITY, AttributeTable.TABLENAME, ATTRIBUTES); uriMatcher.addURI(AUTHORITY, DeepLinkTable.TABLENAME, DEEPLINKS); uriMatcher.addURI(AUTHORITY, NotificationTable.TABLENAME, NOTIFICATIONS); uriMatcher.addURI(AUTHORITY, MetaDataTable.TABLENAME, RESOURCE_METADATA); uriMatcher.addURI(AUTHORITY, ResourceTable.TABLENAME, RESOURCES); uriMatcher.addURI(AUTHORITY, ResourceAttributeTable.TABLENAME, RESOURCES_ATTRIBUTES); uriMatcher.addURI(AUTHORITY, ResourceTagTable.TABLENAME, RESOURCES_TAGS); uriMatcher.addURI(AUTHORITY, TagTable.TABLENAME, TAGS); uriMatcher.addURI(AUTHORITY, UserTagTable.TABLENAME, USER_TAGS); uriMatcher.addURI(AUTHORITY, UserTable.TABLENAME, USERS); uriMatcher.addURI(AUTHORITY, CUSTOM, RAW); } 

Когда приложение запускается, ContentProvider фактически создается вместе с classом Application, поэтому он будет иметь доступ ко всей необходимой информации о пакете. объект ProviderInfo будет содержать информацию, представленную в AndroidManifest … Список, включенный в окончательное приложение.

   

Теперь администратор будет переписан с «com.foo.barapp.content» вместо значения по умолчанию, а UriMatcher будет обновлен до значения приложения, а не по умолчанию. Классы, которые полагаются на «AUTHORITY», теперь будут получать доступ к обновленному значению, а UriMatcher будет правильно различать входящие запросы для «com.foo.barapp.content».

Я тестировал это как с примерным приложением, так и с пакетом androidTest одновременно и нашел, что он работает правильно.

Interesting Posts

Адаптер пейджера не отображает изображение после получения ответа от fragmentа

Как установить шрифт из командной строки Windows?

Поиск инструмента для отображения IP-пакетов (и проведения анализа), отправленных / полученных с / на мой компьютер (хотите отладить, почему не удается подключить сетевой диск)

Geo Fencing – точка внутри / снаружи многоугольника

Как отключить предупреждения о неиспользуемом коде в Rust?

Более одного «Открыть xxxxx здесь как администратор»

Сжатие pdf, созданное офисом 2007

В чем разница между Application.Run () и Form.ShowDialog ()?

прослушиватель событий события на стилизованных значках и ярлыках карты

Как вы воссоздаете среду восстановления системы в Windows 7?

Почему я получаю UnsupportedOperationException при попытке удалить элемент из списка?

Каковы преимущества и недостатки использования сети доставки контента (CDN)?

Угловой 2 маршрутизатор разрешен с наблюдаемым

Почему мои жесткие диски не работают?

Найти точку пересечения двух векторов в MATLAB

Давайте будем гением компьютера.