Android - Nhà cung cấp nội dung

Thành phần nhà cung cấp nội dung cung cấp dữ liệu từ một ứng dụng cho những ứng dụng khác theo yêu cầu. Các yêu cầu như vậy được xử lý bởi các phương thức của lớp ContentResolver. Nhà cung cấp nội dung có thể sử dụng các cách khác nhau để lưu trữ dữ liệu của mình và dữ liệu có thể được lưu trữ trong cơ sở dữ liệu, trong tệp hoặc thậm chí qua mạng.

ContentProvider

sometimes it is required to share data across applications. This is where content providers become very useful.

Các nhà cung cấp nội dung cho phép bạn tập trung nội dung ở một nơi và có nhiều ứng dụng khác nhau truy cập nội dung đó khi cần. Một nhà cung cấp nội dung hoạt động rất giống một cơ sở dữ liệu nơi bạn có thể truy vấn nó, chỉnh sửa nội dung của nó, cũng như thêm hoặc xóa nội dung bằng cách sử dụng các phương thức insert (), update (), delete () và query (). Trong hầu hết các trường hợp, dữ liệu này được lưu trữ trong mộtSQlite cơ sở dữ liệu.

Một nhà cung cấp nội dung được triển khai như một lớp con của ContentProvider và phải triển khai một bộ API tiêu chuẩn cho phép các ứng dụng khác thực hiện các giao dịch.

public class My Application extends  ContentProvider {
}

URI nội dung

Để truy vấn nhà cung cấp nội dung, bạn chỉ định chuỗi truy vấn ở dạng URI có định dạng sau:

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

Đây là chi tiết về các phần khác nhau của URI -

Sr.No Phần & Mô tả
1

prefix

Điều này luôn được đặt thành nội dung: //

2

authority

Điều này chỉ định tên của nhà cung cấp nội dung, ví dụ: danh bạ , trình duyệt , v.v. Đối với nhà cung cấp nội dung bên thứ ba, đây có thể là tên đủ điều kiện, chẳng hạn như com.tutorialspoint.statusprovider

3

data_type

Điều này cho biết loại dữ liệu mà nhà cung cấp cụ thể này cung cấp. Ví dụ: nếu bạn đang nhận tất cả các địa chỉ liên hệ từ nhà cung cấp nội dung Danh bạ , thì đường dẫn dữ liệu sẽ là mọi người và URI sẽ giống như nội dung sau: // contact / people

4

id

Điều này chỉ định bản ghi cụ thể được yêu cầu. Ví dụ: nếu bạn đang tìm kiếm số liên lạc 5 trong nhà cung cấp nội dung Danh bạ thì URI sẽ giống như nội dung sau: // danh bạ / người / 5 .

Tạo nhà cung cấp nội dung

Điều này bao gồm một số bước đơn giản để tạo nhà cung cấp nội dung của riêng bạn.

  • Trước hết, bạn cần tạo một lớp Content Provider mở rộng ContentProviderbaseclass.

  • Thứ hai, bạn cần xác định địa chỉ URI của nhà cung cấp nội dung sẽ được sử dụng để truy cập nội dung.

  • Tiếp theo, bạn sẽ cần tạo cơ sở dữ liệu của riêng mình để lưu giữ nội dung. Thông thường, Android sử dụng cơ sở dữ liệu SQLite và khuôn khổ cần ghi đè phương thức onCreate () sẽ sử dụng phương thức SQLite Open Helper để tạo hoặc mở cơ sở dữ liệu của nhà cung cấp. Khi ứng dụng của bạn được khởi chạy, trình xử lý onCreate () của mỗi Trình cung cấp nội dung của nó được gọi trên chuỗi ứng dụng chính.

  • Tiếp theo, bạn sẽ phải triển khai các truy vấn của Trình cung cấp nội dung để thực hiện các hoạt động cụ thể cho cơ sở dữ liệu khác nhau.

  • Cuối cùng, hãy đăng ký Nhà cung cấp nội dung trong tệp hoạt động của bạn bằng thẻ <provider>.

Đây là danh sách các phương thức bạn cần ghi đè trong lớp Nhà cung cấp nội dung để Nhà cung cấp nội dung của bạn hoạt động -

ContentProvider

  • onCreate() Phương thức này được gọi khi trình cung cấp được khởi động.

  • query()Phương thức này nhận được yêu cầu từ khách hàng. Kết quả được trả về dưới dạng đối tượng Con trỏ.

  • insert()Phương pháp này chèn một bản ghi mới vào trình cung cấp nội dung.

  • delete() Phương pháp này xóa bản ghi hiện có khỏi nhà cung cấp nội dung.

  • update() Phương pháp này cập nhật một bản ghi hiện có từ nhà cung cấp nội dung.

  • getType() Phương thức này trả về kiểu MIME của dữ liệu tại URI đã cho.

Thí dụ

Ví dụ này sẽ giải thích cho bạn cách tạo ContentProvider của riêng bạn . Vì vậy, hãy làm theo các bước sau để tương tự như những gì chúng ta đã làm trong khi tạo Ví dụ về Hello World -

Bươc Sự miêu tả
1 Bạn sẽ sử dụng Android StudioIDE để tạo ứng dụng Android và đặt tên là Ứng dụng của tôi trong gói com.example.MyApplication , với Hoạt động trống.
2 Sửa đổi tệp hoạt động chính MainActivity.java để thêm hai phương thức mới onClickAddName ()onClickRetrieveStudents () .
3 Tạo một tệp java mới có tên là StudentsProvider.java trong gói com.example.MyApplication để xác định nhà cung cấp thực tế của bạn và các phương thức liên quan.
4 Đăng ký nhà cung cấp nội dung của bạn trong tệp AndroidManifest.xml bằng thẻ <nhà cung cấp ... />
5 Sửa đổi nội dung mặc định của tệp res / layout / activity_main.xml để bao gồm một GUI nhỏ để thêm hồ sơ học sinh.
6 Không cần thay đổi string.xml. Studio Android sẽ chăm sóc tệp string.xml.
7 Chạy ứng dụng để khởi chạy trình giả lập Android và xác minh kết quả của các thay đổi được thực hiện trong ứng dụng.

Sau đây là nội dung của tệp hoạt động chính được sửa đổi src/com.example.MyApplication/MainActivity.java. Tệp này có thể bao gồm từng phương pháp cơ bản của vòng đời. Chúng tôi đã thêm hai phương thức mới onClickAddName ()onClickRetrieveStudents () để xử lý tương tác của người dùng với ứng dụng.

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());
      }
   }
}

Tạo tệp mới StudentsProvider.java trong gói com.example.MyApplication và sau đây là nội dung củasrc/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);
   }

   /**
      * Database specific constant declarations
   */
   
   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);";

   /**
      * Helper class that actually creates and manages
      * the provider's underlying data repository.
   */
   
   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);

      /**
         * Create a write able database which will trigger its
         * creation if it doesn't already exist.
      */
         
      db = dbHelper.getWritableDatabase();
      return (db == null)? false:true;
   }

   @Override
   public Uri insert(Uri uri, ContentValues values) {
      /**
         * Add a new student record
      */
      long rowID = db.insert(	STUDENTS_TABLE_NAME, "", values);

      /**
         * If record is added successfully
      */
      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 == ""){
         /**
            * By default sort on student names
         */
         sortOrder = NAME;
      }
      
      Cursor c = qb.query(db,	projection,	selection, 
         selectionArgs,null, null, sortOrder);
      /**
         * register to watch a content URI for changes
      */
      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)){
         /**
            * Get all student records
         */
         case STUDENTS:
            return "vnd.android.cursor.dir/vnd.example.students";
         /**
            * Get a particular student
         */
         case STUDENT_ID:
            return "vnd.android.cursor.item/vnd.example.students";
         default:
            throw new IllegalArgumentException("Unsupported URI: " + uri);
      }
   }
}

Sau đây sẽ là nội dung sửa đổi của tệp AndroidManifest.xml . Ở đây chúng tôi đã thêm thẻ <nhà cung cấp ... /> để bao gồm nhà cung cấp nội dung của chúng tôi:

<?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>

Sau đây sẽ là nội dung của res/layout/activity_main.xml tập tin−

<?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="@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>

Đảm bảo rằng bạn có nội dung sau của res/values/strings.xml tập tin:

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

Hãy thử chạy My Applicationứng dụng chúng tôi vừa tạo. Tôi cho rằng bạn đã tạo raAVDtrong khi thiết lập môi trường. Để chạy ứng dụng từ Android Studio IDE, hãy mở một trong các tệp hoạt động của dự án của bạn và nhấp vào

biểu tượng Chạy từ thanh công cụ. Android Studio cài đặt ứng dụng trên AVD của bạn và khởi động nó và nếu mọi thứ đều ổn với thiết lập và ứng dụng của bạn, nó sẽ hiển thị sau cửa sổ Trình mô phỏng, hãy kiên nhẫn vì có thể mất một lúc dựa trên tốc độ máy tính của bạn -

Bây giờ chúng ta hãy nhập học sinh NameGrade và cuối cùng nhấp vào Add Name, điều này sẽ thêm hồ sơ học sinh trong cơ sở dữ liệu và sẽ nhấp nháy thông báo ở dưới cùng hiển thị URI ContentProvider cùng với số bản ghi được thêm vào cơ sở dữ liệu. Hoạt động này sử dụnginsert()phương pháp. Hãy lặp lại quy trình này để thêm một vài sinh viên nữa vào cơ sở dữ liệu của nhà cung cấp nội dung của chúng tôi.

Khi bạn đã hoàn tất việc thêm bản ghi trong cơ sở dữ liệu, bây giờ đã đến lúc yêu cầu ContentProvider cung cấp lại cho chúng tôi những bản ghi đó, vì vậy hãy nhấp vào Retrieve Students nút này sẽ tìm nạp và hiển thị lần lượt tất cả các bản ghi theo như việc chúng tôi triển khai query() phương pháp.

Bạn có thể viết các hoạt động chống lại các hoạt động cập nhật và xóa bằng cách cung cấp các chức năng gọi lại trong MainActivity.java và sau đó sửa đổi giao diện người dùng để có các nút cho các thao tác cập nhật và xóa theo cách giống như chúng ta đã thực hiện đối với các thao tác thêm và đọc.

Bằng cách này, bạn có thể sử dụng Trình cung cấp nội dung hiện có như Sổ địa chỉ hoặc bạn có thể sử dụng khái niệm Trình cung cấp nội dung trong việc phát triển các ứng dụng hướng cơ sở dữ liệu đẹp, nơi bạn có thể thực hiện tất cả các loại hoạt động cơ sở dữ liệu như đọc, ghi, cập nhật và xóa như giải thích ở trên trong ví dụ.