Android — наличие полномочий провайдера в проекте приложения

Проект библиотеки Android содержит несколько провайдеров, полномочия которых определяются следующим образом в классе контракта:

public static final String CONTENT_AUTHORITY = "my.com.library.providers.tester";
private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);

Сейчас есть много проектов приложений, которые используют этот проект библиотеки. Проблема, с которой я сталкиваюсь в настоящее время, заключается в том, что для каждого проекта приложения мне нужно иметь отдельную ветку в проекте библиотеки для каждого приложения только для того, чтобы иметь уникальный авторитет контента. Это создает некоторые проблемы с управлением версиями (например, распространение функций/исправлений ошибок из одной ветки в каждую другую ветку и т. д.). Вместо этого я хотел бы делегировать ответственность за определение прав доступа к контенту проекту приложения. Есть ли способ сделать это?


person 500865    schedule 28.05.2012    source источник
comment
Это может быть дубликат stackoverflow.com/ вопросов/10320689/, но пока никто не ответил.   -  person 500865    schedule 29.05.2012


Ответы (2)


Приложение — единственное, которому абсолютно необходимо знать о полномочиях, поскольку именно оно объявляет <provider> в манифесте с атрибутом android:authorities.

Следовательно, в принципе, это должно «просто работать», пока вы удаляете из провайдера всю логику, относящуюся к полномочиям, например:

  • те статические данные-члены (которые теперь перемещаются в хостинг-приложение)
  • UriMatcher (накатить что-нибудь самому, что не исследует авторитет, а ориентируется на остальные Uri)

Если по какой-то причине вы абсолютно уверены, что ваш провайдер должен знать свои полномочия, то приложение должно будет предоставить это провайдеру, прежде чем провайдер будет использоваться для реальной работы. Среди возможных способов сделать это:

  • Поскольку ContentProvider является естественным синглтоном, назначьте его статическому элементу данных, а затем передайте ему строку полномочий с помощью пользовательского метода из пользовательского класса Application (поскольку провайдеры инициализируются первыми, поэтому это должно работать)

  • Если вы поддерживаете только API уровня 11+, пусть пользовательский класс Application использует call() на ContentResolver для предоставления полномочий ContentProvider

  • Предположим, что единственные реальные вызовы (например, query(), insert()) являются действительными, и просто лениво инициализируйте свои полномочия на основе того, что приходит с первым Uri, который вы видите.

person CommonsWare    schedule 28.05.2012
comment
Я почти закончил отвечать на вопрос ... затем я увидел, что появился 1 новый ответ, и, конечно же, это был CommonsWare, чей ответ охватывал все, что я упомянул, и многое другое. Просто мне повезло... :P - person Alex Lockwood; 29.05.2012
comment
@AlexLockwood: извините за это. Если вам от этого станет легче, то и со мной тоже. Кроме того, не бойтесь просто опубликовать свой ответ, когда такое произойдет. Вполне возможно, что ваша формулировка или что-то в этом роде найдет отклик у спрашивающего лучше, чем существующий ответ. Кроме того, если вы приложили все усилия, чтобы ввести (большую часть) ответа, вы также можете опубликовать его. - person CommonsWare; 29.05.2012
comment
Я понял идею. Я думал об изменении кода во время компиляции. Разве это не возможность? Если это возможно, это будет легко и, вероятно, проще, чем этот подход. - person 500865; 29.05.2012
comment
@ 500865: Разве это не возможно? -- гм, не сразу, если только вы не собираетесь запускать свою собственную задачу Ant или что-то еще, что создает копию библиотеки, настраивает источник, настраивает project.properties хостингового приложения так, чтобы оно указывало на копию, и т. д. Если это возможно, это было бы легко и, вероятно, проще, чем этот подход. -- Я думаю, что модификация кода во время компиляции будет на несколько порядков сложнее. В конце концов, ленивый поиск вашего Uri на основе первого вызова query() и т. д. должен занимать менее 10 строк кода. - person CommonsWare; 29.05.2012
comment
@CommonsWare: Спасибо, что уделили этому время. - person 500865; 29.05.2012
comment
Я решил это с помощью абстрактного метода в классе приложения «getAuthority()» в проекте библиотеки. Затем его можно реализовать в 2 разных проектах приложений с 2 ​​разными полномочиями. Но позже я разработал более сложный подход — третье приложение исключительно для размещения поставщика контента, который теперь используется совместно между клиентскими приложениями. - person WindRider; 07.02.2014
comment
Интересно, что URIвы бы использовали в call() на ContentResolver, чтобы предоставить полномочия ContentProvider. - person Draško Kokić; 05.05.2014
comment
@DraškoKokić: content://your.authority.goes.here должно работать. При желании добавьте другие сегменты, хотя, поскольку call() не передается Uri, эти сегменты не будут так полезны. - person CommonsWare; 05.05.2014
comment
@CommonsWare: Вы бы предоставили new полномочия в URI или в качестве дополнительного аргумента? Что меня смущает, так это то, что для вызова call на ContentResolver нужно знать полномочия (CP, зарегистрированный в Android), поэтому я не могу понять, как это можно использовать для настройки послесловий полномочий. - person Draško Kokić; 08.05.2014
comment
@DraškoKokić: Вы не можете изменить полномочия ContentProvider во время выполнения. Мои извинения, если я неправильно понял ваш первоначальный комментарий в этой цепочке комментариев. - person CommonsWare; 08.05.2014
comment
Ни одно из вышеупомянутых решений не сработало для меня: 1. Исправьте, что ContentProvider является одноэлементным, но что, если использовать ContentProvider в библиотеке с виджетом, теперь пользователь не откроет приложение, чтобы поместить виджет на экран, поэтому полномочия ContentProvider не будут инициализированы с помощью общедоступная статическая константа. 2. метод вызова ContentResolver, который я не могу использовать, как предложил @DraškoKokić: 3. Что, если я выполняю вызовы query() из самой библиотеки, а не из приложения, тогда в этом случае 3-е решение также не будет работать - person Sagar Trehan; 20.08.2015

Я знаю, что это старая тема, но сегодня столкнулся с этой проблемой, и мы разрабатывали ее в течение довольно долгого времени, поэтому не были готовы просмотреть всю статистику в нашем контракте с контент-провайдером и изменить их, в том числе потому, что наш контент-провайдер и БД генерируются плагин Mechanoid для 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";
}

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

person Ian Warwick    schedule 29.01.2013
comment
Близко к решению, которое я реализовал. Спасибо, что поделился!! - person 500865; 30.01.2013
comment
Спасибо, теперь я могу выпустить сегодня! - person Rich Ehmer; 22.08.2014
comment
@ Ян Уорвик На самом деле я новичок в Android, я работаю с Android Studio, у меня та же проблема с властями, не могли бы вы помочь мне с некоторыми примерами - person Manoj; 16.10.2014
comment
Это решение просто великолепно! Большое тебе спасибо! :D - person Mauker; 03.05.2016