Перейти к содержанию

Произвольные данные обновляются в ContentProvider

Описание

Если необходимо получить доступ к данным ContentProvider, используется объект ContentResolver. Он взаимодействует с объектом-поставщиком — экземпляром класса, который реализует ContentProvider. Объект ContentProvider получает запросы данных от клиентов, выполняет запрошенное действие и возвращает результаты. Методы ContentResolver предоставляют базовые функции «CRUD» (create, retrieve, update и delete) хранилища. Activity или Fragment вызывает CursorLoader для запроса, который, в свою очередь, получает ContentProvider с помощью ContentResolver.

// Запрашивает пользовательский словарик (UserDictionary) и возвращает результаты
cursor = contentResolver.query(
    UserDictionary.Words.CONTENT_URI,  // URI таблицы со словами
    projection,                        // Столбцы, которые вернутся для каждой строки
    selectionClause,                   // Selection условия
    selectionArgs.toTypedArray(),      // Selection параметры
    sortOrder                          // Порядок сортировки
)

Чтобы обновить строку, используется объект ContentValues с обновленными значениями, как при вставке, и критерии выбора, как при запросе. Для обновления используется метод ContentResolver.update(). Необходимо только добавить значения в объект ContentValues ​​для столбцов, которые необходимо обновить. Для удаления содержимого столбца, устанавливается значение null.

Следующий фрагмент изменяет все строки, языковой стандарт которых «en», на языковой стандарт null. Возвращаемое значение — это количество обновленных строк.

// Объект, содержащий обновлённые данные
ContentValues updateValues = new ContentValues();

// Критерии выборки для строк, которые необходимо обновить
String selectionClause = UserDictionary.Words.LOCALE +  " LIKE ?";
String[] selectionArgs = {"en_%"};

// Переменная, которая содержит число обновлённых строк
int rowsUpdated = 0;
...
/*
 * Определяем новые значения
 */
updateValues.putNull(UserDictionary.Words.LOCALE);

rowsUpdated = getContentResolver().update(
    UserDictionary.Words.CONTENT_URI,  // UserDictionary content URI
    updateValues,                      // Столбцы для обновления
    selectionClause,                   // Столбцы, которые выбраны для обновления
    selectionArgs                      // Значения столбцов для выборки
);

Обновление произвольных данных в ContentProvider может привести к серьезным проблемам с безопасностью или неожиданному поведению программы.

Рекомендации

  1. Остерегайтесь SQL-инъекций. Если данные, управляемые ContentProvider, находятся в базе данных SQL, включение внешних ненадежных данных в необработанные операторы SQL может привести к SQL-инъекциям. Рекомендации как избежать SQL-инъекций читай здесь.

  2. Защищайте Content Provider, если необходимо, чтобы провайдер был экспортируемым. Ограничивайте доступ к Content Provider с помощью атрибутов android:permission, android:readPermission или android:writePermission, или предоставляйте доступ только к конкретным uri с помощью <grant-uri-permission …/>, либо <path-permission.….

  3. Если у Content Provider есть атрибуты android:readPermission и android:writePermission одновременно, то не рекомендуется использовать одно и то же разрешение, чтобы, например, приложения, которым необходимо только чтение, не получали дополнительную возможность на запись и наоборот.

  4. Валидируйте данные, которые приходят в ContentValues в методе update().

    Пример

    @Override
    public int update (Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        String name = values.getAsString(PatientEntry.COLUMN_PATIENT_NAME);
        if (name != null && name.length()==0) {
            throw new IllegalArgumentException("Patient name is too short");
        }
    ...
    }
    

Ссылки

  1. ContentProvider basics
К началу