Android: Menyimpan data di Database SQL

Android menyediakan tiga cara untuk menyimpan data di device. Jika hanya untuk menyimpan sedikit data (beberapa variabel), gunakan shared preferences.  Jika data cukup kompleks dan sering memerlukan pencarian (akses random), gunakan database seperti yang akan dibahas di posting ini. Jika ukuran datanya besar,  tidak perlu pencarian, dapat disimpan di SD card untuk kemudian dibaca komputer, atau memerlukan format yang yang sangat spesifik, gunakan file.

Implementasi database di Android menggunakan SQLite.  SQLite adalah embedded database (hanya menggunakan sekitar 250KB memori) yang menyediakan fasilitas relational DBMS  termasuk SQL.  Referensi lengkap SQLite  dapat dilihat di http://www.sqlite.org/   SQLite tidak hanya digunakan di Android.

Setiap aplikasi memiliki instance database tersendiri, dan berbeda dengan shared preference, tidak disediakan fasilitas agar aplikasi dapat membaca database aplikasi lain. Untuk menggunakan SQLite, sangat dianjurkan menggunakan class helper untuk membuka dan menutup database,  menginisiasi tabel  dst. Helper juga digunakan saat melakukan upgrade struktur database jika suatu saat aplikasi diupdate.  Class helper ini diturunkan dari class SQLiteOpenHelper.

Untuk latihan kita akan membuat aplikasi sederhana yang menyimpan data mahasiswa berupa nama dan nomor telepon.  Pertama kita buat class helper terlebih dulu. Buatlah project Android, tambahkan ke dalam project tersebut satu class. Pastikan superclass kelas ini adalah SQLiteOpenHelper.  Beri nama class ini OpenHelper.

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 *   helper untuk database
 */


public class OpenHelper extends SQLiteOpenHelper
{
    //kalau ini berubah, increment versi database
    public static final int DATABASE_VERSION = 1;
    public static final String DATABASE_NAME = "dbMhs.db";
    public static final String TABLE_CREATE =
            "CREATE TABLE MAHASISWA (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAMA TEXT, TELEPON TEXT)";

    public OpenHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //create database
        db.execSQL(TABLE_CREATE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //jika app diupgrade (diinstall yang baru) maka database akan dicreate ulang (data hilang)
        //jika tidak tidak ingin hilang, bisa diproses disini
        db.execSQL("DROP TABLE IF EXITS MAHASISWA");
    }
}

Selanjutnya kita akan membuat class yang melakukan manipulasi terhadap data (insert, ambil data), beri nama DbMahasiswa. Code DbMahasiwa adalah sebagai berikut:

        import android.content.ContentValues;
        import android.content.Context;
        import android.database.Cursor;
        import android.database.sqlite.SQLiteDatabase;

public class DbMahasiswa {
    public static class Mahasiswa {
        public String nama;
        public String telepon;
    }


    private SQLiteDatabase db;
    private final OpenHelper dbHelper;

    public DbMahasiswa(Context c) {
        dbHelper =  new OpenHelper(c);
    }

    public void open() {
        db = dbHelper.getWritableDatabase();
    }

    public void close() {
        db.close();
    }

    public long insertMahasiswa(String nama, String noTelp) {
        ContentValues newValues = new ContentValues();
        newValues.put("NAMA", nama);
        newValues.put("TELEPON", noTelp);
        return db.insert("MAHASISWA", null, newValues);
    }

   //ambil data mahasiswa berdasarkan nama 
   public Mahasiswa getMahasiswa(String nama) {
        Cursor cur = null;
        Mahasiswa M = new Mahasiswa();

        //kolom yang diambil
        String[] cols = new String [] {"ID", "NAMA", "TELEPON"};
        //parameter, akan mengganti ? pada NAMA=?
        String[] param  = {nama};

        cur = db.query("MAHASISWA",cols,"NAMA=?",param,null,null,null);

        if (cur.getCount()>0) {  //ada data? ambil
            cur.moveToFirst();
            M.nama = cur.getString(1);
            M.telepon = cur.getString(2);
        }

        return M;
    }
}

Setelah kita membuat class helper dan class dbMahasiswa, sekarang kita akan memanfaatkan dua kelas tersebut. Kembali ke activity utama yaitu class MainActivity. Tambahkan kode dibagian onCreate sebagai berikut.

protected void onCreate(Bundle savedInstanceState) {

        .... code oncreate

        //insert mahasiswa
        DbMahasiswa db = new DbMahasiswa(getApplicationContext());
        db.open();
        db.insertMahasiswa("budi","123456");

        //ambil data mahasiswa
        DbMahasiswa.Mahasiswa m = db.getMahasiswa("budi");
        AlertDialog ad = new AlertDialog.Builder(this).create();
        ad.setMessage("nama="+m.nama+"  telp:"+m.telepon);
        ad.show();

    }

Pengambilan lokasi secara terus menerus Menggunakan Google Play Service

Update Feb 2016: Versi terakhir: https://docs.google.com/document/d/1bYU_SdfhicUH3QQnqWhcHbtPRapb7tH1qFU8jmx4jLk/edit?usp=sharing

 

Update 21 Nov 2015: mulai dari Android 6 (API 23),  ijin  ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION menjadi bagian dari Android 6 runtime permission system. Sehingga diberikan bukan lagi saat instalasi, tapi saat runtime. Kode dibawah sudah diupdate untuk ini. Atau alternatifnya, turunkan targetSdkVersion ke bawah 23.

Jika dalam tutorial sebelumnya kita mengambil lokasi terakhir, dalam tutorial ini kita akan membuat app yang secara terus menerus mengambil posisi terakhir dari device. Ini bermanfaat misalnya dalam aplikasi tracking, geofencing, navigasi dan lain-lain.

Seperti pada tutorial sebelumnya, pastikan Google Play Service SDK sudah diinstall dan project menggunakan library Google Play Service. Supaya lebih gampang, gunakan project pada tutorial sebelumnya atau impor.

Ubah permission untuk mengakses lokasi yang paling akurat di AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION">

Tambahkan agar MainActivity mengimplement LocationListener. Hati-hati, pastikan yang diimpor adalah android.gms.location.LocationListener bukan android.location.LocationListener!

import  com.google.android.gms.location.LocationListener; 

public class MainActivity extends AppCompatActivity
       implements
       GoogleApiClient.ConnectionCallbacks,
       GoogleApiClient.OnConnectionFailedListener,
       LocationListener //<--tambahkan ini
{ …

Dengan mengimplement interface LocationListener maka jika ada perubahan lokasi, akan ditangkap oleh activity ini (di method onLocationChanged).

Tambahkan objek Locationrequest dan method untuk mengisi paramater objek tersebut (kode dibawah). LocationRequest berisi berbagai setting untuk mendapatkan update lokasi. Penjelasan tentang isi LocationRequest ada di bawah:


LocationRequest mLocationRequest;

protected void createLocationRequest() {
   mLocationRequest = new LocationRequest();
   mLocationRequest.setInterval(10000); //10 detik
   mLocationRequest.setFastestInterval(5000); //5 detik
   mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}

Method ini dipanggil pada saat onCreate, tambahkan juga penanganan request. Karena Android 6 mewajibkan runtime permission system.

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLatText  =  (TextView) findViewById(R.id.tvLat);
        mLongText =  (TextView) findViewById(R.id.tvLong);
        mWaktuUpdate = (TextView) findViewById(R.id.tvWaktu);

        //cek permission
        //mulai dari Android 6: API 23, persmission dilakukan secara dinamik (tidak diawal lagi saat install)
        //untuk jenis2 persmisson tertentu, termasuk lokasi
        //hati-hati, pastikan yang digunakan adalah ACCESS_FINE_LOCATION, jika salah tidak ada runtime error
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST);

                // MY_PERMISSIONS_REQUEST adalah konstanta, nanti digunakan di  onRequestPermissionsResult

        } else {
            //sudah diijinkan
            ijin = true;
            buildGoogleApiClient();
            createLocationRequest();
            mGoogleApiClient.connect();
        }
    }

 @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {

        if (requestCode == MY_PERMISSIONS_REQUEST) {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                //permission diberikan, mulai ambil lokasi
                buildGoogleApiClient();
                createLocationRequest();
                mGoogleApiClient.connect();
                ijin = true;

            } else {
                //permssion tidak diberikan, tampilkan pesan
                AlertDialog ad = new AlertDialog.Builder(this).create();
                ad.setMessage("Tidak mendapat ijin, tidak dapat mengambil lokasi");
                ad.show();
            }
            return;
        }
    }

Ini penjelasan tentang isi locationrequestm, ada tiga komponen yang perlu diset yaitu interval, fastestinterval dan prioritas. Akurasi lokasi akan ditentukan oleh provider, permission dan opsi yang diminta app. Berikut penjelasannnya:

  1. Interval, menyatakan selang interval yang diinginkan, satuannya milidetik. Jika diset 10000 (10 detik), maka app akan diberi update lokasi device setiap 10 detik sekali. Tapi jika ada beberapa app yang menggunakan google location service, maka interval sesungguhnya dapat lebih pendek lagi, karena untuk efisiensi, jika app lain mendapat update lokasi, app kita akan mendapatkannya juga. Ini dapat membuat app terlalu banyak mendapatkan update (overflow) sehingga menyebabkan user interface berkedip-kedip (flicker).
  2. Untuk mencegah terjadinya overflow, dapat diset fastest interval untuk menyatakan interval tercepat yang akan diikirimkan ke app. Misalnya jika diset 5000 (5 detik), maka paling cepat app akan diupdate setiap 5 detik walaupun sebenarnya dapat lebih cepat.
  3. Prioritas. Terdapat beberapa pilihan. Mulai dari yang prioritas paling tinggi yang paling banyak menghabiskan energi yaitu PRIORITY_HIGH_ACCURACY sampai dengan PRIORITY_NO_POWER yang paling hemat energi. Untuk PRIORITY_NO_POWER, app tidak akan mendapatkan lokasi kecuali jika ada app lain yang meminta lokasi.

Selanjutnya, tambahkan method permintaan untuk medapatkan update lokasi dari FusedLocation, perhatikan penggunaan mLocationRequest yang berisi paramter yang kita inginkan. Parameter ketiga “this” menyatakan bahwa activity ini akan dipanggil setiap ada update lokasi di method onLocationChanged

protected void startLocationUpdates() {
    LocationServices.FusedLocationApi.requestLocationUpdates(
            mGoogleApiClient, mLocationRequest, this);
}

Panggil startLocationUpdate saat onConnected (code bawah). Artinya segera setelah GoolgeApiClient terhubung, maka pengambilan lokasi akan dimulai.

@Override
public void onConnected(Bundle bundle) {
       startLocationUpdates();
}

Selanjutnya buat method yang dipanggil setiap lokasi diganti misalnya dengan merefresh user interface dengan data lokasi terakhir.


@Override
public void onLocationChanged(Location location) {
   mCurrentLocation = location;
   updateUI();  //update tampilan
}

private void updateUI() {
 mLatText.setText("Lat.:"+String.valueOf(mCurrentLocation.getLatitude()));
 mLongText.setText("Lon.:" + String.valueOf(mCurrentLocation.getLongitude()));
}

Saat stop dan pause, update lokasi harus distop untuk menghemat resources, dan baru dihidupkan jika app sudah resume (onResume)


    @Override
    protected void onStart() {
        super.onStart();
        if (ijin) {
            mGoogleApiClient.connect();
        }
    }

    @Override
    protected void onStop() {
        if (ijin) {
            mGoogleApiClient.disconnect();
        }
        super.onStop();
    }

    protected void stopLocationUpdates() {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (ijin) {
            stopLocationUpdates();
        }
    }


    @Override
    public void onResume() {
        super.onResume();
        if (ijin) {
            if (mGoogleApiClient.isConnected()) {
                startLocationUpdates();
            }
        }
    }

Coba jalankan app, maka lokasi akan diupdate setiap 5 sd 10 detik sekali.

Source code lengkap tutorial ini: https://github.com/yudiwbs/LokasiUpdate

Bagian 1: Instalasi SDK Android pada Windows (Android Studio)

Sebelumnya pastikan JDK telah diinstall. Jika belum, Anda dapat mendownloadnya di: [oracle.com]

Untuk membuat app Android, dianjurkan untuk menggunakan Android Studio. Walaupun Eclipse+ADT masih dapat digunakan, tetapi dalam waktu dekat tidak akan disupport lagi oleh Google.

Buka developer.android.com/sdk dan pilih Android Studio Bundle dan install. Proses instalasi selanjutnya membutuhkan koneksi internet. Menggunakan Android Studio lebih nyaman dibandingkan Eclipse, tapi kelemahannya Android Studio membutuhkan koneksi internet yang bagus.

Sebelum membuat project, kita perlu mempersiapkan device untuk mencoba app yang telah dibuat. Android SDK menyediakan emulator device (AVD: Android Virtual Device), tetapi emulator ini menggunakan memori sangat besar dan lambat. Sangat dianjurkan untuk menggunakan device Android yang terhubung melalui USB.

Untuk menghubungkan device, pertama yang harus dilakukan adalah mengaktifkan Developer Options. Buka Settings → System. Jika Developer Options belum ada, bisa diaktifkan dengan masuk ke System → About Phone, scroll ke paling bawah. Lalu tap “Build Number” dengan cepat sebanyak tujuh kali (gambar bawah)

Setelah developer options aktif, kita akan mengaktifkan USB debugging. Di HP, masuk ke Settings → Developer Options. Check dua pilihan: USB Debugging dan “Stay Awake” agar device tidak sleep selama terhubung dengan komputer.

Selanjutnya download USB Driver yang sesuai dengan merk device yang digunakan. Jika sebelumnya device sudah pernah dihubungkan dengan komputer, lakukan update driver secara manual melalui Control Panel → Device Manager.

Selanjutnya anda sudah siap membuat app pertama dengan Android Studio

Bagian 5: ListView

Lanjutan dari tutorial 4 (Widget).

Update Desember 2015:  update tutorial menggunakan Android Studio 1.5. Menggunakan ArrayList agar lebih fleksibel.

List view adalah widget untuk menampilkan data dalam bentuk list yang dapat di-scroll. Karena ukuran layar smartphone terbatas dan cenderung portrait, listview merupakan salah satu widget terpenting dan paling sering digunakan untuk menampilkan kelompok informasi.

ListView dapat berbentuk sederhana sampai kompleks. Beberapa contoh:

5_1

Kita akan mulai dengan membuat list sederhana berisi satu baris text seperti gambar di bawah:

5_5

Pertama, buat project baru dan tambahkan ListView (Listview ada dibagian container)

ScreenHunter_141 Dec. 08 16.22

 

Ganti atribut id listview dengan “listAngka”, caranya dengan men-double klik ListView (Gambar bawah)

ScreenHunter_142 Dec. 08 16.23

 

Lalu di MainActivity.java, tambahkan kode berikut:

public class MainActivity extends AppCompatActivity {

    //menggunakan arrayList akan fleksibel untuk ditambah
    //berisi data yang akan ditampilkan
    private ArrayList<String> items = new ArrayList<>();

    //penghubung antara data dengan listview
    ArrayAdapter adapter;

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

        //inisiasi isi
        items.add("satu");
        items.add("dua");
        items.add("tiga");
        items.add("empat");

        ListView listAngka = (ListView) findViewById(R.id.listAngka);

        //set warna abu2, karena default font adalah putih
        listAngka.setBackgroundColor(Color.LTGRAY);

		/*buat adapter
		3 parameter:
		   - context:
		   - layout listview: disini kita menggunakan yang sudah ada (nantinya bisa custom)
		   - datanya: items
		*/
        adapter = new ArrayAdapter (this,android.R.layout.simple_expandable_list_item_1,items);

        //set adapter ke listview
        listAngka.setAdapter(adapter);
    }

}

Coba jalankan.

Pada code di atas, dibuat adapter yang terhubung dengan array string untuk mengisi list. Sedangkan simple_expandable_list_item1 adalah layout standard yang disediakan Android (panjang ya namanya hehe).

Bagaimana mengupdate isi listview saat program sedang berjalan?

Untuk mengupdate data pada contoh diatas, nilai ArrayList dapat langsung diubah dan setelah selesai panggil method adapter.notifyDataSetChanged()untuk me-refresh tampilan. Sebagai contoh, kita akan membuat button yang saat diklik akan mengubah item pertama dan menambah dua item:

Tambahkan button diatas listview

ScreenHunter_143 Dec. 08 16.35

 

Jangan lupa tambahkan atribut onClick pada button (android:onClick=”klikButton”) dan kode MainActivity.java seperti berikut:

    public void klikButton(View v) {
        //ganti item, maka otomatis tampilkan akan diupdate
        items.set(0,"satu diganti one");

        //tambah item
        items.add("lima");
        items.add("enam");

        //refresh listview
        adapter.notifyDataSetChanged();
    }

Maka hasilnya akan sebagai berikut saat button di tap, baris pertama akan diganti:

screen

Untuk menambahkan aksi saat listview diklik, tambahkan code berikut pada onCreate.

 listAngka.setClickable(true);
 listAngka.setOnItemClickListener( new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
                String isiBaris = (String) listAngka.getItemAtPosition(position);
                String pesan = "Posisi:"+position +"->"+ isiBaris;
                Toast toast = Toast.makeText(getApplicationContext(), pesan, Toast.LENGTH_SHORT);
                toast.show();
            }
        });

Jalankan program, dan jika listview di tap, maka akan muncul toast berisi posisi (baris) dan isi baris.