Struktur File Untuk Develop Kamus Digital

Yang telah nimbrung di vik.sintus@gmail.com sorry saya tak bisa membalas satu persatu emailnya. Semoga postingan ini akan mempermudahkan semuanya dalam menyelesaikan proyek pembuatan kamus digital ini, baik yang mengerjakan-nya untuk menyelesaikan tugas akhir maupun yang untuk hobi.

NOTE: aplikasi ini di bangun pakai android versi 11 ke atas

Semua kemacetan yang terjadi dalam proyek aplikasi adalah kebanyakan di sebabkan oleh minimnya pemahaman struktur file dalam android. Saya harus menahan diri untuk tidak menyatakan, 'belajar android dari awal dulu sebelum terjun ke develop aplikasi' karena ini adalah dunia pembelajaran.
Terserah tiap pribadi apakah mau belajar dari awal, dari tengah atau mulai dari akhir, tergantung selera masing2 yang penting kita tetap sama2 ingin belajar,... sikat terus man.

Seharusnya setelah langkah dan proses pembuatan package (build process) dan proses menamakan class utama di lakukan dengan benar dalam eclipse maka file strukture akan otomatis di generate dan terlihat seperti pada gambar 1 berikut:

gambar 1
Setelah di generate secara otomatis oleh eclipse maka akan terlihat nama aplikasi-nya, dalam hal ini saya kasih nama 'kamusDigital'
Sedangkan class utama yang di isi namanya pada waktu build process akan menempatkan dari dalam folder 'src' disanalah semua class java akan berkumpul. Jadi semua kode yang menyangkut logika aplikasi akan berada di dalam folder 'src' tersebut.

Yang saya tandai dengan panah merah pada gambar 1 di atas adalah lokasi semua folder dan file yang kita buat dan yang kita akan selalu sentuh selama development, sedangkan semua yang lain-nya ter-generate sendiri ole eclipse sehingga tak perlu di sentuh ( kecuali kalau sudah super mahir).

Mari kita mulai dengan membuka folder yang menyangkut logika dari pembangunan aplikasi ini yaitu folder 'src' dan setelah di buka maka akan terlihat semua class java yang di butuhkan oleh aplikasi, seperti yang terlihat pada gambar 2 berikut:
gambar 2


Saya membutuhkan 4 buah class untuk aplikasi kamusDigital. Silahkan menamakan class sesuai logika sendiri. Dan apabila aplikasinya membutuhkan class baru maka silahkan klik kanan pada kamusDigital, New lalu klik Class. Silahkan menamakan class-nya sesuai logika sendiri.
Berikut adalah isi dari ke 4 class tsb:

1. KamusDatabase.java adalah sbb:

package com.vik_sintus.projects.kamusDigital;
/**
 * Copyright (C) 2013 Vik Sintus Projects
 *
 * Segala kelebihan dan kekurangan di luar tanggung jawab pembuat.
 * Di larang memakai kode ini untuk kepentingan komersial tanpa ijin.
 * Silahkan di pakai untuk kepentingan belajar.
 * vik.sintus@gmail.com
 * http://belajar-android-indonesia.blogspot.com
 * Unless required by applicable law or agreed to in writing, this software
 * is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * 
 * 
 */
import android.app.SearchManager;
import android.content.ContentValues;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.provider.BaseColumns;
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;

/**
 * logika utk mengambil data dari database, dan
 * memasang table, kolom, baris yang di butuhkan.
 */
public class KamusDatabase {
    private static final String TAG = "KamusDatabase";

    // kolom yang akan di pakai di table-nya database kamus
    // yaitu kolom KATA dan kolom ARTI_NYA
    public static final String KATA = SearchManager.SUGGEST_COLUMN_TEXT_1;
    public static final String ARTI_NYA = SearchManager.SUGGEST_COLUMN_TEXT_2;

    private static final String NAMA_DATABASE = "kamus";
    private static final String TEMPAT_MUNCUL_KATA = "membentangKebawah";
    private static final int VERSI_DATABASE = 2;
    // perantara antara database dan aplikasi
    private final MembantuBukaKamus bukaDatabase;
    private static final HashMap<String,String> penghubungKolom = buatPenghubungKolom();

    
     // berikut adalah Constructor-nya
     // @parameter context maksudnya pada konteks apa class ini bekerja, 
     // dalam hal ini adalah utk membuat database
     
    public KamusDatabase(Context context) {
     bukaDatabase = new MembantuBukaKamus(context);
    }

    
     // membuat penghubung(map) utk semua kolom yg 
     // akan di butuhkan, yang di dalam-nya akan di pasang 
     // SQLiteQueryBuilder. Ini adalah suatu cara yang 
     // baik untuk mendefinisikan nama alias dari kolom2
     // tapi hal itu berarti harus menyertakan 
     // semua kolom yg ada, termasuk kolom key 
     // dengan demikian peluang ContentProvider terbuka 
     // lebar untuk mencari kolom tanpa
     // mengenal nama asli kolom sehingga 
     // bisa membuat nama kolom samaran(alias) on the go
     // bila di butuhkan
     
    private static HashMap<String,String> buatPenghubungKolom() {
        HashMap<String,String> menghubungkan = new HashMap<String,String>();
        menghubungkan.put(KATA, KATA);
        menghubungkan.put(ARTI_NYA, ARTI_NYA);
        menghubungkan.put(BaseColumns._ID, "rowid AS " +
                BaseColumns._ID);
        menghubungkan.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " +
                SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
        menghubungkan.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, "rowid AS " +
                SearchManager.SUGGEST_COLUMN_SHORTCUT_ID);
        return menghubungkan;
    }

    
     // letak-kan cursor pada kata yang di 
     // identifikasikan dengan rowId
     // @parameter barisId adalah Id dari kata yang mau di cari
     // @parameter kolom adalah salah satu kolom yg termasuk dalam search, 
     // kalau kolom==null maka semua 
     // kolom berarti di ikut sertakan dalam search
     // @return Cursor tempatkan cursor pada kata yang cocok, atau
     // null kalau tak menemukan kata yang cocok
     
    public Cursor getWord(String barisID, String[] kolom) {
        String pilihKata = "rowId = ?";
        String[] kolomTempatKata = new String[] {barisID};

        return query(pilihKata, kolomTempatKata, kolom);

        
         //  sama dengan:
         //     SELECT <columns> FROM <table> WHERE barisID = <rowId>
         
    }

    
     // Cursor akan menemukan semua kata yang 
     // sesuai dengan search pencari
     
     // @parameter query adalah string utk mendapatkan isi 
     // @parameter kolom agar kolom tetentu termasuk 
     // dalam pencarian, tapi kalau null maka
     // semuanya kolom teramsuk dalam pencarian
     // @return Cursor ambil semua kata yg cocok, 
     // atau null kalau tak satupun ygcocok.
     
    public Cursor getWordMatches(String cariKata, String[] kolom) {
        String pilihKata = KATA + " MATCH ?";
        String[] tempatPenampungKata = new String[] {cariKata+"*"};

        return query(pilihKata, tempatPenampungKata, kolom);

       
         // sama seperti mysql
         //     SELECT <columns> FROM <table> WHERE 
         //     <KEY_WORD> MATCH 'query*'
         // yang adalah bentuk search text utk 
         // FTS3 (tambah sebuah wildcard) didalam kolom kata2
         // fts3(full text search versi 3).
         
         // - "rowid" adalah unik utk semua baris tapi 
         // kita butuh nilai utk kolom "_id"  agar
         // adapter dapat bekerja, jadi kolom alias adalah 
         // "_id" untuk "rowid"
         // - "rowid" juga perlu di gunakan pada 
         // SUGGEST_COLUMN_INTENT_DATA alias sebagai
         //   pertimbangan dalam melakukan 
         //   cek intent data dengan benar.
         //   Semua alias yg di maksud di jelaskan dalam 
         //   class 'PenghubungData' pada pembuatan query.
         // - hal tsb juga dpt di rubah kalau mau search melalui 
         // ARTI_NYA daripada men-search lewat KATA
         // hal tsb dapat di lakukan dengan merubah 
         // pencarian pakai FTS3 dengan mengganti KEY_WORD dgn
         // FTS_VIRTUAL_TABLE (soearch bolak-balik) tapi 
         // hal tsb akan menyulitkan pengaturan abjad karena
         // kadang satu kata akan memiliki arti lebih dari satu kata
         
    }

    
     // melakukan query ke database.
     // @parameter 'pilihan' adalah mengatur memilih kata
     // @param gudangKataKata adalah pilihan arguments 
     // untuk komponen "?" dalam pilihan
     // @param kolom adalah kolom untuk di isi (return)
     // @return A Cursor pada semua baris yang 
     // cocok dengan tujuan pencarian
     
    private Cursor query(String pilihan, String[] gudangKataKata, String[] kolom) {
        
         // SQLiteBuilder menyediakan sebuah 
         // penghubung(map)utk semua kolom yg di request dengan
         // kolom sebenarnya di databse, membuat 
         // mekanisme kolom aliasnya yg sederhana 
         // yang mana PenghubungData tak perlu 
         // tahu nama kolom sebenarnya
         
        SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
        builder.setTables(TEMPAT_MUNCUL_KATA);
        builder.setProjectionMap(penghubungKolom);

        Cursor cursor = builder.query(bukaDatabase.getReadableDatabase(),
                kolom, pilihan, gudangKataKata, null, null, null);

        if (cursor == null) {
            return null;
        } else if (!cursor.moveToFirst()) {
            cursor.close();
            return null;
        }
        return cursor;
    }


    
     // ini utk membuat/membuka databasenya.
     
    private static class MembantuBukaKamus extends SQLiteOpenHelper {

        private final Context bantuBukaDB;
        private SQLiteDatabase databasenya;

        
         // catatan bahwa FTS3 tidak mendukung 
         // hukum kolom oleh karena itu
         // tak dapat mendeklarasikan sebuah 
         // primary key. Namun demikian, "rowid" akan  
         // di gunakan secara otomatis sebagai 
         // unique identifier maka ketika membuat pencarian,
         //  kita akan gunakan "_id" sebagai sebuah
         //  alias untuk "rowid"
         
        private static final String FTS_TABLE_CREATE =
                    "CREATE VIRTUAL TABLE " + TEMPAT_MUNCUL_KATA +
                    " USING fts3 (" +
                    KATA + ", " +
                    ARTI_NYA + ");";

        MembantuBukaKamus(Context bantuBukaKamus) {
            super(bantuBukaKamus, NAMA_DATABASE, null, VERSI_DATABASE);
            bantuBukaDB = bantuBukaKamus;
        }

        @Override
        public void onCreate(SQLiteDatabase membuatDatabase) {
            databasenya = membuatDatabase;
            databasenya.execSQL(FTS_TABLE_CREATE);
            masukanDiKamus();
        }

        
        
         // mulai sebuah thread utk masukan sebuah 
         // table di database beserta kata-katanya
         
        private void masukanDiKamus() {
            new Thread(new Runnable() {
                public void run() {
                    try {
                        masukanKataKata();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }).start();
        }

        private void masukanKataKata() throws IOException {
            Log.d(TAG, "tunggu yah sedang masukan kata...");
            final Resources sumberKataKata = bantuBukaDB.getResources();
            InputStream masukanKataKata = sumberKataKata.openRawResource(R.raw.daftar_kata_kata);
            BufferedReader membacaKataKata = new BufferedReader(new InputStreamReader(masukanKataKata));

            try {
                String barisanKataKata;
                while ((barisanKataKata = membacaKataKata.readLine()) != null) {
                    String[] daftarKataKata = TextUtils.split(barisanKataKata, "-");
                    if (daftarKataKata.length < 2) continue;
                    long idKataKata = tambahKataKata(daftarKataKata[0].trim(), daftarKataKata[1].trim());
                    if (idKataKata < 0) {
                        Log.e(TAG, "tak bisa menambah Kata: " + daftarKataKata[0].trim());
                    }
                }
            } finally {
             membacaKataKata.close();
            }
            Log.d(TAG, "selesai loading kata-kata.");
        }

       
         // tambah kata untuk membentang ke bawah.
         // @return rowId or -1 jikalau gagal
         
        public long tambahKataKata(String kata, String arti_nya) {
            ContentValues jajaranKataKata = new ContentValues();
            jajaranKataKata.put(KATA, kata);
            jajaranKataKata.put(ARTI_NYA, arti_nya);

            return databasenya.insert(TEMPAT_MUNCUL_KATA, null, jajaranKataKata);
        }

        @Override
        public void onUpgrade(SQLiteDatabase gantiDataBase, int versiLama, int versiBaru) {
            Log.w(TAG, "Database di upgrade dari versi " + versiLama + " ke "
                    + versiBaru + ", dan akan menghapus semua data yg lama");
            gantiDataBase.execSQL("DROP TABLE IF EXISTS " + TEMPAT_MUNCUL_KATA);
            onCreate(gantiDataBase);
        }
    }

}

2. Berikut adalah isi dari KamusDigital.java
/*
 * Copyright (C) 2013 Vik Sintus Projects
 *
 * Segala kelebihan dan kekurangan di luar tanggung jawab pembuat.
 * Di larang memakai kode ini untuk kepentingan komersial tanpa ijin.
 * Silahkan di pakai untuk kepentingan belajar.
 * vik.sintus@gmail.com
 *
 * Unless required by applicable law or agreed to in writing, this software
 * is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * 
 * 
 */

package com.vik_sintus.projects.kamusDigital;

import android.app.Activity;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

/**
 * beraksi sebagai halaman depan (main).
 * yang menayangkan hasil pencarian dari 'search dialog' dan
 * menghandle aksi apa yg di lakukan dengan hasil.
 */
public class KamusDigital extends Activity {

    private TextView munculTulisan;
    private ListView barisanKata;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tampilan);

        munculTulisan = (TextView) findViewById(R.id.tulisanMuncul);
        barisanKata = (ListView) findViewById(R.id.barisDemiBaris);

        mengaturIntent(getIntent());
    }

    @Override
    protected void onNewIntent(Intent intent) {
        // oleh karena aktivitas-nya di set dengan launchMode="singleTop", itu berarti 
        // halaman(aktivitas) dapat di daur ulang dalam arti kalau halaman telah 
     // di buka sebelumnya maka tak perlu di buka lagi tapi hanya menghidupkan 
     // intent pada halaman tsb sehingga mengangkatnya ke depan (terlihat lagi)
        
     
        
        mengaturIntent(intent);
    }

    private void mengaturIntent(Intent intent) {
        if (Intent.ACTION_VIEW.equals(intent.getAction())) {
            // mengatur klik utk search suggestion dan menghidupkan
         // activity yg membuat kata2 bisa di klik
            Intent agarKataDptDiKlik = new Intent(this, TampilanKata.class);
            agarKataDptDiKlik.setData(intent.getData());
            startActivity(agarKataDptDiKlik);
            finish();
        } else if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            // mengatur query pencarian
            String query = intent.getStringExtra(SearchManager.QUERY);
            hasilPencarian(query);
        }
    }

    /**
     * cari di kamus dan tunjukan hasil dari query tertentu
     * @parameter query-nya adalah search query
     */
    private void hasilPencarian(String query) {

        Cursor cursor = managedQuery(PenghubungData.CONTENT_URI, null, null,
                                new String[] {query}, null);

        if (cursor == null) {
            // kalau tak ada hasil di ketemukan
            munculTulisan.setText(getString(R.string.tak_ada_hasil, new Object[] {query}));
        } else {
            // tunjukan beberapa hasil
            int count = cursor.getCount();
            String countString = getResources().getQuantityString(R.plurals.hasil_pencarian,
                                    count, new Object[] {count, query});
            munculTulisan.setText(countString);

            // KATA di taruh di kolom 'kolomKata' 
            // ARTI_NYA di taruh di 'kolomArtinya'
            String[] dari = new String[] { KamusDatabase.KATA,
                                           KamusDatabase.ARTI_NYA };

            // buatkan hubungan antara design element, dimana kolom akan muncul 
            int[] ke = new int[] { R.id.kolomKata,
                                   R.id.kolomArtinya };

            // buatkan cursor adapter sederhana utk semua kata dan 
            // artinya dan tayangkan baris demi baris(ListView) pada layar
            SimpleCursorAdapter letakanKataPadaTempatnya = new SimpleCursorAdapter(this,
                                          R.layout.hasil, cursor, dari, ke);
            barisanKata.setAdapter(letakanKataPadaTempatnya);

            // apa yg terjadi saat klik pada kata2 yang telah berjajar baris demi baris di layar 
            barisanKata.setOnItemClickListener(new OnItemClickListener() {
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    // ketika sebauh kata dapat di klik
                    Intent kataDiKlik = new Intent(getApplicationContext(), TampilanKata.class);
                    Uri data = Uri.withAppendedPath(PenghubungData.CONTENT_URI,
                                                    String.valueOf(id));
                    kataDiKlik.setData(data);
                    startActivity(kataDiKlik);
                }
            });
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater perpanjangTampilan = getMenuInflater();
        perpanjangTampilan.inflate(R.menu.untuk_menu, menu);

        SearchManager mengaturSearch = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView tampilanSearch = (SearchView) menu.findItem(R.id.cari).getActionView();
        tampilanSearch.setSearchableInfo(mengaturSearch.getSearchableInfo(getComponentName()));
        tampilanSearch.setIconifiedByDefault(false);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.cari:
                onSearchRequested();
                return true;
            default:
                return false;
        }
    }
}

3. Berikut adalah PenghubungData.java


/*
 /*
 * Copyright (C) 2013 Vik Sintus Projects
 *
 * Segala kelebihan dan kekurangan di luar tanggung jawab pembuat.
 * Di larang memakai kode ini untuk kepentingan komersial tanpa ijin.
 * Silahkan di pakai untuk kepentingan belajar.
 * vik.sintus@gmail.com
 *
 * Unless required by applicable law or agreed to in writing, this software
 * is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * 
 * 
 */

package com.vik_sintus.projects.kamusDigital;

import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.provider.BaseColumns;

/**
 * utk akses ke kamus database.
 * class 'PenghubungData' ini bertindak sebagai 
 * perantara antara database dan aplikasi
 */
public class PenghubungData extends ContentProvider {
    String TAG = "PenyediaData";
   // tunjukan alamat database
    public static String AUTHORITY = "com.vik_sintus.projects.kamusDigital.PenghubungData";
    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/kamus");

    // MIME types (multi-media/multi-purpose internet mail extension) utk 
    // mencari KATA dan Arti_NYA 
    public static final String MIME_TYPE_KATA = ContentResolver.CURSOR_DIR_BASE_TYPE +
                                                  "/vnd.vik_sintus.projects.kamusDigital";
    public static final String MIME_TYPE_ARTI_NYA = ContentResolver.CURSOR_ITEM_BASE_TYPE +
                                                       "/vnd.vik_sintus.projects.kamusDigital";

    private KamusDatabase kamusDB;

    // untuk mencocokan lokasi resource-nya
    // melalui URI(universal resource identifier)
    private static final int KLIK_PD_KATA = 0;
    private static final int DAPAT_ARTI_KATA = 1;
    private static final int KATA_YG_KELUAR = 2;
    private static final int REFRESH_SHORTCUT = 3;
    private static final UriMatcher cocokan_URI_nya = buatkan_UriMatcher_nya();

    /**
     * bangun UriMatcher-nya.
     */
    private static UriMatcher buatkan_UriMatcher_nya() {
        UriMatcher mencocokanURI =  new UriMatcher(UriMatcher.NO_MATCH);
        //  klik pd kata agar artinya muncul
        mencocokanURI.addURI(AUTHORITY, "kamus", KLIK_PD_KATA);
        mencocokanURI.addURI(AUTHORITY, "kamus/#", DAPAT_ARTI_KATA);
        // kata-kata yang keluar saat ketik di kotak search
        mencocokanURI.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, KATA_YG_KELUAR);
        mencocokanURI.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", KATA_YG_KELUAR);

        /* berikut tak di pakai, tapi kalau kita pakai
         * {@link SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} sebagai 
         * kolom di table, maka kita akan menerima
         * refresh queries ketika a shortcutted suggestion di 
         * tayangkan di Quick Search Box, yg dalam hal ini,
         * URI berikut di sediakan dan kita akan
         * mengembalikan kursor dengan single item yg 
         * merepresentasikan sugesti dat yang telah di refresh.
         */
        mencocokanURI.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT, REFRESH_SHORTCUT);
        mencocokanURI.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", REFRESH_SHORTCUT);
        return mencocokanURI;
    }

    @Override
    public boolean onCreate() {
        kamusDB = new KamusDatabase(getContext());
        return true;
    }

    /**
     * utk menghandle semua pencarian dan kata2 apa yang di perkirakan akan 
     * muncul dari Search Manager.
     * ketika mencari kata yang telah kita ketahui, hanya URI akan di perlukan.
     * ketika mencari semua kata2 atau tak jelas kata apa
     * yang mau di cari, maka 'pilihDariSemuaKataYgAda' harus sebagai
     * elemen pertama untuk search query.
     * semua argumen lain-nya akan di kesampingkan/tak dipedulikan.
     */
    @Override
    public Cursor query(Uri uri, String[] perkiraanKata, String pilihan, String[] pilihDariSemuaKataYgAda,
                        String menurutAbjad) {

        // gunakan UriMatcher utk melihat query macam 
     // apa saja yang kita butuhkan sehingga
     // DB query dapat di format sesuai kebutuhan
        switch (cocokan_URI_nya.match(uri)) {
            case KATA_YG_KELUAR:
                if (pilihDariSemuaKataYgAda == null) {
                  throw new IllegalArgumentException(
                      "oik, tak ada data yg mau di pilih di: " + uri);
                }
                return getSuggestions(pilihDariSemuaKataYgAda[0]);
            case KLIK_PD_KATA:
                if (pilihDariSemuaKataYgAda == null) {
                  throw new IllegalArgumentException(
                      "oik, tak ada data yg mau di pilih di: " + uri);
                }
                return search(pilihDariSemuaKataYgAda[0]);
            case DAPAT_ARTI_KATA:
                return getWord(uri);
            case REFRESH_SHORTCUT:
                return refreshShortcut(uri);
            default:
                throw new IllegalArgumentException("tak mengenal alamat Uri: " + uri);
        }
    }

    private Cursor getSuggestions(String deretanKataYgMuncul) {
      deretanKataYgMuncul = deretanKataYgMuncul.toLowerCase();
      String[] kolom_nya = new String[] {
          BaseColumns._ID,
          KamusDatabase.KATA,
          KamusDatabase.ARTI_NYA,
       /* SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
                        (hanya jikalau short cut-nya butuh di refresh) */
          SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID};

      return kamusDB.getWordMatches(deretanKataYgMuncul, kolom_nya);
    }

    private Cursor search(String kataYgDiCari) {
      kataYgDiCari = kataYgDiCari.toLowerCase();
      String[] kolom_nya = new String[] {
          BaseColumns._ID,
          KamusDatabase.KATA,
          KamusDatabase.ARTI_NYA};

      return kamusDB.getWordMatches(kataYgDiCari, kolom_nya);
    }

    private Cursor getWord(Uri uri) {
      String rowId = uri.getLastPathSegment();
      String[] columns = new String[] {
          KamusDatabase.KATA,
          KamusDatabase.ARTI_NYA};

      return kamusDB.getWord(rowId, columns);
    }

    private Cursor refreshShortcut(Uri uri) {
      /* berikut takan di gunakan pada 
       * implementasi ini, tapi kalau kitan mengikut sertakan
       * {@link SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} sebagai sebuah 
       * kolom suggestions table, kita akan menerima refresh queries
       * ketika sebuah shortcutted suggestion di tunjukan di kotak Quick Search
       * dalam arti, methode ini  akan melihat kedalam table utk kata tertentu
       * menggunakan item dalam URI dan menyediakan 
       * semua kolom yang tadinya di sediakan untuk 
       * suggestion query.
       */
      String rowId = uri.getLastPathSegment();
      String[] columns = new String[] {
          BaseColumns._ID,
          KamusDatabase.KATA,
          KamusDatabase.ARTI_NYA,
          SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
          SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID};

      return kamusDB.getWord(rowId, columns);
    }

    /**
     * metode berikut di perlukan agar 
     * dapat men-query tipe query yang di dukung.
     * dan juga berguna dalam metode query() kita sendiri agar 
     * mengetahui type URI yang di terima.
     */
    @Override
    public String getType(Uri uri) {
        switch (cocokan_URI_nya.match(uri)) {
            case KLIK_PD_KATA:
                return MIME_TYPE_KATA;
            case DAPAT_ARTI_KATA:
                return MIME_TYPE_ARTI_NYA;
            case KATA_YG_KELUAR:
                return SearchManager.SUGGEST_MIME_TYPE;
            case REFRESH_SHORTCUT:
                return SearchManager.SHORTCUT_MIME_TYPE;
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
        }
    }

    // implementasi lain yang di butuhkan

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }

}


4. TampilanKata.java adalah sbb:
package com.vik_sintus.projects.kamusDigital;
/*
 * Copyright (C)2013 Vik Sintus Projects
 *
 * di larang pakai kode ini untuk kepentingan komersial tanpa ijin
 * vik.sintus@gmail.com.
 * http://belajar-android-indonesia.blogspot.com
 *
 * Unless required by applicable law or agreed to in writing, this software
 * is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * 
 */
import android.app.ActionBar;
import android.app.Activity;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.SearchView;
import android.widget.TextView;

/**
 * class ini utk menampilkan kata-kata dan artinya.
 */
public class TampilanKata extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.kata);

        ActionBar tempatTampilKata = getActionBar();
        tempatTampilKata.setDisplayHomeAsUpEnabled(true);

        Uri uri = getIntent().getData();
        Cursor cursor = managedQuery(uri, null, null, null, null);

        if (cursor == null) {
            finish();
        } else {
            cursor.moveToFirst();

            TextView kataKata = (TextView) findViewById(R.id.kolomKata);
            TextView artinya = (TextView) findViewById(R.id.kolomArtinya);

            int indexKata = cursor.getColumnIndexOrThrow(KamusDatabase.KATA);
            int indexArtinya = cursor.getColumnIndexOrThrow(KamusDatabase.ARTI_NYA);

            kataKata.setText(cursor.getString(indexKata));
            artinya.setText(cursor.getString(indexArtinya));
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.untuk_menu, menu);
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        SearchManager aturPencarian = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView tampilanPencarian = (SearchView) menu.findItem(R.id.cari).getActionView();
        tampilanPencarian.setSearchableInfo(aturPencarian.getSearchableInfo(getComponentName()));
        tampilanPencarian.setIconifiedByDefault(false);
        }
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.cari:
                onSearchRequested();
                return true;
            case android.R.id.home:
                Intent intent = new Intent(this, KamusDigital.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(intent);
                return true;
            default:
                return false;
        }
    }
}


Berikut adalah file yang menyangkut User Interface(UI) termasuk text dan gambar. Semua yang menyangkut UI harus berada dalam folder 'res'. Untuk lebih jelasnya perhatikan gambar 3 berikut ini:
gambar 3
Kalau saat build proses folder-folder yang bernaung di dalam folder res tidak tergenerate, maka silahkan di buat dengan klik kanan pada folder res, New, Folder lalu menamakan folder persis seperti yang terlihat pada gambar 3 di atas. Folder - folder yang kita perlukan di dalam folder res adalah layout, menu, raw, values, xml dan folder drawable berserta versinya
Setelah folder - folder UI tersebut di buka satu persatu maka di dalam setiap folder akan ada file xml seperti terlihat pada gambar 4 berikut ini:
gambar 4

Berikut adalah isi dari file - file xml yang terlihat pada gambar 4 di atas. Silahkan meletakannya ke dalam folder masing - masing.
Didalam folder layout ada 3 buah file xml antara lain:

1. hasil.xml yang isinya sbb:


<?xml version="1.0" encoding="utf-8"?>

<!--

/**

 * Copyright (C) 2013 Vik Sintus Projects

 *

 * Segala kelebihan dan kekurangan di luar tanggung jawab pembuat.

 * Di larang memakai kode ini untuk kepentingan komersial tanpa ijin.

 * Silahkan di pakai untuk kepentingan belajar.

 * vik.sintus@gmail.com

 * http://belajar-android-indonesia.blogspot.com

 * Unless required by applicable law or agreed to in writing, this software

 * is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 *

 */

-->

<!-- ini utk layar hasil pencarian kata dan arti-nya.

 -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

        android:orientation="vertical"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        android:padding="5dp">

    <TextView

            android:id="@+id/kolomKata"

            style="@android:style/TextAppearance.Large"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content" />

    <TextView

            android:id="@+id/kolomArtinya"

            style="@android:style/TextAppearance.Small"

            android:singleLine="true"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content" />

</LinearLayout>



2. kata.xml isinya sbb:


<?xml version="1.0" encoding="utf-8"?>
<!--Copyright (C) 2013 Vik Sintus Projects-->
<!-- ini utk tampilan layar kata2 yang 
     keluar saat ketik pada kotak cari.-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="5dp">
    <TextView
            android:id="@+id/kolomKata"
            android:textSize="35dp"
            android:textColor="?android:textColorPrimary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    <TextView
            android:id="@+id/kolomArtinya"
            android:textSize="18dp"
            android:textColor="?android:textColorSecondary"
            android:paddingTop="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
</LinearLayout>


3. tampilan.xml isinya sbb:

<?xml version="1.0" encoding="utf-8"?>
<!--
/**
 * Copyright (C) 2013 Vik Sintus Projects
 *
 * Segala kelebihan dan kekurangan di luar tanggung jawab pembuat.
 * Di larang memakai kode ini untuk kepentingan komersial tanpa ijin.
 * Silahkan di pakai untuk kepentingan belajar.
 * vik.sintus@gmail.com
 * http://belajar-android-indonesia.blogspot.com
 * Unless required by applicable law or agreed to in writing, this software
 * is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * 
 * 
 */
-->
<!-- ini utk tampilan layar utama. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    <TextView
            android:id="@+id/tulisanMuncul"
            android:textColor="?android:textColorPrimary"
            android:textSize="17dp"
            android:text="@string/instruksi_utama"
            android:background="@android:drawable/title_bar"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
    <ListView
            android:id="@+id/barisDemiBaris"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
</LinearLayout>

Didalam folder menu ada satu buah file yang saya beri nama untuk_menu.xml yang isinya sbb:

<?xml version="1.0" encoding="utf-8"?>
<!--Copyright (C) 2013 Vik Sintus Projects-->

<!-- menu utk cari dan TampilanKata.-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/cari"
          android:title="@string/menu_cari"
          android:icon="@drawable/ic_menu_search"
          android:showAsAction="ifRoom"
          android:actionViewClass="android.widget.SearchView" />
</menu>

Di dalam folder raw adalah memuat isi dari kamus dalam bentuk file .txt.  Di sinilah semua kata dan terjemahan-nya akan di muat, dan saya menamakan file-nya daftar_kata_kata.txt
File ini hanya di buat pakai NotePad dengan format sbb:
abang - big brother
abbey - n. a monastery ruled by an abbot
abide - v. dwell; inhabit or live in
abound - v. be abundant or plentiful; exist in large quantities
absence - n. the state of being absent
absorb - v. assimilate or take in
absurd - j. inconsistent with reason or logic or common sense
abundant - j. present in great quantity
academy - n. a school for special training
accept - v. consider or hold as true
access - v. reach or gain access to
accessible - j. easily obtained
acclaim - n. enthusiastic approval
accommodate - v. provide with something desired or needed
accompany - v. go or travel along with
accomplish - v. to gain with effort
account - v. furnish a justifying analysis or explanation
accusation - n. an assertion that someone is guilty of a fault or offence
accuse - v. blame for, make a claim of wrongdoing or misbehavior against
acid - j. biting, sarcastic, or scornful
acquire - v. come into the possession of something concrete or abstract


Di dalam folder values ada file bernama strings.xml yang isinya sbb:
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2013, Vik Sintus Projects
**
*/
-->
<resources>

    <!-- nama aplikasi. -->
    <string name="nama_aplikasi">Kamus Digital</string>

    <!-- label yg muncul(merek) -->
    <string name="namaLabelNya">KamusDigital</string>

    <!-- tulisan yg muncul pada kotak cari. -->
    <string name="tulisanDiKotakCari">cari kata disini---</string>

    <!-- untuk menu. -->
    <string name="menu_cari">Cari---</string>

    <!-- akan terlihat di search settings utk kode ini.  -->
    <string name="artinya">Arti Kata</string>

    <!-- instruksi pada halaman utama. -->
    <string name="instruksi_utama">Silahkan ketik kata yang mau di cari</string>

    <!-- akan di tunjukan di atas hasil search. -->
    <plurals name="hasil_pencarian">
      <item quantity="one">%1$d result for \"%2$s\": </item>
      <item quantity="other">%1$d results for \"%2$s\": </item>
    </plurals>

    <!-- pesan jikalu pencarian gagal. -->
    <string name="tak_ada_hasil">Tak ada \"%s\" dalam database</string>

</resources>

Di dalam folder xml ada file bernama data_untuk_pencarian.xml isinya sbb:

<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2013, Vik Sintus Projects
*/
-->

<!-- berikut adalah setingan tampang kotak search
     utk info lebih lanjut silahkan lihat
     Developer Guide di
     http://developer.android.com/guide/topics/search/
 -->
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/namaLabelNya"
        android:hint="@string/tulisanDiKotakCari"
        android:searchSettingsDescription="@string/artinya"
        android:searchSuggestAuthority="com.vik_sintus.projects.kamusDigital.PenghubungData"
        android:searchSuggestIntentAction="android.intent.action.VIEW"
        android:searchSuggestIntentData="content://com.vik_sintus.projects.kamusDigital.PenghubungData/kamus"
        android:searchSuggestSelection=" ?"
        android:searchSuggestThreshold="1"
        android:includeInGlobalSearch="true"
        >
 </searchable>

Berikut adalah isi dari AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
 * Copyright (C) 2013 Vik Sintus Projects
 *
 * Segala kelebihan dan kekurangan di luar tanggung jawab pembuat.
 * Di larang memakai kode ini untuk kepentingan komersial tanpa ijin.
 * Silahkan di pakai untuk kepentingan belajar.
 * vik.sintus@gmail.com
 * http://belajar-android-indonesia.blogspot.com
 * Unless required by applicable law or agreed to in writing, this software
 * is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * 
 * 
 */
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.vik_sintus.projects.kamusDigital"
        android:versionCode="2"
        android:versionName="2.0">

    <uses-sdk android:minSdkVersion="11" />

    <application android:label="@string/nama_aplikasi"
                 android:icon="@drawable/ic_dictionary">

        <!-- class utama untuk masuk ke aplikasi. -->
        <activity android:name=".KamusDigital"
                  android:launchMode="singleTop">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <!-- yang menerima pencarian. -->
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
                <!-- kategori tak di perlukan,  karena Intent akan menjelaskan-nya pada
                     komponen pada class ini
                     -->
            </intent-filter>

            <!-- mengarahkan ke  meta data pencarian. -->
            <meta-data android:name="android.app.searchable"
                       android:resource="@xml/data_untuk_pencarian" />

        </activity>

        <!-- menampilkan arti kata. -->
        <activity android:name=".TampilanKata" />

        <!-- menyediakan perkiraan kata2 apa yang kira2 di cari -->
        <provider android:name=".PenghubungData"
                  android:authorities="com.vik_sintus.projects.kamusDigital.PenghubungData" />

        <!-- mengarahkan ke aktivitas cari agar aplikasi menghidupkan kegiatan pencarian. -->
        <meta-data android:name="android.app.default_searchable"
                   android:value=".KamusDigital" />

    </application>
</manifest>

Perhatian: ada kode android:icon="@drawable/ic_dictionary" pada file AndridManifest.xml di atas. Saya curi logo milik google yang bernama ic_dictionary.png silahkan pasang logo sendiri di folder drawable dengan format android:icon="@drawable/namaLogoAnda" tanpa extension
. Maksudnya tak peduli apakah logo anda menggunakan ekstensi jpg, jpeg, gif, png dll. Extension-nya itu jangan di masukan kedalam kode nya.

Bagi yang butuh R.java berikut adalah isinya:

package com.vik_sintus.projects.kamusDigital;

public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int ic_dictionary=0x7f020000;
        public static final int ic_menu_search=0x7f020001;
    }
    public static final class id {
        public static final int barisDemiBaris=0x7f090003;
        public static final int cari=0x7f090004;
        public static final int kolomArtinya=0x7f090001;
        public static final int kolomKata=0x7f090000;
        public static final int tulisanMuncul=0x7f090002;
    }
    public static final class layout {
        public static final int hasil=0x7f030000;
        public static final int kata=0x7f030001;
        public static final int tampilan=0x7f030002;
    }
    public static final class menu {
        public static final int untuk_menu=0x7f080000;
    }
    public static final class plurals {
        /**  akan nampak di atas hasil search. 
         */
        public static final int hasil_pencarian=0x7f070000;
    }
    public static final class raw {
        public static final int daftar_kata_kata=0x7f050000;
    }
    public static final class string {
        /**  akan terlihat di search settings utk kode ini.  
         */
        public static final int artinya=0x7f060004;
        /**  instruksi pada halaman utama. 
         */
        public static final int instruksi_utama=0x7f060005;
        /**  untuk menu. 
         */
        public static final int menu_cari=0x7f060003;
        /**  label yg muncul(merek) 
         */
        public static final int namaLabelNya=0x7f060001;
        /**  nama aplikasi. 
         */
        public static final int nama_aplikasi=0x7f060000;
        /**  Search failure message. 
         */
        public static final int tak_ada_hasil=0x7f060006;
        /**  tulisan yg muncul pada kotak cari. 
         */
        public static final int tulisanDiKotakCari=0x7f060002;
    }
    public static final class xml {
        public static final int data_untuk_pencarian=0x7f040000;
    }
}

PERHATIAN: Seharusnya file R.java di atas tidak boleh di modifikasi. Eclipse bahkan sedikit menolak kalau kita mencoba mengedit-nya. File R.java tergenerate secara otomatis yang penting kita sudah menyusun resource(res) file-nya secara benar


 NOTE: Aplikasi ini bagus untuk honeycomb ke atas

semoga membantu