Android — Content Providers (поставщики контента)


Компонент Content Providers (поставщика контента) по запросу передает данные из одного приложения в другие. Такие запросы обрабатываются методами класса ContentResolver. Поставщик контента может использовать разные способы хранения своих данных, и данные могут храниться в базе данных, в файлах или даже в сети.

поставщик услуг

Content Providers

иногда требуется совместное использование данных между приложениями. Здесь очень полезны поставщики контента.

Поставщики контента позволяют централизовать контент в одном месте и при необходимости получать к нему доступ множеству различных приложений. Провайдер контента ведет себя очень похоже на базу данных, где вы можете запрашивать его, редактировать его содержимое, а также добавлять или удалять контент с помощью методов insert (), update (), delete () и query (). В большинстве случаев эти данные хранятся в SQlite база данных.

Провайдер контента реализован как подкласс Поставщик услуг class и должен реализовывать стандартный набор API-интерфейсов, которые позволяют другим приложениям выполнять транзакции.

public class My Application extends  ContentProvider {
}

URI контента

Чтобы запросить поставщика контента, вы указываете строку запроса в форме URI, который имеет следующий формат:

<prefix>://<authority>/<data_type>/<id>

Вот подробности различных частей URI —

Деталь и описание
1prefix
Всегда установлено значение content: //
2authority
Здесь указывается имя поставщика содержимого, например контакты, браузер и т. д. Для сторонних поставщиков контента это может быть полное имя, например com.tutorialspoint.statusprovider
3data_type
Указывает на тип данных, которые предоставляет этот конкретный поставщик. Например, если вы получаете все контакты из Контакты контент-провайдер, то путь к данными будут люди и URI будет выглядеть так content: // контакты / люди
4id
Указывает идентификатор. Например, если вы ищете контактный номер 5 в поставщике контента «Контакты», то URI будет выглядеть так content: // контакты / люди / 5.

Создать Content Provider

Это включает в себя ряд простых шагов для создания собственного поставщика контента.

  • Прежде всего вам нужно создать класс Content Provider, который расширяет ContentProviderbaseclass.
  • Во-вторых, вам необходимо определить URI-адрес вашего контент-провайдера, который будет использоваться для доступа к контенту.
  • Затем вам нужно будет создать свою собственную базу данных для хранения содержимого. Обычно Android использует базу данных SQLite, и фреймворк должен переопределить onCreate () метод, который будет использовать метод SQLite Open Helper для создания или открытия базы данных поставщика. Когда ваше приложение запущено, onCreate () обработчик каждого из его Content Provider вызывается в основном потоке приложения.
  • Затем вам нужно будет реализовать запросы Content Provider для выполнения различных операций с базой данных.
  • Наконец, зарегистрируйте своего поставщика контента в файле активности с помощью тега .

Вот список методов, которые вам нужно переопределить в классе Content Provider, чтобы ваш Content Provider работал:

поставщик услуг

Поставщик услуг

  • onCreate () — этот метод вызывается при запуске провайдера.
  • query() — этот метод получает запрос от клиента. Результат возвращается как объект Cursor.
  • insert() — этот метод вставляет новую запись в поставщик содержимого.
  • delete() — этот метод удаляет существующую запись из поставщика содержимого.
  • update() — этот метод обновляет существующую запись от поставщика содержимого.
  • getType() — этот метод возвращает MIME-тип данных по заданному URI.

Пример

Этот пример объяснит вам, как создать свой собственный ContentProvider. Итак, давайте выполним следующие шаги, аналогичные тем, которые мы следовали при создании Привет, мир, пример

ШагОписание
1Вы будете использовать Android StudioIDE для создания Android-приложения и назовете его как Мое приложение под пакет com.example.MyApplicationс пустым значением Activity.
2Изменить основной файл активности MainActivity.java добавить два новых метода onClickAddName () и onClickRetrieveStudents ().
3Создайте новый файл java с именем СтудентыProvider.java под пакет com.example.MyApplication для определения вашего фактического поставщика и связанных с ним методов.
4Зарегистрируйте своего контент-провайдера в своем AndroidManifest.xml файл с использованием тега
5Измените содержимое по умолчанию res / layout / activity_main.xml файл, чтобы включить небольшой графический интерфейс для добавления записей студентов.
6Не нужно менять string.xml. Студия Android позаботится о файле string.xml.
7Запустите приложение, чтобы запустить эмулятор Android и проверить результат изменений, внесенных в приложение.

Ниже приводится содержание измененного файла MainActivity
src / com.example.MyApplication / MainActivity.java.
Этот файл может включать каждый из основных методов жизненного цикла. Мы добавили два новых метода onClickAddName () и onClickRetrieveStudents () для обработки взаимодействия пользователя с приложением.

package com.example.MyApplication;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;

import android.content.ContentValues;
import android.content.CursorLoader;

import android.database.Cursor;

import android.view.Menu;
import android.view.View;

import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
   }
   public void onClickAddName(View view) {
      // Add a new student record
      ContentValues values = new ContentValues();
      values.put(StudentsProvider.NAME,
         ((EditText)findViewById(R.id.editText2)).getText().toString());

      values.put(StudentsProvider.GRADE,
         ((EditText)findViewById(R.id.editText3)).getText().toString());

      Uri uri = getContentResolver().insert(
         StudentsProvider.CONTENT_URI, values);

      Toast.makeText(getBaseContext(),
         uri.toString(), Toast.LENGTH_LONG).show();
   }
   public void onClickRetrieveStudents(View view) {
      // Retrieve student records
      String URL = "content://com.example.MyApplication.StudentsProvider";

      Uri students = Uri.parse(URL);
      Cursor c = managedQuery(students, null, null, null, "name");

      if (c.moveToFirst()) {
         do{
            Toast.makeText(this,
               c.getString(c.getColumnIndex(StudentsProvider._ID)) +
                  ", " +  c.getString(c.getColumnIndex( StudentsProvider.NAME)) +
                     ", " + c.getString(c.getColumnIndex( StudentsProvider.GRADE)),
            Toast.LENGTH_SHORT).show();
         } while (c.moveToNext());
      }
   }
}

Создайте новый файл StudentsProvider.java в com.example.MyApplication пакет, а далее — содержимое src / com.example.MyApplication / StudentsProvider.java

package com.example.MyApplication;

import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;

import android.database.Cursor;
import android.database.SQLException;

import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;

import android.net.Uri;
import android.text.TextUtils;

public class StudentsProvider extends ContentProvider {
   static final String PROVIDER_NAME = "com.example.MyApplication.StudentsProvider";
   static final String URL = "content://" + PROVIDER_NAME + "/students";
   static final Uri CONTENT_URI = Uri.parse(URL);

   static final String _ID = "_id";
   static final String NAME = "name";
   static final String GRADE = "grade";

   private static HashMap<String, String> STUDENTS_PROJECTION_MAP;

   static final int STUDENTS = 1;
   static final int STUDENT_ID = 2;

   static final UriMatcher uriMatcher;
   static{
      uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
      uriMatcher.addURI(PROVIDER_NAME, "students", STUDENTS);
      uriMatcher.addURI(PROVIDER_NAME, "students/#", STUDENT_ID);
   }

   /**
      * Объявления констант для конкретной базы данных
   */
   
   private SQLiteDatabase db;
   static final String DATABASE_NAME = "College";
   static final String STUDENTS_TABLE_NAME = "students";
   static final int DATABASE_VERSION = 1;
   static final String CREATE_DB_TABLE =
      " CREATE TABLE " + STUDENTS_TABLE_NAME +
         " (_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
         " name TEXT NOT NULL, " +
         " grade TEXT NOT NULL);";

   /**
      * Класс-помощник, который фактически создает и управляет
      * базовым репозиторием данных провайдера.
   */
   
   private static class DatabaseHelper extends SQLiteOpenHelper {
      DatabaseHelper(Context context){
         super(context, DATABASE_NAME, null, DATABASE_VERSION);
      }

      @Override
      public void onCreate(SQLiteDatabase db) {
         db.execSQL(CREATE_DB_TABLE);
      }

      @Override
      public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
         db.execSQL("DROP TABLE IF EXISTS " +  STUDENTS_TABLE_NAME);
         onCreate(db);
      }
   }

   @Override
   public boolean onCreate() {
      Context context = getContext();
      DatabaseHelper dbHelper = new DatabaseHelper(context);

      /**
         * Создайте базу данных с возможностью записи, которая
         * запустит ее создание, если она еще не существует.
      */
         
      db = dbHelper.getWritableDatabase();
      return (db == null)? false:true;
   }

   @Override
   public Uri insert(Uri uri, ContentValues values) {
      /**
         * Добавить новую студенческую запись
      */
      long rowID = db.insert(	STUDENTS_TABLE_NAME, "", values);

      /**
         * Если запись добавлена успешно
      */
      if (rowID > 0) {
         Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
         getContext().getContentResolver().notifyChange(_uri, null);
         return _uri;
      }
        
      throw new SQLException("Failed to add a record into " + uri);
   }

   @Override
   public Cursor query(Uri uri, String[] projection, 
      String selection,String[] selectionArgs, String sortOrder) {
      SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
      qb.setTables(STUDENTS_TABLE_NAME);

      switch (uriMatcher.match(uri)) {
         case STUDENTS:
            qb.setProjectionMap(STUDENTS_PROJECTION_MAP);
         break;

         case STUDENT_ID:
            qb.appendWhere( _ID + "=" + uri.getPathSegments().get(1));
         break;
         
         default:   
      }

      if (sortOrder == null || sortOrder == ""){
         /**
            * По умолчанию сортировка по именам студентов
         */
         sortOrder = NAME;
      }
      
      Cursor c = qb.query(db,	projection,	selection, 
         selectionArgs,null, null, sortOrder);
      /**
         * зарегистрироваться, чтобы следить за URI контента на предмет изменений
      */
      c.setNotificationUri(getContext().getContentResolver(), uri);
      return c;
   }

   @Override
   public int delete(Uri uri, String selection, String[] selectionArgs) {
      int count = 0;
      switch (uriMatcher.match(uri)){
         case STUDENTS:
            count = db.delete(STUDENTS_TABLE_NAME, selection, selectionArgs);
         break;

         case STUDENT_ID:
            String id = uri.getPathSegments().get(1);
            count = db.delete( STUDENTS_TABLE_NAME, _ID +  " = " + id +
               (!TextUtils.isEmpty(selection) ? " 
               AND (" + selection + ')' : ""), selectionArgs);
            break;
         default:
            throw new IllegalArgumentException("Unknown URI " + uri);
      }

      getContext().getContentResolver().notifyChange(uri, null);
      return count;
   }

   @Override
   public int update(Uri uri, ContentValues values, 
      String selection, String[] selectionArgs) {
      int count = 0;
      switch (uriMatcher.match(uri)) {
         case STUDENTS:
            count = db.update(STUDENTS_TABLE_NAME, values, selection, selectionArgs);
         break;

         case STUDENT_ID:
            count = db.update(STUDENTS_TABLE_NAME, values, 
               _ID + " = " + uri.getPathSegments().get(1) +
               (!TextUtils.isEmpty(selection) ? " 
               AND (" +selection + ')' : ""), selectionArgs);
            break;
         default:
            throw new IllegalArgumentException("Unknown URI " + uri );
      }
        
      getContext().getContentResolver().notifyChange(uri, null);
      return count;
   }

   @Override
   public String getType(Uri uri) {
      switch (uriMatcher.match(uri)){
         /**
            * Получить все студенческие записи
         */
         case STUDENTS:
            return "vnd.android.cursor.dir/vnd.example.students";
         /**
            * Найдите конкретный ученик
         */
         case STUDENT_ID:
            return "vnd.android.cursor.item/vnd.example.students";
         default:
            throw new IllegalArgumentException("Unsupported URI: " + uri);
      }
   }
}

Ниже будет измененное содержание AndroidManifest.xml файл. Здесь мы добавили тег , чтобы включить нашего поставщика контента:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.MyApplication">

   <application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:supportsRtl="true"
      android:theme="@style/AppTheme">
         <activity android:name=".MainActivity">
            <intent-filter>
               <action android:name="android.intent.action.MAIN" />
               <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
         </activity>
        
      <provider android:name="StudentsProvider"
         android:authorities="com.example.MyApplication.StudentsProvider"/>
   </application>
</manifest>

Ниже будет содержание res / layout / activity_main.xml файл

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context="com.example.MyApplication.MainActivity">

   <TextView
      android:id="@+id/textView1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Content provider"
      android:layout_alignParentTop="true"
      android:layout_centerHorizontal="true"
      android:textSize="30dp" />

   <TextView
      android:id="@+id/textView2"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Tutorials point "
      android:textColor="#ff87ff09"
      android:textSize="30dp"
      android:layout_below="@+id/textView1"
      android:layout_centerHorizontal="true" />

   <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/imageButton"
      android:src="https://www.tutorialspoint.com/android/@drawable/abc"
      android:layout_below="@+id/textView2"
      android:layout_centerHorizontal="true" />

   <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/button2"
      android:text="Add Name"
      android:layout_below="@+id/editText3"
      android:layout_alignRight="@+id/textView2"
      android:layout_alignEnd="@+id/textView2"
      android:layout_alignLeft="@+id/textView2"
      android:layout_alignStart="@+id/textView2"
      android:onClick="onClickAddName"/>

   <EditText
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/editText"
      android:layout_below="@+id/imageButton"
      android:layout_alignRight="@+id/imageButton"
      android:layout_alignEnd="@+id/imageButton" />

   <EditText
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/editText2"
      android:layout_alignTop="@+id/editText"
      android:layout_alignLeft="@+id/textView1"
      android:layout_alignStart="@+id/textView1"
      android:layout_alignRight="@+id/textView1"
      android:layout_alignEnd="@+id/textView1"
      android:hint="Name"
      android:textColorHint="@android:color/holo_blue_light" />

   <EditText
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/editText3"
      android:layout_below="@+id/editText"
      android:layout_alignLeft="@+id/editText2"
      android:layout_alignStart="@+id/editText2"
      android:layout_alignRight="@+id/editText2"
      android:layout_alignEnd="@+id/editText2"
      android:hint="Grade"
      android:textColorHint="@android:color/holo_blue_bright" />

   <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Retrive student"
      android:id="@+id/button"
      android:layout_below="@+id/button2"
      android:layout_alignRight="@+id/editText3"
      android:layout_alignEnd="@+id/editText3"
      android:layout_alignLeft="@+id/button2"
      android:layout_alignStart="@+id/button2"
      android:onClick="onClickRetrieveStudents"/>
</RelativeLayout>

Убедитесь, что у вас есть следующее содержание res / values ​​/ strings.xml файл:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">My Application</string>
</resources>;

Попробуем запустить наш модифицированный My Application приложение, которое мы только что создали. Я полагаю, вы создали свой AVD при настройке среды. Чтобы запустить приложение из Android Studio IDE, откройте один из файлов активности вашего проекта и нажмите «Выполнить». Значок запуска Android Studio значок на панели инструментов. Android Studio устанавливает приложение на ваш AVD и запускает его, и если все в порядке с вашей настройкой и приложением, оно отобразит следующее окно эмулятора, проявите терпение, потому что это может занять некоторое время в зависимости от скорости вашего компьютера —

Демонстрация поставщика содержимого Android

А теперь войдем в студентку Имя и Оценка и, наконец, нажмите на Добавить имя Кнопка, это добавит студенческую запись в базу данных и высветит сообщение внизу, показывающее ContentProvider URI вместе с номером записи, добавленной в базу данных. В этой операции используются наши insert() метод. Давайте повторим этот процесс, чтобы добавить еще несколько студентов в базу данных нашего контент-провайдера.

Добавить записи с помощью ContentProvider

После того, как вы закончили добавление записей в базу данных, пришло время попросить ContentProvider вернуть нам эти записи, поэтому давайте нажмем Retrieve Students кнопка, которая будет извлекать и отображать все записи одну за другой, что соответствует нашей реализации нашего query() метод.

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

Таким образом, вы можете использовать существующий Content Provider, такой как адресная книга, или вы можете использовать концепцию Content Provider при разработке хороших приложений, ориентированных на базы данных, где вы можете выполнять все виды операций с базой данных, такие как чтение, запись, обновление и удаление, как описано выше в примере.

Поделись с друзьями:

Оставьте комментарий