• Uncategorized
  • 0

11.1A: Implement a Minimalist Content Provider

Task 1. Create the MinimalistContentProvider project

ContentProvider: Penyedia konten menyediakan antarmuka publik yang aman ke data, sehingga aplikasi lain bisa mengakses data dengan izin yang sesuai.

ContentResolver: Digunakan oleh Aktivitas untuk mengirimkan kueri ke penyedia konten. Content resolver mengembalikan data sebagai objek Cursor yang kemudian bisa digunakan, misalnya, oleh sebuah adaptor, untuk menampilkan data.

Kelas Contract (tidak diperlihatkan): Contract adalah kelas publik yang mengekspos informasi penting tentang penyedia konten ke aplikasi lain. Ini biasanya menyertakan URI untuk mengakses data, konstanta penting, dan struktur data yang akan dikembalikan

1.1. Create a project within the given constraints

Buat aplikasi dengan satu aktivitas yang hanya menampilkan satu tampilan teks dan dua tombol. Satu tombol menampilkan kata pertama di data (daftar) dan tombol lainnya akan menampilkan semua kata. Kedua tombol memanggil onClickDisplayEntries() saat diklik. Untuk saat ini, metode ini akan menggunakan pernyataan switch hanya untuk menampilkan pernyataan bahwa tombol tertentu diklik. Gunakan tabel di bawah sebagai panduan untuk menyetel proyek Anda.

Nama aplikasi

MinimalistContentProvider

Satu Aktivitas

Template Empty Activity

Name: MainActivity

private static final String TAG = MainActivity.class.getSimpleName();

public void onClickDisplayEntries (View view){Log.d (TAG, “Yay, I was clicked!”);}

TextView

@+id/textview

android:text=”response”

Button

@+id/button_display_all

android:text=”List all words”

android:onClick=”onClickDisplayEntries”

Button

@+id/button_display_first

android:text=”List first word”

android:onClick=”onClickDisplayEntries”

 

1.2. Complete the basic setup

Selesaikan persiapan dasar antarmuka pengguna:

  1. Di MainActivity, buat variabel anggota untuk tampilan teks dan lakukan inisialisasi di onCreate().
  2. Di onClickDisplayEntries(), gunakan pernyataan switch untuk memeriksa tombol mana yang ditekan. Gunakan view id untuk mengenali tombol. Cetak pernyataan log untuk setiap kasus.
  3. Di onClickDisplayEntries(), di bagian akhir, tambahkan beberapa teks ke TextView.
  4. Seperti biasanya, ekstrak sumber daya string.
  5. Jalankan aplikasi.

MainActivity seharusnya sama dengan solusi ini.

package android.example.com.minimalistcontentprovider;

[... imports]

public class MainActivity extends AppCompatActivity {

   private static final String TAG = MainActivity.class.getSimpleName();

   TextView mTextView;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       mTextView = (TextView) findViewById(R.id.textview);
   }

   public void onClickDisplayEntries(View view) {
       Log.d (TAG, "Yay, I was clicked!");

       switch (view.getId()) {
           case R.id.button_display_all:
               Log.d (TAG, "Yay, " + R.id.button_display_all + " was clicked!");
               break;
           case R.id.button_display_first:
               Log.d (TAG, "Yay, " + R.id.button_display_first + " was clicked!");
               break;
           default:
               Log.d (TAG, "Error. This should never happen.");
       }
       mTextView.append("Thus we go! \n");
   }
}

Task 2. Create a Contract class, a URI, and mock data

Contract berisi informasi tentang tentang data yang diperlukan aplikasi untuk membangun kueri.

  • Contract adalah kelas publik yang menyertakan informasi penting untuk aplikasi lain yang ingin terhubung dengan penyedia konten ini dan mengakses data Anda.
  • URI menampilkan cara membangun URI untuk mengakses data. Skema URI berperilaku sebagai API untuk mengakses data. Ini mirip dengan merancang panggilan REST untuk CRUD. Aplikasi lain akan menggunakan URI Konten ini.

2.1. Create the Contract class

  1. Buat kelas Java Contract publik yang baru dengan tanda tangan berikut. Ini harus final.
    public final class Contract {}
    
  2. Untuk mencegah seseorang tidak sengaja membuat instance kelas Contract, berikan constructor pribadi kosong.
    private Contract() {}

 

2.2. Create the URI

URI konten untuk penyedia konten memiliki bentuk umum berikut:

scheme://authority/path/id
  • scheme selalu content:// untuk URI konten.
  • authority (merepresentasikan domain, dan untuk penyedia konten biasanya berakhiran .provider)
  • path adalah jalur menuju data
  • id secara unik mengidentifikasi rangkaian data untuk ditelusuri

URI berikut bisa digunakan untuk meminta semua entri di tabel “words”:

content://com.android.example.wordcontentprovider.provider/words

 

2.3. Add the MIME Type

  1. Deklarasikan tipe MIME untuk satu item data.
    static final String SINGLE_RECORD_MIME_TYPE = "vnd.android.cursor.item/vnd.com.example.provider.words";
    
  2. Deklarasikan tipe MIME untuk beberapa catatan.
    static final String MULTIPLE_RECORD_MIME_TYPE = "vnd.android.cursor.dir/vnd.com.example.provider.words";
    

2.4. Create the mock data

Dalam strings.xml, tambahkan satu daftar kata yang pendek:

<string-array name="words">
   <item>Android</item>
   <item>Activity</item>
   <item>ContentProvider</item>
   <item>ContentResolver</item>
</string-array>

Task 3. Implement the MiniContentProvider class

3.1. Create the MiniContentProvider class

  1. Buat kelas Java MiniContentProvider yang memperluas ContentProvider. (Untuk praktik ini, jangan gunakan opsi menu Create Class > Other > Content Provider.)
  2. Implementasikan metode (Code > Implement methods).
  3. Tambahkan tag log.
  4. Tambahkan variabel anggota untuk data tiruan.
    public String[] mData;
    
  5. Di onCreate(), inisialisasikan mData dari larik kata dan kembalikan true.
    @Override
    public boolean onCreate() {
       Context context = getContext();
       mData = context.getResources().getStringArray(R.array.words);
       return true;
    }
    
  6. Tambahkan pesan log ke metode insert, delete, dan update. Anda tidak akan mengimplementasikan metode ini untuk praktik ini.
    Log.e(TAG, "Not implemented: update uri: " + uri.toString());

3.2. Publish the content provider by adding it to the Android manifest

Deklarasi berisi nama penyedia konten dan otoritas (identifier uniknya).

  1. Dalam AndroidManifest, di dalam tag aplikasi, setelah tag penutup aktivitas, tambahkan:
    <provider
        android:name=".MiniContentProvider"
    android:authorities="com.android.example.minimalistcontentprovider.provider" />
    
  2. Jalankan kode Anda untuk memastikan dikompilasi dengan baik.

3.3. Set up URI matching

Buat perubahan berikut di kelas MiniContentProvider.

  1. Dalam kelas MiniContentProvider, buat variabel statis pribadi untuk UriMatcher.

    Argumen untuk constructor menentukan nilai untuk dikembalikan jika tidak ada kecocokan. Sebagai praktik terbaik, gunakan UriMatcher.NO_MATCH.

    private static UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    
  2. Buat metode Anda sendiri untuk menginisialisasi URI matcher.
    private void initializeUriMatching(){}
    
  3. Panggil initializeUriMatching di onCreate() kelas MiniContentProvider.
  4. Dalam metode initializeUriMatching(), tambahkan URI yang diterima penyedia konten Anda ke matcher dan tetapkan sebagai kode integer. Ini adalah URI berdasarkan otoritas dan jalur konten yang ditetapkan di Contract.

    Simbol # mencocokkan string karakter numerik dengan panjang berapa saja. Di aplikasi ini, ini mengacu pada indeks kata di larik string. Di aplikasi produksi, ini bisa jadi id entri dalam database. Tetapkan URI ini nilai numerik 1.

    sUriMatcher.addURI(Contract.AUTHORITY, Contract.CONTENT_PATH + "/#", 1);
    
  5. URI kedua adalah yang Anda tentukan di Contract untuk mengembalikan semua item. Tetapkan nilai numerik 0.sUriMatcher.addURI(Contract.AUTHORITY, Contract.CONTENT_PATH, 0);

3.4. Implement the getType() method

Metode getType() penyedia konten mengembalikan tipe MIME untuk setiap URI yang ditetapkan.

Kecuali Anda melakukan sesuatu yang khusus di kode Anda, implementasi metode ini akan sangat mirip untuk penyedia konten apa pun. Ini melakukan yang berikut:

  1. Mencocokkan URI.
  2. Mengaktifkan kode yang dikembalikan.
  3. Mengembalikan tipe MIME yang sesuai.
public String getType(Uri uri) {
        switch (sUriMatcher.match(uri)) {
            case 0:
                return Contract.MULTIPLE_RECORD_MIME_TYPE;
            case 1:
                return Contract.SINGLE_RECORD_MIME_TYPE;
            default:
                // Alternatively, throw an exception.
                return null;
        }
    }

3.5 Implement the query() method

Tujuan metode query() adalah untuk mencocokkan URI, mengonversinya ke mekanisme akses data internal Anda (misalnya, kueri SQLite), mengeksekusi kode akses data internal, dan mengembalikan hasil di objek Cursor.

The query() method

Metode query memiliki tanda tangan berikut:

public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder){}

Argumen ke metode ini merepresentasikan bagian kueri SQL. Bahkan jika Anda menggunakan jenis mekanisme storage data lain, Anda masih harus menerima kueri dengan gaya ini dan menangani argumen dengan benar.

uri

URI lengkap. Ini tidak boleh null.

projection

Menunjukkan kolom/atribut mana untuk diakses.

selection

Menunjukkan baris/catatan objek mana untuk diakses.

selectionArgs

Parameter yang melekat pada argumen pilihan sebelumnya.

Untuk alasan keamanan, argumen diproses terpisah.

sortOrder

Apakah akan mengurutkan, dan jika demikian, apakah naik, turun, atau berdasarkan.

Jika ini null, pengurutan default atau tanpa pengurutan akan diterapkan.

 

Analyze the query() method

  1. Identifikasi langkah-langkah pemrosesan berikut di kode metode kueri() yang ditampilkan di bawah di bagian solusi.

    Pemrosesan kueri selalu terdiri dari langkah-langkah ini:

    1. Mencocokkan URI.

    2. Mengaktifkan kode yang dikembalikan.

    3. Memproses argumen dan membangun kueri yang sesuai untuk backed.

    4. Dapatkan data dan (jika perlu) masukkan ke dalam Cursor.

    5. Kembalikan kursor.

  2. Identifikasi bagian kode yang perlu diubah di aplikasi dunia nyata.

    Implementasi kueri untuk aplikasi dasar ini mengambil beberapa pintasan.

    • Penanganan kesalahan minimal.
    • Karena aplikasi menggunakan data tiruan, Cursor bisa diisi secara langsung.
    • Karena skema URI sederhana, metode ini cukup singkat.
  3. Identifikasi setidaknya satu keputusan desain yang memudahkan pemahaman dan pengelolaan kode.
    • Menganalisis kueri dan mengeksekusinya untuk mengisi kursor dipisahkan ke dalam dua metode.
    • Kode berisi lebih banyak kode daripada kode yang bisa dieksekusi.
  4. Tambahkan kode ke aplikasi Anda.
@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
   int id = -1;
   switch (sUriMatcher.match(uri)) {
       case 0:
           // Matches URI to get all of the entries.
           id = Contract.ALL_ITEMS;
           // Look at the remaining arguments
           // to see whether there are constraints.
           // In this example, we only support getting
           //a specific entry by id. Not full search.
           // For a real-life app, you need error-catching code;
           // here we assume that the
           // value we need is actually in selectionArgs and valid.
           if (selection != null){
               id = parseInt(selectionArgs[0]);
           }
           break;

       case 1:
           // The URI ends in a numeric value, which represents an id.
           // Parse the URI to extract the value of the last,
           // numeric part of the path,
           // and set the id to that value.
           id = parseInt(uri.getLastPathSegment());
           // With a database, you would then use this value and
           // the path to build a query.
           break;

       case UriMatcher.NO_MATCH:
           // You should do some error handling here.
           Log.d(TAG, "NO MATCH FOR THIS URI IN SCHEME.");
           id = -1;
           break;
       default:
           // You should do some error handling here.
           Log.d(TAG, "INVALID URI - URI NOT RECOGNIZED.");
           id = -1;
   }
   Log.d(TAG, "query: " + id);
   return populateCursor(id);
}

 

3.6. Implement the populateCursor() method

Metode query harus mengembalikan tipe Cursor, sehingga metode populateCursor() harus membuat, mengisi, dan mengembalikan kursor.

  • Jika data Anda disimpan di database SQLite, mengeksekusi kueri akan mengembalikan sebuah Cursor.
  • Jika Anda tidak menggunakan metode storage data yang mengembalikan kursor, seperti file atau data tiruan, Anda bisa menggunakan MatrixCursor untuk menampung data yang akan dikembalikan. MatrixCursor adalah kursor untuk penggunaan umum ke dalam larik objek yang terus bertambah sesuai kebutuhan. Untuk membuat MatrixCursor, Anda harus mengisinya dengan larik string nama kolom.

Metode populateCursor() melakukan yang berikut:

  1. Menerima id yang diekstrak dari URI.
  2. Membuat MatrixCursor untuk menyimpan data yang diterima (karena data tiruan yang diterima bukan kursor).
  3. Membuat dan mengeksekusi kueri. Untuk aplikasi ini, ini akan mengambil string di indeks id dari larik string. Dalam aplikasi yang lebih realistis, ini bisa mengeksekusi kueri ke database.
  4. Menambahkan hasil ke kursor.
  5. Mengembalikan kursor.
    private Cursor populateCursor(int id) {
       MatrixCursor cursor = new MatrixCursor(new String[] { Contract.CONTENT_PATH });
       // If there is a valid query, execute it and add the result to the cursor.
       if (id == Contract.ALL_ITEMS) {
           for (int i = 0; i < mData.length; i++) {
               String word = mData[i];
               cursor.addRow(new Object[]{word});
           }
       } else if (id >= 0) {
           // Execute the query to get the requested word.
           String word = mData[id];
           // Add the result to the cursor.
           cursor.addRow(new Object[]{word});
       }
       return cursor;
    }

Task 4. Use a ContentResolver to get data

Setelah mempersiapkan penyedia konten, metode onClickDisplayEntries() di MainActivity bisa diluaskan untuk melakukan kueri dan menampilkan data ke UI. Ini memerlukan langkah-langkah berikut:

  1. Buat kueri bergaya SQL, bergantung pada tombol mana yang ditekan.
  2. Gunakan content resolver untuk berinteraksi dengan penyedia konten untuk mengeksekusi kueri dan mengembalikan sebuah Cursor.
  3. Proses hasilnya di Cursor.

4.1. Get the content resolver

Content resolver berinteraksi dengan penyedia konten atas nama Anda.

Content resolver mengharapkan URI Content yang di-parse bersama dengan parameter kueri yang membantu mengambil data.

Anda tidak harus membuat content resolver sendiri. Anda bisa menggunakan yang disediakan di konteks aplikasi Anda oleh framework Android dengan memanggil getContentResolver().

  1. Di MainActivity, hapus semua kode dari dalam onClickDisplayEntries().
  2. Tambahkan kode ini ke onClickDisplayEntries() di MainActivity.
    Cursor cursor = getContentResolver().query(Uri.parse(queryUri), projection, selectionClause, selectionArgs, sortOrder);
    

4.2. Define the query arguments

Agar getContentResolver.query() bisa berfungsi, Anda harus mendeklarasikan dan menetapkan nilai ke semua argumennya.

  1. URI: Deklarasikan ContentURI yang mengidentifikasi penyedia konten dan tabel. Dapatkan informasi untuk URI yang benar dari contract.
    String queryUri = Contract.CONTENT_URI.toString();
    
  2. Projection: Sebuah larik string dengan nama kolom untuk dikembalikan. Menyetel ini ke null akan mengembalikan semua kolom. Jika hanya ada satu kolom, seperti di contoh ini, menyetel ini secara eksplisit adalah opsional, tetapi bisa berguna untuk tujuan dokumentasi. // Only get words. String[] projection = new String[] {Contract.CONTENT_PATH};
  3. selectionClause: Klausa argumen untuk kriteria pilihan, yaitu, baris mana yang akan dikembalikan. Diformat sebagai klausa SQL WHERE (mengecualikan kata kunci “WHERE”). Meneruskan null akan mengembalikan semua baris untuk tampilan URI yang diberikan. Karena ini akan berbeda sesuai dengan tombol mana yang ditekan, deklarasikan ini sekarang dan setel nanti.
    String selectionClause;
    
  4. selectionArgs: Nilai argumen untuk kriteria pilihan. Jika Anda menyertakan ? di String selection, ? akan digantikan oleh nilai dari selectionArgs, dengan urutan munculnya.
    PENTING: Praktik terbaik keamanan adalah selalu memisahkan selection dan selectionArgs.

    String selectionArgs[];

  5. sortOrder: Urutan untuk mengurutkan hasil. Diformat sebagai klausa SQL ORDER BY (mengecualikan kata kunci ORDER BY). Biasanya ASC atau DESC; null meminta tata urutan default, yang bisa jadi tidak berurutan.
    // For this example, accept the order returned by the response.
    String sortOrder = null;

4.3. Decide on selection criteria

Nilai selectionClause dan selectionArgs bergantung pada tombol mana yang ditekan di UI.

  • Untuk menampilkan semua kata, setel kedua argumen ke null.
  • Untuk mendapatkan kata pertama, kueri kata dengan ID 0. (Ini mengasumsikan bahwa ID kata dimulai dari 0 dan dibuat sesuai urutan. Anda mengetahui ini, karena informasinya diperlihatkan di contract. Untuk penyedia konten yang berbeda, sebaiknya ketahui id-nya dan telusuri dengan cara yang berbeda.)
  1. Ganti blok switch yang sudah ada dengan kode berikut ini di onClickDisplayEntries, sebelum Anda mendapatkan content resolver.
    switch (view.getId()) {
       case R.id.button_display_all:
           selectionClause = null;
           selectionArgs = null;
           break;
       case R.id.button_display_first:
           selectionClause = Contract.WORD_ID + " = ?";
           selectionArgs = new String[] {"0"};
           break;
       default:
           selectionClause = null;
           selectionArgs = null;
    }

4.4. Process the Cursor

Setelah mendapatkan content resolver, Anda harus memproses hasil dari Cursor.

  • Jika ada data, tampilkan di TextView.
  • Jika tidak ada data, laporkan kesalahan.
  1. Periksa kode berikut dan pastikan Anda memahami semuanya.
       if (cursor != null) {
       if (cursor.getCount() > 0) {
           cursor.moveToFirst();
           int columnIndex = cursor.getColumnIndex(projection[0]);
           do {
               String word = cursor.getString(columnIndex);
               mTextView.append(word + "\n");
           } while (cursor.moveToNext());
       } else {
           Log.d(TAG, "onClickDisplayEntries " + "No data returned.");
           mTextView.append("No data returned." + "\n");
       }
       cursor.close();
    } else {
       Log.d(TAG, "onClickDisplayEntries " + "Cursor is null.");
       mTextView.append("Cursor is null." + "\n");
    }
    
  2. Sisipkan kode ini di akhir onClickDisplayEntry().
  3. Jalankan aplikasi Anda.
  4. Klik tombol untuk melihat data yang diambil di TextView.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *