Academia.eduAcademia.edu

Android Programming

Android Programming Candra Adiputra cbnd Daftar Isi 1 Kalkulator Konversi 1.1 Project . . . . . . 1.2 Layout . . . . . . 1.3 Activity . . . . . 1.4 Running . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 5 9 14 2 Image Viewer 2.1 Project . . 2.2 Layout . . 2.3 Activity . 2.4 Running . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 17 17 19 23 3 Audio Player 3.1 Project . . 3.2 Layout . . 3.3 Activity . 3.4 Running . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 26 26 28 40 4 Web Browser 42 4.1 Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 4.2 Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 i Android Programming - candra.web.id 4.3 4.4 Activity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Running dan Set Permission . . . . . . . . . . . . . . . . . . . 47 5 Map Application 5.1 Google Map API Key . . . 5.2 Project . . . . . . . . . . . . 5.3 Layout . . . . . . . . . . . . 5.4 Uses Permission dan Library 5.5 Activity dan Running . . . . 5.6 Location API . . . . . . . . 6 Kontak Online 6.1 Overview . . . . . . . . . . 6.2 Menyiapkan Server . . . . . 6.2.1 Database . . . . . . 6.2.2 Web Service (PHP + 6.3 Aplikasi Client Android . . 6.3.1 Project . . . . . . . 6.3.2 Layout dan Menu . . 6.3.3 Program . . . . . . . 6.3.4 Permission . . . . . 6.4 Running . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JSON) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 51 52 53 53 54 56 . . . . . . . . . . 63 64 64 64 64 66 66 66 70 96 99 MODUL 1 Kalkulator Konversi Target Gambar 1.1: Kalkulator Konversi 1 Android Programming - candra.web.id 1.1 Project Untuk membuat aplikasi Kalkulator ini, kita perlu membuat Project terlebih dahulu. Langkah langkah untuk membuat Project yakni: • Melalui menu File > New > Android Project. Atau dapat juga melalui Button New yang ada pada Toolbars. Jika Tidak ada, maka pilih Project pada suv menu New, kemudain pada dialog New Project, pilih Android > Android Project. • Pada dialog new Android Project, beri nama Project dengan nama ”Kalkulator Konversi”. Kemudian pilih Next >. Gambar 1.2: Android Project • Pilih build target menjadi Android 2.3.3, Kemudian pilih Next >. • Selanjutnya pada Application Info, isi dengan: 2 Android Programming - candra.web.id Gambar 1.3: Build Target – Application Name: Kalkulator Konversi – Package Name: lab.andro.android.kalkulatorkonversi – Create Activity: KalkulatorKonversiActivity – Minimum SDK: 10 Kemudian klik Finish. 3 Android Programming - candra.web.id Gambar 1.4: Application Info Project Overview Setelah Project berhasil dibuat, secara otomatis framework aplikasi Android Anda akan digenerate (dapat anda lihat pada gambar 1.5 dibawah). Beberapa hal penting yang perlu Anda perhatikan dari project ini diantaranya yakni: • src berisi source code Java untuk Program. • gen berisi file-file yang digenerate otomatis oleh SDK. Penting: Jangan mengubah file-file yang ada di dalamnya, karena akan secara otomatis di ubah oleh SDK. • res Berisi file-file resource yang dibutuhkan aplikasi. Seperti file gambar, audio, layout, theme dan lainnya. 4 Android Programming - candra.web.id Gambar 1.5: Kalkulator Konversi • AndroidManifest.xml Berisi konfigurasi Activity aplikasi dan perizinan akses aplikasi terhadap system. 1.2 Layout Tampilan aplikasi Android diatur menggunakan Layout. Sebuah aplikasi Android, dapat menggunakan lebih dari satu layout untuk dapat berinteraksi dengan user. Layout-layout ini dapat dibuat dengan menggunakan XML. Anda tidak perlu khawatir jika Anda belum terlalu paham dengan XML, karena plugin ADT yang terinstall pada Eclipse telah disertai dengan Layout Editor untuk memudahkan kita dalam membuat Layout ini. Setiap kali Project baru dibuat, sebuah layout akan digenerate oleh SDK. Layout ini terletak dalam direktory res/layout dengan nama main.xml. Gambar 1.6 dibawah ini adalah contoh Layout main.xml yang dibuka dengan Layout Editor. 5 Android Programming - candra.web.id Gambar 1.6: Layout Editor Ada dua mode yang bisa digunakan untuk membuat layout melalui Layout Editor ini yakni dengan menggunakan mode Grafis atau mode XML. Pada mode Grafis telah disediakan Pallete yang didalamnya terdapat Widgetwidget yang dapat digunakan pada aplikasi. Untuk aplikasi Kalkulator ini kita akan mencoba membuat layout dengan menggunakan mode grafis. Berikut langkah-langkahnya: 1. Buka layout main (main.xml). 2. Hapus Text widget yang telah ada (bertuliskan ”Hello World, KalkulatorKonversiActivity!” pada layout). 3. Tambahkan beberapa widget berikut secara berurutan: (a) TextView (berada pada pallete Form Widgets), (b) EditText (berada pada pallete Text Field, bila perlu pilih EditText dengan format Number), (c) RadioGroup (berada pada pallete Form Widgets), dan (d) Button (berada pada pallete Form Widgets). 6 Android Programming - candra.web.id Gambar 1.7: Layout yang telah diubah 4. Selanjutnya, kita perlu mengubah property masing-masing widget yang telah kita tambahkan pada layout. Ada beberapa cara untuk mengubah propertynya yakni dengan cara meng-klik kanan pada widget tersebut, kemudian pilih sub-menu yang merepresentasikan propertynya. Atau dengan cara mengubahnya langsung pada file XML-nya dengan memasuki mode XML Editor. Untuk lebih memudahkan pemahaman, kita akan mengubah propertinya melalui XML editornya. Masuk ke mode XML editor dengan mengklik tab main.xml yang berada persis dibawah editor layout. Kemudian Ubah property masing-masing Widget yang ada menjadi: 1 2 3 4 5 6 7 8 9 10 11 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Nilai" /> 7 Android Programming - candra.web.id 12 13 14 15 16 17 18 19 <EditText android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:inputType="numberDecimal" > <requestFocus /> </EditText> 20 21 22 23 24 25 26 27 28 29 30 <RadioGroup android:id="@+id/radioGroup1" android:layout_width="match_parent" android:layout_height="wrap_content" > <RadioButton android:id="@+id/radio0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="Meter ke Feet" /> 31 32 33 34 35 36 <RadioButton android:id="@+id/radio1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Feet ke Meter" /> 37 38 39 40 41 42 43 <RadioButton android:id="@+id/radio2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RadioButton" /> </RadioGroup> 44 45 46 47 48 49 <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Proses" /> 50 51 </LinearLayout> 8 Android Programming - candra.web.id Catatan: Ubah bagian yang dicetak biru dan hapus bagian yang dicetak merah. Sehingga jika layout dilihat pada mode Grafik akan terlihat seperti gambar 1.8 di bawah ini. Gambar 1.8: Layout Jadi 1.3 Activity Untuk menggunakan layout dan menambahkan logika program ke dalamnya kita perlu membuatkan Activity untuk layout tersebut. Pada program pertama ini, kita akan menggunakan Activity yang telah kita buat saat pembuatan project yang kita beri nama KalkulatorKonversiActivity. Activity ini berada dalam file KalkulatorKonversiActivity.java yang berada di dalam direktory src > lab.andro.android.kalkulatorkonversi. Buka file tersebut untuk mengubahnya. 9 Android Programming - candra.web.id package lab.andro.android.kalkulatorkonversi; 1 2 import android.app.Activity; import android.os.Bundle; 3 4 5 public class KalkulatorKonversiActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } } 6 7 8 9 10 11 12 13 Atur layout agar menggunakan layout main.xml –pada activity utama yang digenerate pada saat pembuatan Project, layout akan langsung di set ke main.xml. Selanjutnya kita perlu menambahkan logika program ke dalamnya. Skenario aplikasinya yakni: • User memasukkan input berupa angka ke dalam Text Field, • Kemudian user memilih jenis konversi Meter ke Feet atau Feet ke Meter, pilihan default adalah Meter ke Feet (1 meter = 3.2808399 feet). • Ketika user menekan button ”Proses”, program akan mengkalkulasi angka yang dimasukkan pada text field sesuai dengan pilihan modenya. Berikut adalah langkah-langkahnya: a. Tambahkan beberapa baris kode berikut pada Activity KalkulatorKonversiActivity sebelum methode onCreate: 4 ... 5 6 7 8 9 10 public class KalkulatorKonversiActivity extends Activity { /** Called when the activity is first created. */ private EditText etAngka; private RadioButton rbMeterFeet; private Button btnProses; 11 12 @Override 10 Android Programming - candra.web.id 13 14 ... public void onCreate(Bundle savedInstanceState) { b. Kemudian tekan tombol Ctrl+Shift+O untuk melakukan import kelas secara otomatis. c. Selanjutnya, pada methode onCreate, link-kan semua Objek etAngka, rbMeterFeet dan btnProses dengan komponen Widget yang ada pada Layout. Caranya: 11 ... 12 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); 13 14 15 16 17 18 19 20 21 22 23 ... } etAngka = (EditText) findViewById(R.id.editText1); rbMeterFeet = (RadioButton) findViewById(R.id.radio0); rbMeterFeet.setChecked(true); btnProses = (Button) findViewById(R.id.button1); d. Atur event onCLickListener pada Button btnProses agar dapat menghandle event ketika button ti klik: 20 ... btnProses = (Button) findViewById(R.id.button1); 21 22 23 24 25 26 27 28 29 30 ... } btnProses.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { kalkulasi(); } }); Jangan lupa untuk menekan kombinasi tombol Ctrl+Shift+O. e. Tambahkan methode kalkulasi() setelah methode onCreate: 11 Android Programming - candra.web.id 30 ... 31 32 public void kalkulasi() { double meter = 3.2808399; 33 double angka = 0; try { angka = Double.parseDouble( etAngka.getText().toString()); } catch (Exception e) { Toast.makeText(this, "Masukkan Angka", Toast.LENGTH_LONG).show(); } 34 35 36 37 38 39 40 41 42 String hasil; if(rbMeterFeet.isChecked()) { hasil = angka + " Meter = " + (angka * meter) + " Feet"; } else { hasil = angka + " Feet = " + (angka / meter) + " Meter"; } 43 44 45 46 47 48 49 50 51 AlertDialog.Builder ab = new AlertDialog.Builder(this); ab.setTitle("Hasil"); ab.setMessage(hasil); ab.setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 } } AlertDialog dialog = ab.create(); dialog.show(); Keterangan: Toast digunakan untuk menampilkan notifikasi pada layar. Sedangkan AlertDialog.Builder dan AlertDialog digunakan untuk membuat Alert dialog, dimana nati hasil 12 Android Programming - candra.web.id kalkulasi akan ditampilkan ke dalam dialog ini. Full Source: ✞ 1 package lab. andro . android . kalkulatorkonversi ; 2 3 4 5 6 7 8 9 10 11 import import import import import import import import import android .app. Activity ; android .app. AlertDialog ; android . content . DialogInterface ; android .os. Bundle ; android .view.View; android . widget . Button ; android . widget . EditText ; android . widget . RadioButton ; android . widget . Toast ; 12 13 14 15 16 17 public class KalkulatorKonversiActivity extends Activity { /** Called when the activity is first created . */ private EditText etAngka ; private RadioButton rbMeterFeet ; private Button btnProses ; 18 19 20 21 22 @Override public void onCreate ( Bundle savedInstanceState ) { super . onCreate ( savedInstanceState ); setContentView (R. layout .main); 23 24 25 26 27 etAngka = ( EditText ) findViewById (R.id. editText1 ); rbMeterFeet = ( RadioButton ) findViewById (R.id. radio0 ); rbMeterFeet . setChecked (true); btnProses = ( Button ) findViewById (R.id. button1 ); 28 29 30 31 32 33 34 btnProses . setOnClickListener (new View. OnClickListener () { public void onClick (View v) { kalkulasi (); } }); } 35 36 37 public void kalkulasi () { double meter = 3.2808399; 38 39 40 41 42 43 44 double angka = 0; try { angka = Double . parseDouble ( etAngka . getText (). toString ()); } catch ( Exception e) { Toast . makeText (this , " Masukkan Angka ", 13 Android Programming - candra.web.id 45 } 46 Toast . LENGTH_LONG ).show (); 47 String hasil ; if( rbMeterFeet . isChecked ()) { hasil = angka + " Meter = " + (angka * meter ) + " Feet"; } else { hasil = angka + " Feet = " + (angka / meter ) + " Meter "; } 48 49 50 51 52 53 54 55 56 AlertDialog . Builder ab = new AlertDialog . Builder (this); ab. setTitle ("Hasil"); ab. setMessage ( hasil ); ab. setPositiveButton ("Ok", new DialogInterface . OnClickListener () { public void onClick ( DialogInterface dialog , int which ) { dialog . dismiss (); } }); 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 } ✝ } AlertDialog dialog = ab. create (); dialog .show (); KalkulatorKonversiActivity.java Setelah semua ditambahkan, simpan perubahan. Pastikan semua kelas yang perlu di-import telah diimport. 1.4 Running Sebelum dapat menjalankan program, pastikan terlebih dahulu Anda telam membuat Virtual Device android dengan versi 2.3.3 (Api 10) atau versi setelahnya (untuk pembuatan AVD, lihat Appendix). Atau jika Anda memiliki perangkat handset Android, Anda dapat menggunakannya sebagai tempat uji coba program dengan menghubungkannya melalui USB. Ada beberapa cara untuk menjalankan program, Pertama dengan menekan kombinasi tombol Ctrl+F11 atau melalui menu Run > Run atau dengan menekan Button Run pada toolbar. Gambar 1.9 di bawah ini adalah gambar dialog run saat pertama kali menjalankan aplikasi. 14 ✆ Android Programming - candra.web.id Gambar 1.9: Run As –Pilih Android Application Contoh hasil Running aplikasi yang telah jadi: Gambar 1.10: Hasil Running Aplikasi 15 MODUL 2 Image Viewer Target Gambar 2.1: Image Viewer 16 Android Programming - candra.web.id 2.1 Project Pada modul ini kita akan mencoba membuat aplikasi untuk mengolah gambar dengan resource gambar berasal dari SD Card. Selain menampilkan Gambar, pada modul ini kita juga akan mencoba menggunakan dan memanggil Aplikasi built-in Android dari dalam aplikasi kita. Untuk mencobanya, kita perlu membuat sebuah Project baru. Buat sebuah Project baru dengan konfigurasi Project sebagai berikut: • Project name:Image Viewer • Build target: Api 10 • Application name: Image Viewer • Package name: lab.andro.android.imageviewer • Create Activity: ImageViewerActivity • Minimum SDK: 10 2.2 Layout Setelah Project dibuat, selanjutnya kita perlu mengubah layout main.xml yang telah ada. Tambahkan beberapa Widget secara berurutan beserta propertynya yakni: a. Button (berada pada pallete Form Widgets) • id= ”@+id/button1” • text= ”Buka Gambar” • layout_width= ”match_parent” b. ImageView (berada pada pallete Images & Media) Pada saat menambahkan akan dikonfirmasi mengenai gabar yang akan digunakan. Pilih saja gambar Icon yang ada (ic_launcher). • id=”@+id/imageView1” • layout_width= ”match_parent” • layout_height= ”match_parent” 17 Android Programming - candra.web.id Kurang lebih layout akan terlihat seperti gambar 2.2 di bawah ini. Gambar 2.2: Layout Dengan isi file main.xml menjadi: ✞ 1 <?xml version ="1.0" encoding ="utf -8"?> 2 <LinearLayout xmlns:android =" http: // schemas . android .com/apk/res/ android " 3 android:layout_width =" fill_parent " 4 android:layout_height =" fill_parent " 5 android:orientation =" vertical " > 6 7 8 9 10 11 <Button android:id ="@+id/ button1 " android:layout_width =" match_parent " android:layout_height =" wrap_content " android:text ="Buka Gambar " /> 12 18 Android Programming - candra.web.id <ImageView android:id ="@+id/ imageView1 " android:layout_width =" match_parent " android:layout_height =" match_parent " android:src =" @drawable / ic_launcher " /> 13 14 15 16 17 18 19 </ LinearLayout > ✝ main.xml Kemudian simpan perubahan pada layout. 2.3 Activity Setelah layout selesai dibuat, selanjutnya kita perlu mengimplementasikan logika program ke dalam Activitynya. Skenarionya yakni: • Ketika user menekan button ”Buka Gambar” user akan masuk ke galeri Gambar yang ada pada Handset Android. • Gambar yang dipilih oleh user pada galeri, akan ditampilkan dibawah button ”Buka Gambar”. Berdasarkan skenario tersebut, kita akan membutuhkan Activity lain yakni Activity Galery. Activity galery yang akan kita gunakan adalah acitivity galery built-in dari Android. Sehingga kita tidak perlu repot-repot untuk membuat Activity baru yang serupa. Untuk mengimplementasikan skenario tersebut, berikut adalah langkahlangkahnya: a. Buka Activity ImageViewerActivity, kemudian tambahkan beberapa property berikut: 7 8 9 10 11 12 ... public class ImageViewerActivity extends Activity { public static final int _PILIH_GAMBAR = 1; private Button btnBuka; private ImageView ivGambar; ... Jangn lupa untuk menekan tombol Ctrl+Shift+O untuk mengimport kelas secara otomatis. 19 ✆ Android Programming - candra.web.id b. Selanjutnya pada methode onCreate, linkan btnBuka dan ivGambar dengan widget-widget yang ada pada layout: 12 13 14 15 16 17 18 19 ... @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btnBuka = (Button) findViewById(R.id.button1); ivGambar = (ImageView) findViewById(R.id.imageView1); ... c. Buat handler untuk menghandle event Klik pada Button btnBuka di dalam methode onCreate: 19 20 ... btnBuka.setOnClickListener(new View.OnClickListener() { 21 22 23 24 25 26 }); ... public void onClick(View v) { bukaGambar(); } d. Tambahkan methode bukaGambar ke dalam activity: 30 31 32 33 34 35 36 37 ... private void bukaGambar() { Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images .Media.EXTERNAL_CONTENT_URI); startActivityForResult(i, _PILIH_GAMBAR); } ... e. Dan yang terakhir, tambahkan Override methode onActivityResult untuk menghandle ketika user memilih gambar dari galeri: 37 38 39 ... @Override protected void onActivityResult(int requestCode, 20 Android Programming - candra.web.id int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); 40 41 42 switch (requestCode) { case _PILIH_GAMBAR: if(resultCode == RESULT_OK){ Uri gambarTerpilih = data.getData(); InputStream gbrStream = null; try { gbrStream = getContentResolver() .openInputStream(gambarTerpilih); } catch (FileNotFoundException e) { e.printStackTrace(); return; } Bitmap bitGambar = BitmapFactory .decodeStream(gbrStream); ivGambar.setImageBitmap(bitGambar); } 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 break; 60 61 62 63 64 } ... 65 66 default: break; } f. Sehingga, source untuk activity ini menjadi: 1 ✞ package lab. andro . android . imageviewer ; 2 3 4 import java.io. FileNotFoundException ; import java.io. InputStream ; 5 6 7 8 9 10 11 12 13 import import import import import import import import android .app. Activity ; android . content . Intent ; android . graphics . Bitmap ; android . graphics . BitmapFactory ; android .net.Uri; android .os. Bundle ; android .view.View; android . widget . Button ; 21 Android Programming - candra.web.id 14 import android . widget . ImageView ; 15 16 17 18 19 public class ImageViewerActivity extends Activity { public static final int _PILIH_GAMBAR = 1; private Button btnBuka ; private ImageView ivGambar ; 20 21 22 23 24 25 26 @Override public void onCreate ( Bundle savedInstanceState ) { super. onCreate ( savedInstanceState ); setContentView (R. layout .main); btnBuka = ( Button ) findViewById (R.id. button1 ); ivGambar = ( ImageView ) findViewById (R.id. imageView1 ); 27 btnBuka . setOnClickListener (new View. OnClickListener () { 28 29 30 31 32 33 34 } public void onClick (View v) { bukaGambar (); } }); 35 36 37 38 39 40 41 private void bukaGambar () { Intent i = new Intent ( Intent . ACTION_PICK , android . provider . MediaStore . Images . Media . EXTERNAL_CONTENT_URI ); startActivityForResult (i, _PILIH_GAMBAR ); } 42 43 44 45 @Override protected void onActivityResult (int requestCode , int resultCode , Intent data) { super. onActivityResult ( requestCode , resultCode , data); 46 47 48 49 50 51 52 53 54 55 56 57 58 59 switch ( requestCode ) { case _PILIH_GAMBAR : if( resultCode == RESULT_OK ){ Uri gambarTerpilih = data. getData (); InputStream gbrStream = null; try { gbrStream = getContentResolver (). openInputStream ( gambarTerpilih ); } catch ( FileNotFoundException e) { e. printStackTrace (); return ; } Bitmap bitGambar = BitmapFactory . decodeStream ( gbrStream ); ivGambar . setImageBitmap ( bitGambar ); 22 Android Programming - candra.web.id } 60 61 break; 62 63 64 65 66 67 68 } ✝ } default : break; } ImageViewerActivity.java g. Simpan semua perubahan. 2.4 Running Sebelum mencoba menjalankan aplikasi Image Viewer ini, kita perlu menambahkan file gambar ke dalam SD-Card emulator terlebih dahulu. Untuk menambahkan file gambar ini caranya yakni: • Jalankan emulator yang akan digunakan untuk menguji aplikasi. • Setelah emulator berhasil dijalankan dan system Android nya berjalan sempurna, buka perspective DDMS pada Eclipse, melalui menu Window > Open Perspective > DDMS. • Pada DDMS, buka tab File Explorer. • Untuk menyimpan ke dalam SD-Card, masuk ke direktory mnt > sdcard. Pilih direktory sdcard kemudian klik button berlogo HP yang ada persis di pojok kanan-atas list direktory pada tab tersebut. Sebagai contoh lihat Gambar 2.3. • Kemudian pilih file gambar yang akan di-upload ke dalam emulator. • Setelah file berhasil di-upload, pada beberapa kasus kadang kita harus merestart emulator untuk dapat melihat hasilnya. 23 ✆ Android Programming - candra.web.id Gambar 2.3: File Explorer Setelah file gambar berhasil di-upload ke emulator, selanjutnya tinggal menguji coba Aplikasi Image viewer kita ini. Contoh hasil Run program: Gambar 2.4: Hasil Run aplikasi Image Viewer 24 MODUL 3 Audio Player Target Gambar 3.1: Target: Music Player 25 Android Programming - candra.web.id 3.1 Project Pada modul ini kita akan mencoba membuat aplikasi Music Player. Pada aplikasi ini, kita akan mencoba kontrol-kontrol sederhana media player untuk dapat menjalankan music seperti play, pause dan resume. Untuk mencobanya, kita perlu membuat sebuah project baru, dengan konfigurasi sebagai berikut: • Project name:Music Player • Build target: Api 10 • Application name: Music Player • Package name: lab.andro.android.musicplayer • Create Activity: MusicPlayerActivity • Minimum SDK: 10 3.2 Layout Buat layout sederhana, untuk media player ini. Pada layout ini kita akan mengggunakan RelativeLayout untuk membuat tampilan yang menarik dan lebih flexible. (Tips: Untuk membuat layout ini sebaiknya menggunakan mode XML, karena akan terasa lebih mudah dibandingkan dengan mode grafis) Buat layout sebagai berikut: ✞ <?xml version ="1.0" encoding ="utf -8"?> 2 <RelativeLayout xmlns:android ="http: // schemas . android .com/apk/ res/ android " 3 android:layout_width =" fill_parent " 4 android:layout_height =" fill_parent " > 1 5 6 7 8 9 10 11 12 <ImageButton android:id ="@+id/ imageButtonAdd " android:layout_width =" wrap_content " android:layout_height =" wrap_content " android:layout_alignParentBottom ="true" android:layout_alignTop ="@+id/ imageButtonPlay " android:src =" @android:drawable / ic_input_add " /> 13 14 <ImageButton 26 Android Programming - candra.web.id 15 16 17 18 19 20 android:id ="@+id/ imageButtonPlay " android:layout_width =" wrap_content " android:layout_height =" wrap_content " android:layout_alignParentBottom ="true" android:layout_toRightOf ="@+id/ imageButtonAdd " android:src =" @android:drawable / ic_media_play " /> 21 22 23 24 25 26 27 <SeekBar android:id ="@+id/ seekBar1 " android:layout_width =" match_parent " android:layout_height =" wrap_content " android:layout_alignTop ="@+id/ imageButtonPlay " android:layout_toRightOf ="@+id/ imageButtonPlay " /> 28 29 30 31 32 33 34 35 36 <TextView android:id ="@+id/ textView1 " android:layout_width =" wrap_content " android:layout_height =" wrap_content " android:layout_above ="@+id/ imageButtonAdd " android:layout_alignParentLeft ="true" android:layout_alignParentRight ="true" android:text =" TextView " /> 37 38 39 40 41 42 43 44 45 46 <ImageView android:id ="@+id/ imageView1 " android:layout_width =" wrap_content " android:layout_height =" wrap_content " android:layout_above ="@+id/ textView1 " android:layout_alignParentLeft ="true" android:layout_alignParentRight ="true" android:layout_alignParentTop ="true" android:src =" @android:drawable / divider_horizontal_dark " /> 47 48 </ RelativeLayout > ✝ Layout main.xml Catatan: Semua gambar atau icon yang digunakan pada widget ImageButton, menggunakan icon yang ada dalam SDK. Anda bisa menggantinya dengan icon atau gambar sendiri yang di taruh di dalam direktory res > drawable. Jika layout ditampilkan dari mode grafis, maka akan terlihat seperti Gambar 3.2 di bawah ini. 27 ✆ Android Programming - candra.web.id Gambar 3.2: Layout main.xml dengan menggunakan RelativeLayout 3.3 Activity Selanjutnya kita perlu mengubah Activity MusicPlayerActivity. Skenario aplikasi Music Player ini yakni: • User memilih file dari dalam galeri Music dengan mengklik button bergambar ”plus”. • Setelah file dipilih, User baru bisa menjalankan filenya dengan menekan Button ”Play”. • Ketika music sedang berjalan, seek bar akan ter-update secara otomatis, Button play berubah menjadi button ”Pause”, jika file musicnya memiliki Cover Art maka Cover Art-nya akan ditampilkan dalam Image View dan Informasi file Music akan ditampilkan di TextView yang terletak dibawah ImageView. • User dapat men-seek music ke posisi tertentu dengan mengklik pada seekbar. 28 Android Programming - candra.web.id Untuk mengimplementasikan skenario program diatas, mari kita tambahkan beberapa perubahan pada Activity MusicPlayerActivity. a. Tambahkan beberapa Property berikut: ... private private private private private private private private private private private private ... static final int _BUKA_GALERY = 1; MediaPlayer mPlayer; ImageButton ibPlay; ImageView ivGambar; SeekBar sbProgress; TextView tvFileInfo; ImageButton btn; Uri uriFile; Uri lastUri; MediaMetadataRetriever mRetriever; boolean played; final Handler handler = new Handler(); b. Pada methode onCreate, linkkan semua widget yang telah dibuat di atas dengan widget yang ada dalam layout. Serta implementasikan semua objek (selain Widget) yang telah dideklarasikan di atas. ... ... ibPlay = (ImageButton) findViewById(R.id.imageButtonPlay); ibPlay.setEnabled(false); ivGambar = (ImageView) findViewById(R.id.imageView1); sbProgress = (SeekBar) findViewById(R.id.seekBar1); tvFileInfo = (TextView) findViewById(R.id.textView1); btn = (ImageButton) findViewById(R.id.imageButtonAdd); mRetriever = new MediaMetadataRetriever(); mPlayer = new MediaPlayer(); played = false; c. Atur Listener untuk event-event onClickListener pada button, onTouch pada SeekBar dan onCompleteListener untuk objek MediaPlayer. 29 Android Programming - candra.web.id ... btn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { bukaFile(); } }); ibPlay.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { playPause(); } }); mPlayer.setOnCompletionListener( new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { played = false; ibPlay.setImageResource( android.R.drawable.ic_media_play); } }); sbProgress.setOnTouchListener( new View.OnTouchListener() { ... public boolean onTouch(View v, MotionEvent event) { seekChange(v); return false; } }); d. Implementasikan methode seekChange(View v): ... protected void seekChange(View v) { if (mPlayer.isPlaying()) { SeekBar sb = (SeekBar) v; mPlayer.seekTo(sb.getProgress()); } 30 Android Programming - candra.web.id } ... e. Implementasikan methode bukaFile(): ... private void bukaFile() { Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore .Audio.Media.EXTERNAL_CONTENT_URI); startActivityForResult(i, _BUKA_GALERY); } ... f. Tambahkan Overide Methode onActivityResult untuk mengambil uri dari file yang dipilih pada Galeri. ... @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case _BUKA_GALERY: if (resultCode == RESULT_OK) { Uri file = data.getData(); setFile(file); } break; } ... default: break; } g. Tambahkan methode setFile(Uri file): ... private void setFile(Uri file) { 31 Android Programming - candra.web.id } ... uriFile = file; ibPlay.setEnabled(true); h. Buat methode untuk menjalankan thread yang bertugas untuk mengupdate SeekBar. ... public void startPlayProgressUpdater() { sbProgress.setProgress(mPlayer.getCurrentPosition()); if (mPlayer.isPlaying()) { Runnable notifikasi = new Runnable() { public void run() { startPlayProgressUpdater(); } }; handler.postDelayed(notifikasi, 1000); } else { mPlayer.pause(); ibPlay.setImageResource( android.R.drawable.ic_media_play); } } ... i. Buat methode playPause(): ... private void playPause() { ... } ... j. Pada methode playPause, tambahkan kode untuk mengecek status MediaPlayer mPlayer dan uri dari file yang akan dimainkan: ... if (played && lastUri == uriFile) { mPlayer.pause(); ibPlay.setImageResource( 32 Android Programming - candra.web.id android.R.drawable.ic_media_play); played = false; return; } else if (!played && lastUri == uriFile) { mPlayer.start(); ibPlay.setImageResource( android.R.drawable.ic_media_pause); played = true; startPlayProgressUpdater(); return; } ... if (lastUri != uriFile) { if (played) { mPlayer.stop(); } mPlayer.reset(); played = false; ibPlay.setImageResource( android.R.drawable.ic_media_play); } Pengecekan dilakukan agar tidak terjadi kesalahan logika saat menjalankan media player. k. Implementasikan kode untuk mengontrol objek MediaPlayer pada methode ini, serta beberapa kode untuk mendapatkan informasi mengenai file Audio yang dijalankan (Title, Artist, Cover Art dan lainnya): ... try { mPlayer.setDataSource(this, uriFile); mPlayer.prepare(); mPlayer.start(); played = true; lastUri = uriFile; mRetriever.setDataSource(this, uriFile); String judul = mRetriever 33 Android Programming - candra.web.id .extractMetadata( MediaMetadataRetriever .METADATA_KEY_TITLE); String artist = mRetriever .extractMetadata( MediaMetadataRetriever .METADATA_KEY_ARTIST); tvFileInfo.setText(artist + " - " + judul); byte[] albumArt = mRetriever.getEmbeddedPicture(); if (albumArt != null) { Bitmap artwork = BitmapFactory.decodeByteArray( albumArt, 0, albumArt.length); ivGambar.setImageBitmap(artwork); } else { ivGambar.setImageResource( R.drawable.ic_launcher); } ibPlay.setImageResource( android.R.drawable.ic_media_pause); sbProgress.setMax(mPlayer.getDuration()); sbProgress.setProgress(0); startPlayProgressUpdater(); ... } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "Gagal membuka file", Toast.LENGTH_LONG) .show(); } 34 Android Programming - candra.web.id Keterangan: kode program: 1 2 3 4 5 6 7 8 9 mRetriever.setDataSource(this, uriFile); String judul = mRetriever .extractMetadata( MediaMetadataRetriever .METADATA_KEY_TITLE); String artist = mRetriever .extractMetadata( MediaMetadataRetriever .METADATA_KEY_ARTIST); 10 11 tvFileInfo.setText(artist + " - " + judul); 12 13 14 15 16 17 18 19 20 21 22 byte[] albumArt = mRetriever.getEmbeddedPicture(); if (albumArt != null) { Bitmap artwork = BitmapFactory.decodeByteArray( albumArt, 0, albumArt.length); ivGambar.setImageBitmap(artwork); } else { ivGambar.setImageResource( R.drawable.ic_launcher); } 23 24 25 ibPlay.setImageResource( android.R.drawable.ic_media_pause); Digunakan untuk mendapatkan informasi dari file Audio. Dengan menggunakan objek dari MediaMetadataRetriever, kita dapat mengambil metadata file mengenai Title (MediaMetadataRetriever.METADATA_KEY_TITLE), Artist dan lainnya. Sedangkan untuk mengambil Cover Art dengan memanfaatkan methode getEmbeddedPicture dari objek MediaMetadataRetriever. Namun embedded picture ini masih bertype byte, sehingga perlu dikonversi menjadi bitmap terlebih dahulu. l. Sehingga keseluruhan kode program akan menjadi: 1 ✞ package lab. andro . android . musicplayer ; 2 3 4 5 import java.io. IOException ; import android .app. Activity ; import android . content . Intent ; 35 Android Programming - candra.web.id 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import import import import import import import import import import import import import import android . graphics . Bitmap ; android . graphics . BitmapFactory ; android . media . MediaMetadataRetriever ; android . media . MediaPlayer ; android .net.Uri; android .os. Bundle ; android .os. Handler ; android .view. MotionEvent ; android .view.View; android . widget . ImageButton ; android . widget . ImageView ; android . widget . SeekBar ; android . widget . TextView ; android . widget . Toast ; 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class MusicPlayerActivity extends Activity { private static final int _BUKA_GALERY = 1; private MediaPlayer mPlayer ; private ImageButton ibPlay ; private ImageView ivGambar ; private SeekBar sbProgress ; private TextView tvFileInfo ; private ImageButton btn; private Uri uriFile ; private Uri lastUri ; private MediaMetadataRetriever mRetriever ; private boolean played ; private final Handler handler = new Handler (); 34 35 36 37 38 39 /** Called when the activity is first created . */ @Override public void onCreate ( Bundle savedInstanceState ) { super. onCreate ( savedInstanceState ); setContentView (R. layout .main); 40 41 42 43 44 45 46 47 ibPlay = ( ImageButton ) findViewById (R.id. imageButtonPlay ); ibPlay . setEnabled (false ); ivGambar = ( ImageView ) findViewById (R.id. imageView1 ); sbProgress = ( SeekBar ) findViewById (R.id. seekBar1 ); tvFileInfo = ( TextView ) findViewById (R.id. textView1 ); btn = ( ImageButton ) findViewById (R.id. imageButtonAdd ); mRetriever = new MediaMetadataRetriever (); 48 49 50 mPlayer = new MediaPlayer (); played = false ; 51 52 53 54 btn. setOnClickListener (new View. OnClickListener () { public void onClick (View v) { bukaFile (); 36 Android Programming - candra.web.id } }); 55 56 57 ibPlay . setOnClickListener (new View. OnClickListener () { public void onClick (View v) { playPause (); } }); 58 59 60 61 62 63 mPlayer . setOnCompletionListener (new MediaPlayer . OnCompletionListener () { public void onCompletion ( MediaPlayer mp) { played = false ; ibPlay . setImageResource ( android .R. drawable . ic_media_play ); } }); 64 65 66 67 68 69 70 sbProgress . setOnTouchListener (new View. OnTouchListener () { 71 72 public boolean onTouch (View v, MotionEvent event ) { seekChange (v); return false; } }); 73 74 75 76 77 78 79 } 80 81 82 83 84 85 86 protected void seekChange (View v) { if ( mPlayer . isPlaying ()) { SeekBar sb = ( SeekBar ) v; mPlayer . seekTo (sb. getProgress ()); } } 87 88 private void playPause () { 89 90 91 92 93 94 95 96 97 98 99 100 101 if ( played && lastUri == uriFile ) { mPlayer . pause (); ibPlay . setImageResource ( android .R. drawable . ic_media_play ); played = false; return ; } else if (! played && lastUri == uriFile ) { mPlayer . start (); ibPlay . setImageResource ( android .R. drawable . ic_media_pause ); played = true; startPlayProgressUpdater (); 37 Android Programming - candra.web.id 102 103 } return ; 104 105 106 107 108 109 110 111 112 113 if ( lastUri != uriFile ) { if ( played ) { mPlayer .stop (); } mPlayer . reset (); played = false; ibPlay . setImageResource ( android .R. drawable . ic_media_play ); } 114 115 try { 116 117 118 119 120 121 mPlayer . setDataSource (this , uriFile ); mPlayer . prepare (); mPlayer . start (); played = true; lastUri = uriFile ; 122 123 124 125 126 127 128 129 130 131 mRetriever . setDataSource (this , uriFile ); String judul = mRetriever . extractMetadata ( MediaMetadataRetriever . METADATA_KEY_TITLE ); String artist = mRetriever . extractMetadata ( MediaMetadataRetriever . METADATA_KEY_ARTIST ); 132 133 tvFileInfo . setText ( artist + " - " + judul ); 134 135 136 137 138 139 140 141 142 143 144 byte [] albumArt = mRetriever . getEmbeddedPicture (); if ( albumArt != null) { Bitmap artwork = BitmapFactory . decodeByteArray ( albumArt , 0, albumArt . length ); ivGambar . setImageBitmap ( artwork ); } else { ivGambar . setImageResource ( R. drawable . ic_launcher ); } 145 146 147 ibPlay . setImageResource ( android .R. drawable . ic_media_pause ); 148 149 150 sbProgress . setMax ( mPlayer . getDuration ()); sbProgress . setProgress (0); 38 Android Programming - candra.web.id startPlayProgressUpdater (); 151 152 } catch ( IllegalArgumentException e) { e. printStackTrace (); } catch ( SecurityException e) { e. printStackTrace (); } catch ( IllegalStateException e) { e. printStackTrace (); } catch ( IOException e) { e. printStackTrace (); Toast . makeText (this , "Gagal membuka file", Toast . LENGTH_LONG ) .show (); } 153 154 155 156 157 158 159 160 161 162 163 164 165 166 } 167 168 169 170 171 172 173 private void bukaFile () { Intent i = new Intent ( Intent . ACTION_PICK , android . provider . MediaStore . Audio . Media . EXTERNAL_CONTENT_URI ); startActivityForResult (i, _BUKA_GALERY ); } 174 175 176 177 178 @Override protected void onActivityResult (int requestCode , int resultCode , Intent data) { super. onActivityResult ( requestCode , resultCode , data); 179 switch ( requestCode ) { case _BUKA_GALERY : if ( resultCode == RESULT_OK ) { Uri file = data. getData (); setFile (file); } break; 180 181 182 183 184 185 186 187 188 189 190 191 } default : break; } 192 193 194 195 196 private void setFile (Uri file) { uriFile = file; ibPlay . setEnabled (true); } 197 198 199 public void startPlayProgressUpdater () { sbProgress . setProgress ( mPlayer . getCurrentPosition ()); 39 Android Programming - candra.web.id 200 201 202 203 204 205 206 207 208 209 210 211 212 213 } ✝ } if ( mPlayer . isPlaying ()) { Runnable notifikasi = new Runnable () { public void run () { startPlayProgressUpdater (); } }; handler . postDelayed ( notifikasi , 1000) ; } else { mPlayer . pause (); ibPlay . setImageResource ( android .R. drawable . ic_media_play ); } Activity MusicPlayerActivity 3.4 Running Setelah semua methode diimplementasikan, sekarang kita perlu mencoba Aplikasi ini. Namun sebelumnya kita perlu mengupload beberapa file Music ke dalam emulator. Caranya dapat Anda baca kembali pada modul sebelumnya. Berikut adalah contoh running aplikasi MusicPlayer yang telah kita buat di atas: 40 ✆ Android Programming - candra.web.id Gambar 3.3: Hasil akhir aplikasi 41 MODUL 4 Web Browser Target Gambar 4.1: Target Aplikasi: Web Browser 42 Android Programming - candra.web.id 4.1 Project Pada modul ini kita akan mencoba membuat aplikasi Music Player. Pada aplikasi ini, kita akan mencoba kontrol-kontrol sederhana media player untuk dapat menjalankan music seperti play, pause dan resume. Untuk mencobanya, kita perlu membuat sebuah project baru, dengan konfigurasi sebagai berikut: • Project name:Web Browser • Build target: Api 10 • Application name: Web Browser • Package name: lab.andro.web.browser • Create Activity: WebBrowserActivity • Minimum SDK: 10 4.2 Layout Setelah Project dibuat, selanjutnya kita perlu mengubah layout main.xml yang telah ada. Tambahkan beberapa Widget secara berurutan beserta propertynya yakni: • Ubah orientasi LinearLayout yang telah ada menjadi vertikal, • Tambahkan sebuah Linier Layout dengan orientasi ”horizontal” kemudian isi dengan beberapa widget berikut beserta propertynya: – EditText id=”@+id/editText1” – Button id=”@+id/button1” layout width=”80dip” layout height=”wrap_content” text=”Go” 43 Android Programming - candra.web.id • Tambahkan widget WebView dibawah LinearLayout yang telah ditambahkan pada point sebelumnya dengan property: id=”@+id/webView1” layout width=”match_parent” layout height=”match_parent” Sehingga layout menjadi: Gambar 4.2: Layout Dengan kode XML sebagai berikut: ✞ 1 <?xml version ="1.0" encoding ="utf -8"?> 2 <LinearLayout xmlns:android =" http: // schemas . android .com/apk/res/ android " 3 android:layout_width =" fill_parent " 4 android:layout_height =" fill_parent " 5 android:orientation =" vertical " > 6 7 8 9 10 <LinearLayout android:id ="@+id/ linearLayout1 " android:layout_width =" match_parent " android:layout_height =" wrap_content " > 11 44 Android Programming - candra.web.id 12 13 14 15 16 <EditText android:id ="@+id/ editText1 " android:layout_width =" wrap_content " android:layout_height =" wrap_content " android:layout_weight ="1" > 17 18 19 <requestFocus /> </ EditText > 20 21 22 23 24 25 26 <Button android:id ="@+id/ button1 " android:layout_width ="80 dip" android:layout_height =" wrap_content " android:text ="Go" /> </ LinearLayout > 27 28 29 30 31 <WebView android:id ="@+id/ webView1 " android:layout_width =" match_parent " android:layout_height =" match_parent " /> 32 33 </ LinearLayout > ✝ Layout main.xml ✆ 4.3 Activity Setelah Layout dibuat, selanjutnya kita perlu mengubah activity WebBrowserActivity. 1. Tambahkan beberapa property berikut: ... private EditText etAddress; private Button btnGoToAddr; private WebView webView; ... 2. Pada methode onCreate, link-kan semua objek widget di atas dengan widgetnya yang ada di layout: ... etAddress = (EditText) findViewById(R.id.editText1); btnGoToAddr = (Button) findViewById(R.id.button1); 45 Android Programming - candra.web.id ... webView = (WebView) findViewById(R.id.webView1); 3. Set web client untuk webView agar web dapat ditampilkan melalui widget web view yang ada pada layout: ... ... webView.setWebViewClient(new WebViewClient()); 4. Set listener on Click untuk button Go: ... ... btnGoToAddr.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { String addr = etAddress.getText().toString(); webView.loadUrl(addr); } }); 5. Sehingga akan menjadi: 1 ✞ package lab. andro .web. browser ; 2 3 4 5 6 7 8 9 import import import import import import import android .app. Activity ; android .os. Bundle ; android .view.View; android . webkit . WebView ; android . webkit . WebViewClient ; android . widget . Button ; android . widget . EditText ; 10 11 12 13 14 15 16 17 18 19 public class WebBrowserActivity extends Activity { /** Called when the activity is first created . */ private EditText etAddress ; private Button btnGoToAddr ; private WebView webView ; @Override public void onCreate ( Bundle savedInstanceState ) { super. onCreate ( savedInstanceState ); setContentView (R. layout .main); 20 46 Android Programming - candra.web.id etAddress = ( EditText ) findViewById (R.id. editText1 ); btnGoToAddr = ( Button ) findViewById (R.id. button1 ); webView = ( WebView ) findViewById (R.id. webView1 ); webView . setWebViewClient (new WebViewClient ()); 21 22 23 24 25 btnGoToAddr . setOnClickListener (new View. OnClickListener () { 26 27 28 29 30 31 32 33 34 } ✝ public void onClick (View v) { String addr = etAddress . getText (). toString (); webView . loadUrl (addr); } }); } Activity: WebBrowserActivity 4.4 Running dan Set Permission Setelah semua kode kita implementasikan, program belum dapat dijalankan langsung. Karena butuh perizinan untuk menggunakan koneksi Internet. Jika dijalankan tanpa mengatur perizinannya, maka ketika dijalankan akan terlihat seperti pada gambar 4.3. Gambar 4.3: Web Browser 47 ✆ Android Programming - candra.web.id Untuk menanggulangi masalah ini, buka file AndroidManifest.xml yang berada pada root project. Kemudian Tambahkan satu baris kode berikut di luar tag application.: ... <uses-permission android:name="android.permission.INTERNET"/> ... Sehingga menjadi: ✞ 1 <?xml version ="1.0" encoding ="utf -8"?> 2 <manifest xmlns:android =" http: // schemas . android .com/apk/res/ android " 3 package ="lab. andro .web. browser " 4 android:versionCode ="1" 5 android:versionName ="1.0" > 6 7 8 <uses -sdk android:minSdkVersion ="10" /> <uses - permission android:name =" android . permission . INTERNET "/ > 9 10 11 12 13 14 15 16 17 <application android:icon =" @drawable / ic_launcher " android:label =" @string / app_name " > <activity android:label =" @string / app_name " android:name =". WebBrowserActivity " > <intent - filter > <action android:name =" android . intent . action .MAIN " /> 18 19 20 21 22 <category android:name =" android . intent . category . LAUNCHER " /> </intent - filter > </ activity > </ application > 23 24 </ manifest > ✝ Activity: WebBrowserActivity Kemudian jalankan kembali program. Jika tidak ada masalah, maka hasilnya akan menjadi: 48 ✆ Android Programming - candra.web.id Gambar 4.4: Hasil Running Aplikasi Web Browser 49 MODUL 5 Map Application Target Gambar 5.1: Target 50 Android Programming - candra.web.id 5.1 Google Map API Key Sebelum kita membuat project, pertama kita mengenerate API key untuk Aplikasi kita. Sebagai catatan, API key yang digunakan pada komputer yang berbeda akan berbeda juga. Untuk mendapatkan Google Map API key, langkah-langkahnya yakni: a. Buka terminal (Untuk Linux atau Mac) atau Command Prompt (untuk Windows). Sebelumnya pastikan PATH ke binary/executable jre telah di setting terlebih dahulu agar binary keytool dapat di eksekusi. b. Melalui Terminal ketikkan perintak berikut: $ keytool -list -keystore KEYSTORE -v Ganti KEYSTORE dengan lokasi debug.keystore yang ada pada komputer Anda masing-masing. • Windows Vista: C:\Users\<user>\.android\debug.keystore} • Windows XP: C:\Documents and Settings\<user>\.android\debug.keystore • OS X and Linux: ~/.android/debug.keystore Contoh hasilnya: Enter keystore password: ***************** WARNING WARNING WARNING ***************** * The integrity of the information stored in your keystore * * has NOT been verified! In order to verify its integrity, * * you must provide your keystore password. * ***************** WARNING WARNING WARNING ***************** Keystore type: JKS Keystore provider: SUN Your keystore contains 1 entry 51 Android Programming - candra.web.id Alias name: androiddebugkey Creation date: Apr 14, 2012 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Android Debug, O=Android, C=US Issuer: CN=Android Debug, O=Android, C=US Serial number: 1a95b440 Valid from: Sat Apr 14 17:09:12 WIT 2012 until: Mon Apr 07 ... Certificate fingerprints: MD5: 99:8D:B7:9D:14:A6:EE:48:33:0C:7B:AF:41:62:CD:10 SHA1: E9:D6:F2:56:AE:F0:D9:63:D6:73:93:42:E9:BE:5B:E1:... SHA256: C7:47:AA:0E:DC:72:08:B0:24:F5:CB:C9:2C:F1:81:72:... Signature algorithm name: SHA256withRSA Version: 3 ... c. Ambil MD5 dari fingerprint keystore tersebut (dicetak biru pada contoh di atas). d. Buka browser, kemudian masuk ke alamat: https://developers.google.com/android/maps-api-signup e. Masukkan MD5 fingerprint tadi, kemudian klik ”Generate API Key”. Untuk sementara simpan API key yang Anda dapatkan untuk digunakan nanti pada program. 5.2 Project Buat Project Android baru dengan konfigurasi sebagai Berikut: • Project name:Petaku • Build target: Api 7 • Application name: Petaku • Package name: lab.andro.petaku • Create Activity: PetakuActivity • Minimum SDK: 7 52 Android Programming - candra.web.id 5.3 Layout Setelah Project berhasil dibuat, selanjutnya kita perlu mengubah Layout aplikasi agar dapat menggunakan Map. Buka layout main.xml, kemudian ubah menjadi: <?xml version="1.0" encoding="utf-8"?> <com.google.android.maps.MapView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/mapview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:apiKey="API_KEY" /> Kemudian ganti API_KEY dengan API Key yang telah didapatkan pada bagian 5.1 di atas. Misalnya: android:apiKey="0zEcmwFgGjgueJd8BWFmQBUy2DEagV6RxjnSQ3w" 5.4 Uses Permission dan Library Menggunakan Google Map membutuhkan koneksi internet. Sehingga kita perlu memberikan permission untuk dapat menggunakan INTERNET untuk aplikasi kita. Selain Internet, kita juga membutuhkan beberapa Akses permission lainnya yakni ACCESS_COARSE_LOCATION dan ACCESS_FINE_LOCATION untuk dapat menggunakan GPS. Buka file AndroidManifest.xml kemudian tambahkan baris berikut diluar tag application: <uses-permission android:name= "android.permission.INTERNET" /> <uses-permission android:name= "android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name= "android.permission.ACCESS_FINE_LOCATION" /> Selain itu, kita juga perlu menambahkan akses ke library external untuk dapat menggunakan MapView. Tambahkan baris berikut di dalam tag application: 53 Android Programming - candra.web.id <uses-library android:name="com.google.android.maps" /> Sehingga file AndroidManifest.xml akan menjadi: ✞ 1 <?xml version ="1.0" encoding ="utf -8"?> 2 <manifest xmlns:android =" http: // schemas . android .com/apk/res/ android " 3 package ="lab. andro . android . petaku " 4 android:versionCode ="1" 5 android:versionName ="1.0" > 6 7 <uses -sdk android:minSdkVersion ="7" /> 8 9 10 11 <uses - permission android:name =" android . permission . INTERNET " /> <uses - permission android:name =" android . permission . ACCESS_COARSE_LOCATION " /> <uses - permission android:name =" android . permission . ACCESS_FINE_LOCATION " /> 12 13 14 15 16 17 18 19 20 <application android:icon =" @drawable / ic_launcher " android:label =" @string / app_name " > <activity android:name =". PetakuActivity " android:label =" @string / app_name " > <intent - filter > <action android:name =" android . intent . action .MAIN " /> 21 22 23 24 <category android:name =" android . intent . category . LAUNCHER " /> </intent - filter > </ activity > 25 26 27 <uses - library android:name ="com. google . android .maps" /> </ application > 28 29 </ manifest > ✝ AndroidManifest.xml 5.5 Activity dan Running Selanjutnya kita perlu mengubah Activity PetakuActivity untuk dapat menggunakan MapView pada aplikasi. Buka Activity PetakuActivity kemudian lakukan perubahan berikut: 54 ✆ Android Programming - candra.web.id a. Tambahkan baris import berikut untuk mengimport MapActivity: import com.google.android.maps.MapActivity; b. Ubah activity yang tadinya merupakan turunan dari kelas Activity menjadi MapActivity: ... public class PetakuActivity extends MapActivity { ... c. Implement semua methode yang belum di implementasikan dari kelas MapActivity (seharusnya hanay satu methode saja): ... @Override protected boolean isRouteDisplayed() { return false; } ... d. Sehingga Activity menjadi: 1 ✞ package lab. andro . android . petaku ; 2 3 4 import android .os. Bundle ; import com. google . android .maps. MapActivity ; 5 6 7 8 9 10 11 12 public class PetakuActivity extends MapActivity { /** Called when the activity is first created . */ @Override public void onCreate ( Bundle savedInstanceState ) { super. onCreate ( savedInstanceState ); setContentView (R. layout .main); } 13 14 15 16 17 18 19 } ✝ @Override protected boolean isRouteDisplayed () { // TODO Auto - generated method stub return false; } Activity: PetakuActivity 55 ✆ Android Programming - candra.web.id e. Selanjutnya coba run program untuk mencoba apakah Map berhasil di load dengan baik atau tidak. Contoh hasil Run programnya yakni: Gambar 5.2: Petaku 5.6 Location API Untuk dapat menggunakan Location API agar kita dapat mengakses Lokasi, ada beberapa hal yang perlu kita tambahkan dalam program, yakni: a. Implements LocationListener pada kelas/activity PetakuActivity. ... public class PetakuActivity extends MapActivity implements LocationListener { ... b. Implementasikan semua methode yang belum diimplementasikan dari kelas LocationListener (Biarkan methode-methode tersebut kososng terlebih dahulu): 56 Android Programming - candra.web.id ... public void onLocationChanged(Location arg0) { } public void onProviderDisabled(String provider) { } public void onProviderEnabled(String provider) { } public void onStatusChanged(String provider, int status, Bundle extras) { } ... c. Tambahkan beberapa property berikut: ... private private private private ... LocationManager locationManager; MapView petaView; MyLocationOverlay myLocationOverlay; String provider; d. Pada methode onCreate, tambahkan beberapa baris berikut untuk menginisialisasi Lokasi: ... locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Criteria criteria = new Criteria(); provider = locationManager.getBestProvider(criteria, false); Location location = locationManager .getLastKnownLocation(provider); 57 Android Programming - candra.web.id ... if(location == null) { Toast.makeText(this, "Lokasi tidak diperoleh", Toast.LENGTH_LONG).show(); } e. Setelah itu tambahkan baris berikut setelah inisialisasi Lokasi, untuk mengontrol Map dan menambahkan overlay: ... ... petaView = (MapView) findViewById(R.id.mapview); petaView.displayZoomControls(true); petaView.setBuiltInZoomControls(true); petaView.getController().setZoom(10); myLocationOverlay = new MyLocationOverlay(this, petaView); myLocationOverlay.enableCompass(); petaView.getOverlays().add(myLocationOverlay); myLocationOverlay.runOnFirstFix(new Runnable() { public void run() { petaView.getController().animateTo( myLocationOverlay.getMyLocation()); } }); f. Pada methode onLocationChanged, tambahkan baris berikut agar setiap kali lokasi berubah, maka peta akan secara otomatis mengarah ke lokasi tersebut: petaView.getController().animateTo( myLocationOverlay.getMyLocation()); g. Optional: Overide methode onResume dan onPause: ... @Override protected void onResume() { super.onResume(); locationManager.requestLocationUpdates(provider, 58 Android Programming - candra.web.id } 400, 1, this); myLocationOverlay.enableCompass(); myLocationOverlay.enableMyLocation(); @Override protected void onPause() { locationManager.removeUpdates(this); myLocationOverlay.disableCompass(); myLocationOverlay.disableMyLocation(); super.onPause(); } ... h. Source lengkap untuk Activity PetakuActivity: ✞ 1 package lab. andro . android . petaku ; 2 3 4 5 6 7 8 9 import import import import import import import android . content . Context ; android . location . Criteria ; android . location . Location ; android . location . LocationListener ; android . location . LocationManager ; android .os. Bundle ; android . widget . Toast ; 10 11 12 13 import com. google . android .maps. MapActivity ; import com. google . android .maps. MapView ; import com. google . android .maps. MyLocationOverlay ; 14 15 16 17 18 19 public class PetakuActivity extends MapActivity implements LocationListener { private LocationManager locationManager ; private MapView petaView ; private MyLocationOverlay myLocationOverlay ; private String provider ; 20 21 22 23 24 @Override public void onCreate ( Bundle savedInstanceState ) { super. onCreate ( savedInstanceState ); setContentView (R. layout .main); 25 26 27 locationManager = ( LocationManager ) getSystemService ( Context . LOCATION_SERVICE ); 28 29 Criteria criteria = new Criteria (); 59 Android Programming - candra.web.id provider = locationManager . getBestProvider (criteria , false ); Location location = locationManager . getLastKnownLocation ( provider ); 30 31 32 if( location == null) { Toast . makeText (this , " Lokasi tidak diperoleh ", Toast . LENGTH_LONG ).show (); } 33 34 35 36 37 38 petaView = ( MapView ) findViewById (R.id. mapview ); petaView . displayZoomControls (true); petaView . setBuiltInZoomControls (true); 39 40 41 42 petaView . getController (). setZoom (10); 43 44 45 46 47 48 49 50 51 52 53 } 54 myLocationOverlay = new MyLocationOverlay (this , petaView ); myLocationOverlay . enableCompass (); petaView . getOverlays ().add( myLocationOverlay ); myLocationOverlay . runOnFirstFix (new Runnable () { public void run () { petaView . getController (). animateTo ( myLocationOverlay . getMyLocation ()); } }); 55 56 57 58 59 @Override protected boolean isRouteDisplayed () { return false; } 60 61 62 63 public void onLocationChanged ( Location arg0) { petaView . getController (). animateTo ( myLocationOverlay . getMyLocation ()); 64 65 } 66 67 public void onProviderDisabled ( String provider ) { 68 69 } 70 71 public void onProviderEnabled ( String provider ) { 72 73 } 74 75 public void onStatusChanged ( String provider , int status , 60 Android Programming - candra.web.id Bundle extras ) { 76 } 77 78 @Override protected void onResume () { super. onResume (); locationManager . requestLocationUpdates (provider , 400, 1, this); myLocationOverlay . enableCompass (); myLocationOverlay . enableMyLocation (); } 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 } ✝ @Override protected void onPause () { locationManager . removeUpdates (this); myLocationOverlay . disableCompass (); myLocationOverlay . disableMyLocation (); super. onPause (); } Activity: PetakuActivity i. Simpan perubahan dan coba run Program. Berikut adalah contoh hasil running aplikasi Petaku ini: Gambar 5.3: Hasil Akhir 61 ✆ Interfacing Web Services 62 MODUL 6 Kontak Online Target Gambar 6.1: Target 63 Android Programming - candra.web.id 6.1 Overview Pada modul terakhir ini kita akan mencoba mambuat Aplikasi sederhana yang melakukan akses ke database server. Idenya mirip seperti Aplikasi Notepad yang ada pada Android, akan tetapi pada contoh ini data akan disimpan ke dalam server. Beberapa hal yang perlu kita siapkan sebelum mebuat aplikasi Androidnya yakni: • Database Server (MySQL, PostgreSQL atau lainnya), • Web Server (Apache, XAMPP atau lainnya) dan • PHP, untuk membuat aplikasi web servicenya. 6.2 Menyiapkan Server 6.2.1 Database Siapkan Database sederhana dengan nama ”kontak” yang berisi sebuah tabel dengan nama ”kontakku”. Beri empat buah field dalam tabel kontakku yakni id, nama, alamat dan flag (flag untuk memberikan pada tanda). CREATE TABLE kontakku ( id int(11) NOT NULL AUTO_INCREMENT, nama varchar(255) NOT NULL, alamat text NOT NULL, flag enum('normal','penting') NOT NULL DEFAULT 'normal', PRIMARY KEY (id) ); 6.2.2 Web Service (PHP + JSON) Buat sebuah tiga buah file PHP sederhana untuk mengakses database yakni: • koneksi.php ✞ 1 2 3 <?php $link = mysql_connect ('localhost ', 'root ', 'lupa '); mysql_select_db (" kontak "); 64 Android Programming - candra.web.id 4 5 6 7 ?> if (! $link) { die('Could not connect : ' . mysql_error ()); } ✝ koneksi.php ✆ • get-kontak.php ✞ 1 <? 2 3 include ('koneksi .php '); $query =" SELECT * FROM kontakku "; 4 $result = pg_query ( $query ) or die('Query failed : ' . pg_last_error ()); 5 6 7 8 9 10 11 12 ?> $data= array (); while ($r = pg_fetch_array ($result , null , PGSQL_ASSOC )) { $data [] = $r; } echo json_encode ($data); ✝ get-kontak.php • insert-kontak.php ✞ 1 2 3 4 5 <? include ('koneksi .php '); $nama= $_POST ['nama ']; $alamat = $_POST ['alamat ']; $flag= $_POST ['flag ']; 6 7 8 $query =" INSERT INTO kontakku (nama ,alamat ,flag) VALUES (' $nama ', '$alamat ', '$flag ')"; 9 10 11 12 13 14 $result = pg_query ( $query ) or die('Query failed : ' . pg_last_error ()); if( $result ) { echo 1; } else { echo 0; 65 ✆ Android Programming - candra.web.id 15 16 ?> } ✝ insert-kontak.php Catatan: Untuk keperluan service Delete dan Update, Anda dapat mengembangkannya sendiri nanti setelah anda dapat membuat sebuah interface untuk masing-masing service yang ada di atas. 6.3 Aplikasi Client Android 6.3.1 Project Buat project Android dengan konfigurasi sebagai berikut: • Project name: Kontak Online • Build target: Api 10 (atau lainnya) • Application name: Kontak Online • Package name: lab.andro.android.kontakonline • Create Activity: KontakOnlineActivity • Minimum SDK: 10 (sesuaikan dengan build target). 6.3.2 Layout dan Menu Pada aplikasi ini, kita akan membuat beberapa Layout. Yakni layout utama yang berisikan ListView, layout item untuk mengganti item dalam list view dan layout untuk membuat Kontak. Mari kita siapkan satu persatu semua layout ini. • Layout Utama (main.xml) ✞ 1 2 3 4 5 <?xml version ="1.0" encoding ="utf -8"?> <LinearLayout xmlns:android =" http: // schemas . android . com/apk/res/ android " android:layout_width =" fill_parent " android:layout_height =" fill_parent " android:orientation =" vertical "> 66 ✆ Android Programming - candra.web.id 6 7 8 9 10 11 <ListView android:id =" @android:id /list" android:layout_width =" match_parent " android:layout_height =" wrap_content " > </ ListView > </ LinearLayout > ✝ ✆ main.xml Catatan: Property android:id pada widget ListView harus berisi "@android:id/list". • Layout untuk item (item_kontak.xml) dalam List View pada main.xml ✞ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?xml version ="1.0" encoding ="utf -8"?> <LinearLayout xmlns:android =" http: // schemas . android . com/apk/res/ android " android:layout_width =" match_parent " android:layout_height =" match_parent " android:orientation =" vertical " > <RelativeLayout android:layout_width =" match_parent " android:layout_height =" wrap_content " > <TextView android:id ="@+id/ textNama " android:layout_width =" wrap_content " android:layout_height =" wrap_content " android:layout_alignParentLeft ="true" android:layout_alignParentTop ="true" android:text ="Large Text" android:textAppearance ="? android:attr / textAppearanceLarge " /> <ImageView android:id ="@+id/ imageFlag " android:layout_alignParentRight ="true" android:layout_width =" wrap_content " android:layout_height =" wrap_content " android:layout_alignParentTop ="true" android:src =" @android:drawable / star_big_on " /> </ RelativeLayout > </ LinearLayout > ✝ item_kontak.xml 67 ✆ Android Programming - candra.web.id • Layout untuk membuat Kontak (kontak_baru.xml) ✞ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 <?xml version ="1.0" encoding ="utf -8"?> <RelativeLayout xmlns:android =" http: // schemas . android . com/apk/res/ android " android:layout_width =" match_parent " android:layout_height =" match_parent " android:orientation =" vertical " > <TextView android:id ="@+id/ textView1 " android:layout_width =" wrap_content " android:layout_height =" wrap_content " android:layout_alignParentTop ="true" android:layout_alignParentRight ="true" android:layout_alignParentLeft ="true" android:text =" Nama: " android:textAppearance ="? android:attr / textAppearanceMedium " /> <EditText android:id ="@+id/ editTextNama " android:layout_width =" match_parent " android:layout_height =" wrap_content " android:singleLine ="true" android:layout_alignParentRight ="true" android:layout_alignParentLeft ="true" android:layout_below ="@+id/ textView1 " android:ems ="10" > <requestFocus /> </ EditText > <TextView android:id ="@+id/ textView2 " android:layout_width =" wrap_content " android:layout_height =" wrap_content " android:text =" Alamat: " android:layout_alignParentRight ="true" android:layout_alignParentLeft ="true" android:layout_below ="@+id/ editTextNama " android:textAppearance ="? android:attr / textAppearanceMedium " /> <EditText android:id ="@+id/ editTextAlamat " android:layout_width =" match_parent " android:layout_height =" wrap_content " android:layout_above ="@+id/ checkBoxPenting " 68 Android Programming - candra.web.id 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 android:layout_alignParentLeft ="true" android:layout_alignParentRight ="true" android:layout_below ="@+id/ textView2 " android:gravity ="top" android:autoText ="false " android:ems ="10" /> <CheckBox android:id ="@+id/ checkBoxPenting " android:layout_width =" wrap_content " android:layout_height =" wrap_content " android:layout_alignParentRight ="true" android:layout_alignParentLeft ="true" android:layout_alignParentBottom ="true" android:text =" Penting " /> </ RelativeLayout > ✝ kontak_baru.xml Dan kita juga membutuhkan dua buah file XML lagi untuk membuat menu. Cara pembuatan menu ini sama seperti pembuatan Layout baru, akan tetapi pilih Resource Type-nya menjadi Menu. Berikut beberapa menu yang perlu dibuat: • Menu utama (menu_utama.xml) untuk menu pada Activity utama: ✞ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?xml version ="1.0" encoding ="utf -8"?> <menu xmlns:android =" http: // schemas . android .com/apk/ res/ android " > <item android:id ="@+id/ menuKontakBaru " android:icon =" @android:drawable / ic_menu_add " android:title =" Tambah Kontak "> </item > <item android:id ="@+id/ menuAbout " android:icon =" @android:drawable / ic_menu_help " android:title =" About "> </item > <item android:id ="@+id/ menuRefresh " android:icon =" @android:drawable / ic_menu_rotate " android:title =" Refresh "> </item > 69 ✆ Android Programming - candra.web.id 18 </menu > ✝ menu_utama.xml ✆ • Menu simpan (menu_simpan.xml) untuk menu pada Activity BuatKontakBaru: ✞ 1 2 3 4 5 6 7 8 <?xml version ="1.0" encoding ="utf -8"?> <menu xmlns:android =" http: // schemas . android .com/apk/ res/ android " > <item android:id ="@+id/ menuSimpan " android:icon =" @android:drawable / ic_menu_save " android:title =" Simpan "> </item > </menu > ✝ menu_simpan.xml 6.3.3 Program Setelah layout selesai dibuat, selanjutnya kita perlu menambahkan kode ke dalam program. Ada beberapa hal yang perlu kita tambahkan ke dalam program selain Activity utama yang telah di buat pada saat pembuatan Project yakni: kelas CustomHTTPClient untuk memudahkan akses HTTP (Socket Programming –Topik Advance), kelas Kontak dan dua buah Activity lain yakni KontakBaruActivity dan BacaKontakActivity. Mari kita tambahkan satu-persatu. HTTP Client (CustomHTTPClient.java) Buat sebuah kelas baru pada package lab.andro.android.kontakonline dengan nama CustomHTTPClient kemudian isi dengan koe-kode beikut: ✞ 1 package lab.andro. android . kontakonline ; 2 3 4 5 6 7 import import import import import java.io. BufferedReader ; java.io. IOException ; java.io. InputStreamReader ; java.net.URI; java.util. ArrayList ; 8 9 import org. apache .http. HttpResponse ; 70 ✆ Android Programming - candra.web.id 10 11 12 13 14 15 16 17 18 import import import import import import import import import org. apache .http. client . HttpClient ; org. apache .http. client . entity . UrlEncodedFormEntity ; org. apache .http. client . methods . HttpGet ; org. apache .http. client . methods . HttpPost ; org. apache .http.conn. params . ConnManagerParams ; org. apache .http.impl. client . DefaultHttpClient ; org. apache .http. params . HttpConnectionParams ; org. apache .http. params . HttpParams ; org. apache .http. params . HttpProtocolParams ; 19 20 21 22 public class CustomHTTPClient { public static final int HTTP_TIMEOUT = 30 * 1000; private static HttpClient mHttpClient ; 23 24 25 26 27 28 29 30 31 32 33 34 private static HttpClient getHttpClient () { if ( mHttpClient == null) { mHttpClient = new DefaultHttpClient (); final HttpParams params = mHttpClient . getParams (); HttpConnectionParams . setConnectionTimeout (params , HTTP_TIMEOUT ); HttpConnectionParams . setSoTimeout (params , HTTP_TIMEOUT ); HttpProtocolParams . setUseExpectContinue ( mHttpClient . getParams (), false ); ConnManagerParams . setTimeout (params , HTTP_TIMEOUT ); } return mHttpClient ; } 35 36 37 38 39 40 41 42 43 44 45 @SuppressWarnings ({ " unchecked ", " rawtypes " }) public static String executeHttpPost ( String url , ArrayList postParameters ) throws Exception { BufferedReader in = null; try { HttpClient client = getHttpClient (); HttpPost request = new HttpPost (url); UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity ( postParameters ); request . setEntity ( formEntity ); HttpResponse response = client . execute ( request ); in = new BufferedReader (new InputStreamReader ( response . getEntity (). getContent ())); 46 71 Android Programming - candra.web.id StringBuffer sb = new StringBuffer (""); String line = ""; String NL = System . getProperty ("line. separator "); while (( line = in. readLine ()) != null) { sb. append (line + NL); } in.close (); 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 } String result = sb. toString (); return result ; } finally { if (in != null) { try { in.close (); } catch ( IOException e) { e. printStackTrace (); } } } 67 68 69 70 71 72 73 74 75 public static String executeHttpGet ( String url) throws Exception { BufferedReader in = null; try { HttpClient client = getHttpClient (); HttpGet request = new HttpGet (); request . setURI (new URI(url)); HttpResponse response = client . execute ( request ); in = new BufferedReader (new InputStreamReader ( response . getEntity (). getContent ())); 76 77 78 79 80 81 82 83 StringBuffer sb = new StringBuffer (""); String line = ""; String NL = System . getProperty ("line. separator "); while (( line = in. readLine ()) != null) { sb. append (line + NL); } in.close (); 84 85 86 87 String result = sb. toString (); return result ; } finally { 72 Android Programming - candra.web.id 88 89 90 91 92 93 94 95 96 97 } } } if (in != null) { try { in.close (); } catch ( IOException e) { e. printStackTrace (); } } ✝ Kelas CustomHTTPClient Kelas Kontak Buat kelas baru dengan nama Kontak dengan mengimplementasikan interface android.os.Parcelable. ✞ 1 package lab.andro. android . kontakonline ; 2 3 4 import android .os. Parcel ; import android .os. Parcelable ; 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class Kontak implements Parcelable { private String id; private String nama; private String alamat ; private String flag; public Kontak ( String id , String nama , String alamat , String flag) { super (); this.id = id; this.nama = nama; this. alamat = alamat ; this.flag = flag; } public Kontak () { super (); this.id = ""; this.nama = ""; this. alamat = ""; this.flag = " normal "; } public Kontak ( Parcel s) { 73 ✆ Android Programming - candra.web.id 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 this.id = s. readString (); this.nama = s. readString (); this. alamat = s. readString (); this.flag = s. readString (); } public String getId () { return id; } public void setId( String id) { this.id = id; } public String getNama () { return nama; } public void setNama ( String nama) { this.nama = nama; } public String getAlamat () { return alamat ; } public void setAlamat ( String isi) { this. alamat = isi; } public int describeContents () { return 0; } public String getFlag () { return flag; } public void setFlag ( String flag) { this.flag = flag; } public void writeToParcel ( Parcel dest , int flags) { dest. writeString (id); dest. writeString (nama); dest. writeString ( alamat ); dest. writeString (flag); } public static Parcelable .Creator <Kontak > CREATOR = new Parcelable .Creator <Kontak >() { public Kontak createFromParcel ( Parcel source ) { return new Kontak ( source ); } 74 Android Programming - candra.web.id 69 70 71 72 73 } }; public Kontak [] newArray (int size) { return new Kontak [size ]; } ✝ Kelas Kontak ✆ Activity dan JSON Parser Sebelum membuat semua Activity yang lainnya, buatlah sebuah Interface baru dengan nama KontakOnline sebagai berikut: ✞ 1 package lab.andro. android . kontakonline ; 2 3 4 5 6 7 public interface KontakOnline { String SERVER_ADDR = "http ://10.0.2.2/ kontak - online /"; String GET_KONTAK = SERVER_ADDR + "get - kontak .php"; String INSERT_KONTAK = SERVER_ADDR + "insert - kontak .php"; } ✝ Interface KontakOnline ✆ Catatan: Alamat http://10.0.2.2 adalah alamat untuk server lokal (PC development). Untuk server yang telah dihostingkan, ganti String SERVER_ADDR dengan alamat yang menuju tempat file get-kontak.php tersimpan. Selanjutnya Kita perlu mengubah Activity KontakOnlineActivity dan menambahkan dua Activity baru lainnya yakni Activity KontakBaruActivity dan BacaKontakActivity. Mari kita bahas satu persatu: a. Activity KontakOnlineActivity • Ubah Activity ini menjadi ListActivity dengan mengganti superclass-nya yang tadinya dari kelas Activity menjadi ListActivity agar dapat lebih mudah memproses ListView. Kemudian implementasikan interface KontakOnline pada kelas ini. ... public class KontakOnlineActivity extends ListActivity implements KontakOnline { .. 75 Android Programming - candra.web.id • Tambahkan beberapa Property sebagai berikut: ... private private private private ... List<Kontak> kontak = new ArrayList<Kontak>(); final static int ACT_KONTAK_BARU = 0; ProgressDialog pd; KontakAdapter adapter; • Buat tiga buah internal kelas bari di dalam kelas/Activity ini. Masing-masing sebagai berikut: Kelas ViewHolder ... static class ViewHolder { TextView textNama; ImageView imageFlag; } ... Kelas KontakAdapter ... private static class KontakAdapter extends BaseAdapter { private LayoutInflater lInflater; @SuppressWarnings("unused") private Context context; private List<Kontak> kontak; public KontakAdapter(Context ctx, List<Kontak> ctt) { lInflater = LayoutInflater.from(ctx); this.context = ctx; this.kontak = ctt; } public int getCount() { return kontak.size(); } public Object getItem(int position) { return kontak.get(position); } public long getItemId(int position) { 76 Android Programming - candra.web.id } return position; public View getView(int position, View convertView, ViewGroup parent) { final ViewHolder holder; if(convertView == null) { convertView = lInflater.inflate(R.layout.item_kontak, null); holder = new ViewHolder(); holder.textNama = (TextView) convertView.findViewById(R.id.textNama); holder.imageFlag = (ImageView) convertView.findViewById(R.id.imageFlag); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } } holder.textNama.setText(kontak.get(position).getNama()); if(kontak.get(position).getFlag().contains("penting")) { holder.imageFlag.setImageResource( android.R.drawable.star_big_on); } else { holder.imageFlag.setImageResource( android.R.drawable.star_big_off); } return convertView; } ... Kelas DataHandler ... class DataHandler extends Handler { public void handleMessage(Message msg) { boolean aman = msg.getData().getBoolean("stat"); pd.dismiss(); if (aman) { ArrayList<Kontak> lst = msg.getData() .getParcelableArrayList("data"); 77 Android Programming - candra.web.id } ... } if(!lst.isEmpty()) { kontak = lst; fillData(); } else { Toast.makeText(KontakOnlineActivity.this, "Data Kosong", Toast.LENGTH_LONG) .show(); } } else { Toast.makeText(KontakOnlineActivity.this, "Data tidak dapat ditampilkan", Toast.LENGTH_LONG).show(); } dan Kelas GetDataThread ... class GetDataThread extends Thread { Handler mHandler; public GetDataThread(Handler mHandler) { super(); this.mHandler = mHandler; } @Override public void run() { String res = null; ArrayList<Kontak> listkontak = new ArrayList<Kontak>(); try { res = CustomHTTPClient.executeHttpGet(GET_KONTAK); Log.d("RESULT", res); if (res == null) { return; } // Parsing JSON ke Objek JSONArray jsa = new JSONArray(res); int i = 0; 78 Android Programming - candra.web.id while (!jsa.isNull(i)) { Kontak c = new Kontak(); c.setId(jsa.getJSONObject(i) .getString("id").trim()); c.setNama(jsa.getJSONObject(i) .getString("nama").trim()); c.setAlamat(jsa.getJSONObject(i) .getString("alamat")); c.setFlag(jsa.getJSONObject(i) .getString("flag").trim()); listkontak.add(c); i++; } } catch (Exception e) { Log.d("LOG", e.getMessage()); Message msg = mHandler.obtainMessage(); Bundle b = new Bundle(); b.putBoolean("stat", false); msg.setData(b); mHandler.sendMessage(msg); return; } } ... } Message msg = mHandler.obtainMessage(); Bundle b = new Bundle(); if(listkontak.isEmpty()) { b.putBoolean("stat", false); } else { b.putBoolean("stat", true); b.putParcelableArrayList("data", listkontak); } msg.setData(b); mHandler.sendMessage(msg); • Buat methode fillData() yang dipanggil dalam kelas DataHandler yang telah dibuat di atas: ... 79 Android Programming - candra.web.id private void fillData() { adapter = new KontakAdapter(this,kontak); setListAdapter(adapter); } ... • Implementasikan menu serta handlernya: ... @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu_utama, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menuKontakBaru: kontakBaru(); break; case R.id.menuAbout: showAbout(); break; case R.id.menuRefresh: getData(); break; } default: break; } return super.onOptionsItemSelected(item); private void showAbout() { AlertDialog.Builder ab = new AlertDialog.Builder(this); ab.setTitle("About"); ab.setMessage("Contoh aplikasi untuk Interfacing Web Services"); ab.setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { 80 Android Programming - candra.web.id dialog.dismiss(); } }); ab.setIcon(android.R.drawable.ic_dialog_info); } AlertDialog a = ab.create(); a.show(); private void kontakBaru() { Intent i = new Intent(this, KontakBaruActivity.class); startActivityForResult(i, ACT_KONTAK_BARU); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case ACT_KONTAK_BARU: if (resultCode == RESULT_OK) { getData(); } break; default: break; } super.onActivityResult(requestCode, resultCode, data); } ... • Buat methode getData() untuk menjalankan Thread yang bertugas untuk mengambil data ke server: ... private void getData() { pd = ProgressDialog.show(this, "Sedang di Proses", "Mengambil data dari server...", true, false); DataHandler handler = new DataHandler(); GetDataThread td = new GetDataThread(handler); td.start(); } ... 81 Android Programming - candra.web.id • Implementasikan Methode untuk menghandle event Klik pada item yang ada dalam ListView dengan meng-Override methode onListItemClick: ... @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Intent i = new Intent(this, BacaKontakActivity.class); i.putExtra("kontak", kontak.get(position)); startActivity(i); } ... • dan yang terakhir, panggil methode getData() melalui methode onCreate ... @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.getData(); } ... • Sehingga kelas ini akan menjadi seperti berikut: ✞ 1 package lab.andro. android . kontakonline ; 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import import import import import import import import import import import import import import java.util. ArrayList ; java.util.List; lab.andro. android . kontakonline .R; org.json. JSONArray ; android .app. AlertDialog ; android .app. AlertDialog . Builder ; android .app. ListActivity ; android .app. ProgressDialog ; android . content . Context ; android . content . DialogInterface ; android . content . Intent ; android . graphics . drawable . Drawable ; android .os. Bundle ; android .os. Handler ; 82 Android Programming - candra.web.id 17 18 19 20 21 22 23 24 25 26 27 28 29 import import import import import import import import import import import import import android .os. Message ; android .util.Log; android .view. LayoutInflater ; android .view.Menu; android .view. MenuInflater ; android .view. MenuItem ; android .view.View; android .view. ViewGroup ; android . widget . BaseAdapter ; android . widget . ImageView ; android . widget . ListView ; android . widget . TextView ; android . widget .Toast; 30 31 32 33 34 35 36 public class KontakOnlineActivity extends ListActivity implements KontakOnline { private List <Kontak > kontak = new ArrayList <Kontak >(); private final static int ACT_KONTAK_BARU = 0; private ProgressDialog pd; private kontakAdapter adapter ; 37 38 39 40 41 42 43 @Override public void onCreate ( Bundle savedInstanceState ) { super . onCreate ( savedInstanceState ); setContentView (R. layout .main); this. getData (); } 44 45 46 47 48 49 50 51 private void getData () { pd = ProgressDialog .show(this , " Sedang di Proses " , " Mengambil data dari server ...", true , false ) ; DataHandler handler = new DataHandler (); GetDataThread td = new GetDataThread ( handler ); td.start (); } 52 53 54 55 private void fillData () { adapter = new kontakAdapter (this , kontak ); setListAdapter ( adapter ); 83 Android Programming - candra.web.id 56 } 57 58 59 60 61 62 63 64 @Override protected void onListItemClick ( ListView l, View v, int position , long id) { super . onListItemClick (l, v, position , id); Intent i = new Intent (this , BacaKontakActivity . class ); i. putExtra (" kontak ", kontak .get( position )); startActivity (i); } 65 66 67 68 69 70 71 @Override public boolean onCreateOptionsMenu (Menu menu) { MenuInflater inflater = getMenuInflater (); inflater . inflate (R.menu.menu_utama , menu); return super . onCreateOptionsMenu (menu); } 72 73 74 75 76 77 78 79 80 81 82 83 84 @Override public boolean onOptionsItemSelected ( MenuItem item) { switch (item. getItemId ()) { case R.id. menuKontakBaru : kontakBaru (); break ; case R.id. menuAbout : showAbout (); break ; case R.id. menuRefresh : getData (); break ; 85 86 87 88 89 90 } default : break ; } return super . onOptionsItemSelected (item); 91 92 93 94 private void showAbout () { AlertDialog . Builder ab = new AlertDialog . Builder ( this); ab. setTitle (" About "); 84 Android Programming - candra.web.id ab. setMessage (" Contoh aplikasi untuk Interfacing Web Services "); ab. setPositiveButton ("OK", new DialogInterface . OnClickListener () { 95 96 97 public void onClick ( DialogInterface dialog , int which) { dialog . dismiss (); } }); ab. setIcon ( android .R. drawable . ic_dialog_info ); 98 99 100 101 102 103 AlertDialog a = ab. create (); a.show (); 104 105 106 107 } 108 109 110 111 112 private void kontakBaru () { Intent i = new Intent (this , KontakBaruActivity . class ); startActivityForResult (i, ACT_KONTAK_BARU ); } 113 114 115 116 117 118 119 120 121 122 123 124 125 126 @Override protected void onActivityResult (int requestCode , int resultCode , Intent data) { switch ( requestCode ) { case ACT_KONTAK_BARU : if ( resultCode == RESULT_OK ) { getData (); } break ; default : break ; } super . onActivityResult (requestCode , resultCode , data); } 127 128 129 130 class DataHandler extends Handler { public void handleMessage ( Message msg) { boolean aman = msg. getData (). getBoolean ("stat") ; 85 Android Programming - candra.web.id 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 } } pd. dismiss (); if (aman) { ArrayList <Kontak > lst = msg. getData (). getParcelableArrayList ("data"); if (! lst. isEmpty ()) { kontak = lst; fillData (); } else { Toast. makeText ( KontakOnlineActivity .this , "Data Kosong ", Toast. LENGTH_LONG ) .show (); } } else { Toast. makeText ( KontakOnlineActivity .this , "Data tidak dapat ditampilkan ", Toast. LENGTH_LONG ) .show (); } 149 150 151 class GetDataThread extends Thread { Handler mHandler ; 152 153 154 155 156 public GetDataThread ( Handler mHandler ) { super (); this. mHandler = mHandler ; } 157 158 159 160 161 162 163 164 165 166 167 168 169 @Override public void run () { String res = null; ArrayList <Kontak > listkontak = new ArrayList < Kontak >(); try { res = CustomHTTPClient . executeHttpGet ( GET_KONTAK ); Log.d(" RESULT ", res); if (res == null) { return ; } // Parsing JSON ke Objek JSONArray jsa = new JSONArray (res); 86 Android Programming - candra.web.id int i = 0; while (! jsa. isNull (i)) { Kontak c = new Kontak (); c.setId(jsa. getJSONObject (i). getString ("id" ).trim ()); c. setNama (jsa. getJSONObject (i). getString (" nama").trim ()); c. setAlamat (jsa. getJSONObject (i). getString ( " alamat ")); c. setFlag (jsa. getJSONObject (i). getString (" flag").trim ()); listkontak .add(c); i++; } 170 171 172 173 174 175 176 177 178 179 180 } catch ( Exception e) { Log.d("LOG", e. getMessage ()); Message msg = mHandler . obtainMessage (); Bundle b = new Bundle (); b. putBoolean ("stat", false ); msg. setData (b); mHandler . sendMessage (msg); return ; } 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 } } Message msg = mHandler . obtainMessage (); Bundle b = new Bundle (); if( listkontak . isEmpty ()) { b. putBoolean ("stat", false ); } else { b. putBoolean ("stat", true); b. putParcelableArrayList ("data", listkontak ); } msg. setData (b); mHandler . sendMessage (msg); 203 204 205 206 207 private static class kontakAdapter extends BaseAdapter { private LayoutInflater lInflater ; @SuppressWarnings (" unused ") private Context context ; 87 Android Programming - candra.web.id 208 private List <Kontak > kontak ; 209 210 211 212 213 214 public kontakAdapter ( Context ctx , List <Kontak > ctt) { lInflater = LayoutInflater .from(ctx); this. context = ctx; this. kontak = ctt; } 215 216 217 218 public int getCount () { return kontak .size (); } 219 220 221 222 public Object getItem (int position ) { return kontak .get( position ); } 223 224 225 226 public long getItemId (int position ) { return position ; } 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 public View getView (int position , View convertView , ViewGroup parent ) { final ViewHolder holder ; if( convertView == null) { convertView = lInflater . inflate (R. layout . item_kontak , null); holder = new ViewHolder (); holder . textNama = ( TextView ) convertView . findViewById (R.id. textNama ); holder . imageFlag = ( ImageView ) convertView . findViewById (R.id. imageFlag ); convertView . setTag ( holder ); } else { holder = ( ViewHolder ) convertView . getTag (); } 242 243 244 245 holder . textNama . setText ( kontak .get( position ). getNama ()); if( kontak .get( position ). getFlag (). contains (" penting ")) { holder . imageFlag . setImageResource ( android .R. 88 Android Programming - candra.web.id 246 247 248 249 } 250 drawable . star_big_on ); } else { holder . imageFlag . setImageResource ( android .R. drawable . star_big_off ); } return convertView ; 251 } 252 253 254 255 256 257 258 } static class ViewHolder { TextView textNama ; ImageView imageFlag ; } ✝ Kelas KontakOnlineActivity b. Activity KontakBaruActivity • Buat kelas baru dengan nama KontakBaruActivity dengan superclass Activity dan interface KontakOnline: ... public class KontakBaruActivity extends Activity implements KontakOnline{ ... • Tambahkan beberapa property/objek widget berikut untuk menangani widget pada Layout: ... private EditText editNama; private EditText editAlamat; private CheckBox checkPenting; ... • Override methode onCreate kemudian set Layout agar menggunakan layout kontak_baru.xml dan link-kan semua objek widget yang dibuat di atas: ... @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); 89 ✆ Android Programming - candra.web.id setContentView(R.layout.kontak_baru); ... } editNama = (EditText) findViewById(R.id.editTextNama); editAlamat = (EditText) findViewById(R.id.editTextAlamat); checkPenting = (CheckBox) findViewById(R.id.checkBoxPenting); • Buat menu pada Activity sekaligus handlingnya: ... @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu_simpan, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menuSimpan: simpan(); break; ... } default: break; } return super.onOptionsItemSelected(item); • dan buat methode simpan() untuk mengirim data ke server: ... private void simpan() { String nama = null; String alamat = null; String flag = "normal"; if(editNama.getText().toString().isEmpty()) { Toast.makeText(this, "Nama tidak boleh Kosong", Toast.LENGTH_LO return; } 90 Android Programming - candra.web.id if(editAlamat.getText().toString().isEmpty()) { Toast.makeText(this, "Alamat tidak boleh Kosong", Toast.LENGTH_ return; } nama = editNama.getText().toString(); alamat = editAlamat.getText().toString(); if(checkPenting.isChecked()) { flag = "penting"; } } ... String res = null; ArrayList<NameValuePair> postParameters = new ArrayList<NameValueP postParameters.add(new BasicNameValuePair("nama", nama)); postParameters.add(new BasicNameValuePair("alamat", alamat)); postParameters.add(new BasicNameValuePair("flag", flag)); try { res = CustomHTTPClient.executeHttpPost(INSERT_KONTAK, postParam if(res.trim().equals("1")) { Toast.makeText(this, "Tersimpan", Toast.LENGTH_LONG).show(); finish(); } } catch (Exception e) { Toast.makeText(this, "Gagal Menyimpan", Toast.LENGTH_LONG).show return; } • ✞Sehingga kelas/Activity ini akan menjadi: 1 package lab.andro. android . kontakonline ; 2 3 4 5 6 7 8 9 10 11 import import import import import import import import import java.util. ArrayList ; org. apache .http. NameValuePair ; org. apache .http. message . BasicNameValuePair ; lab.andro. android . kontakonline .R; android .app. Activity ; android .os. Bundle ; android .view.Menu; android .view. MenuInflater ; android .view. MenuItem ; 91 Android Programming - candra.web.id 12 13 14 import android . widget . CheckBox ; import android . widget . EditText ; import android . widget .Toast; 15 16 17 18 19 public class KontakBaruActivity extends Activity implements KontakOnline { private EditText editNama ; private EditText editAlamat ; private CheckBox checkPenting ; 20 21 22 23 24 @Override public void onCreate ( Bundle savedInstanceState ) { super . onCreate ( savedInstanceState ); setContentView (R. layout . kontak_baru ); 25 editNama = ( EditText ) findViewById (R.id. editTextNama ); editAlamat = ( EditText ) findViewById (R.id. editTextAlamat ); checkPenting = ( CheckBox ) findViewById (R.id. checkBoxPenting ); 26 27 28 29 30 } 31 32 33 34 35 36 37 @Override public boolean onCreateOptionsMenu (Menu menu) { MenuInflater inflater = getMenuInflater (); inflater . inflate (R.menu. menu_simpan , menu); return super . onCreateOptionsMenu (menu); } 38 39 40 @Override public boolean onOptionsItemSelected ( MenuItem item) { 41 42 43 44 45 switch (item. getItemId ()) { case R.id. menuSimpan : simpan (); break ; 46 47 48 49 default : break ; } 92 Android Programming - candra.web.id 50 51 } return super . onOptionsItemSelected (item); 52 53 54 55 56 57 58 59 60 private void simpan () { String nama = null; String alamat = null; String flag = " normal "; if( editNama . getText (). toString (). isEmpty ()) { Toast. makeText (this , "Nama tidak boleh Kosong ", Toast. LENGTH_LONG ).show (); return ; } 61 62 63 64 65 66 67 if( editAlamat . getText (). toString (). isEmpty ()) { Toast. makeText (this , " Alamat tidak boleh Kosong ", Toast. LENGTH_LONG ).show (); return ; } nama = editNama . getText (). toString (); alamat = editAlamat . getText (). toString (); 68 69 70 71 if( checkPenting . isChecked ()) { flag = " penting "; } 72 73 74 75 76 77 78 79 80 81 82 83 84 String res = null; ArrayList < NameValuePair > postParameters = new ArrayList < NameValuePair >(); postParameters .add(new BasicNameValuePair ("nama", nama)); postParameters .add(new BasicNameValuePair (" alamat ", alamat )); postParameters .add(new BasicNameValuePair ("flag", flag)); try { res = CustomHTTPClient . executeHttpPost ( INSERT_KONTAK , postParameters ); if(res.trim (). equals ("1")) { Toast. makeText (this , " Tersimpan ", Toast. LENGTH_LONG ).show (); finish (); } } catch ( Exception e) { 93 Android Programming - candra.web.id 85 86 87 88 89 90 } } } ✝ // TODO: handle exception Toast. makeText (this , " Gagal Menyimpan ", Toast. LENGTH_LONG ).show (); return ; Kelas KontakBaruActivity ✆ c. Activity BacaKontakActivity • Buat kelas baru dengan nama BacaKontakActivity dengan superclass Activity dan interface KontakOnline (interface optional): ... public class BacaKontakActivity extends Activity implements KontakOnline { ... • Tambahkan beberapa property/objek widget berikut untuk menangani widget pada Layout: ... private EditText editNama; private EditText editAlamat; private CheckBox checkPenting; ... • Override methode onCreate kemudian set Layout agar menggunakan layout kontak_baru.xml, ambill data yang dikirim dari activity KontakOnlineActivity dan link-kan semua objek widget yang dibuat di atas serta inisialisasi didalam methode ini: ... @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.kontak_baru); Kontak k = this.getIntent().getParcelableExtra("kontak"); if(k==null) { finish(); } editNama = (EditText) findViewById(R.id.editTextNama); 94 Android Programming - candra.web.id editAlamat = (EditText) findViewById(R.id.editTextAlamat); checkPenting = (CheckBox) findViewById(R.id.checkBoxPenting); ... } editNama.setText(k.getNama()); editAlamat.setText(k.getAlamat()); if(k.getFlag().trim().equals("penting")) { checkPenting.setChecked(true); } editNama.setFocusable(false); editAlamat.setFocusable(false); checkPenting.setEnabled(false); • ✞Sehingga kelas/Activity ini akan menjadi: 1 package lab.andro. android . kontakonline ; 2 3 4 5 6 7 import import import import import lab.andro. android . kontakonline .R; android .app. Activity ; android .os. Bundle ; android . widget . CheckBox ; android . widget . EditText ; 8 9 10 11 12 public class BacaKontakActivity extends Activity implements KontakOnline { private EditText editNama ; private EditText editAlamat ; private CheckBox checkPenting ; 13 14 15 16 17 18 19 20 21 @Override public void onCreate ( Bundle savedInstanceState ) { super . onCreate ( savedInstanceState ); setContentView (R. layout . kontak_baru ); Kontak k = this. getIntent (). getParcelableExtra (" kontak "); if(k== null) { finish (); } 22 23 24 editNama = ( EditText ) findViewById (R.id. editTextNama ); editAlamat = ( EditText ) findViewById (R.id. editTextAlamat ); 95 Android Programming - candra.web.id checkPenting = ( CheckBox ) findViewById (R.id. checkBoxPenting ); 25 26 27 28 29 30 31 32 33 34 35 36 } } editNama . setText (k. getNama ()); editAlamat . setText (k. getAlamat ()); if(k. getFlag ().trim (). equals (" penting ")) { checkPenting . setChecked (true); } editNama . setFocusable ( false ); editAlamat . setFocusable ( false ); checkPenting . setEnabled ( false ); ✝ Kelas BacaKontakActivity Sebelum mengakhiri bagian ini, ada baiknya Anda mengecek kembali apakah semua kelas/Activity telah dibuat. Berikut kelas/Activity yang harus dibuat: • BacaKontakActivity • CustomHTTPClient • Kontak • KontakBaruActivity • KontakOnline dan • KontakOnlineActivity yang didalamnya terdapat kelas internal: DataHandler, GetDataThread, KontakAdapter dan ViewHolder. 6.3.4 Permission Setelah semua bagian program dibuat, program dapat di-run langsung. Namun tentunya akan muncul beberapa masalah diantaranya: • Data idak dapat ditampilkan (Jika data dalam database telah ada). • Dan, aplikasi akan di ”Force Close” ketika mencoba memilih menu Tambah Kontak. 96 ✆ Android Programming - candra.web.id Gambar 6.2: Error (kiri data gagal di load dan kanan Force Close) Dengan pesan error di DDMS untuk force close: ✞ 1 05 -02 20 :58:47 .258: E/ AndroidRuntime (388) : android . content . ActivityNotFoundException: Unable to find explicit activity class {lab. andro . android . kontakonline /lab. andro . android . kontakonline . KontakBaruActivity }; have you declared this activity in your AndroidManifest .xml? ✝ ✆ Log error pada DDMS Masalah pertama bisa terjadi karena dua hal, pertama server belum siap atau tidak dapat diakses. Kedua dikarenakan permission untuk menggunakan INTERNET tidak diberikan pada Android Manifest. Maka untuk menyelesaikannya, tambahkan baris berikut pada file AndroidManifest.xml diluar tag application: <uses-permission android:name="android.permission.INTERNET" /> Sedangkan untuk masalah yang kedua, ini dikarenakan Activity KontakBaruActivity masih belum dikenal di dalam manifest. Sehingga perlu ditambhakan di dalam manifest: 97 Android Programming - candra.web.id <activity android:name=".KontakBaruActivity" android:label="Buat Kontak Baru" android:theme="@android:style/Theme.Light" > </activity> <activity android:name=".BacaKontakActivity" android:label="Baca Kontak" android:theme="@android:style/Theme.Light" > </activity> Kedua tag activity tersebut harus dimasukkan di dalam file AndroidManifest.xml di dalam tag application. ✞ <?xml version ="1.0" encoding ="utf -8"?> 2 <manifest xmlns:android =" http: // schemas . android .com/apk/res/ android " 3 package ="lab. andro . android . kontakonline " 4 android:versionCode ="1" 5 android:versionName ="1.0" > 6 <uses -sdk android:minSdkVersion ="10" /> 7 <uses - permission android:name =" android . permission . INTERNET " /> 1 8 9 10 11 12 13 14 15 16 17 <application android:icon =" @drawable / ic_launcher " android:label =" @string / app_name " android:theme =" @android:style / Theme .Light " > <activity android:name =". KontakOnlineActivity " android:label =" @string / app_name " > <intent - filter > <action android:name =" android . intent . action .MAIN " /> 18 19 20 21 22 23 24 25 26 27 28 29 <category android:name =" android . intent . category . LAUNCHER " /> </intent - filter > </ activity > <activity android:name =". KontakBaruActivity " android:label ="Buat Kontak Baru" android:theme =" @android:style / Theme .Light" > </ activity > <activity android:name =". BacaKontakActivity " android:label ="Baca Kontak " 98 Android Programming - candra.web.id android:theme =" @android:style / Theme .Light" > </ activity > 32 </ application > 33 </ manifest > ✝ 30 31 Isi AndroidManifest.xml 6.4 Running Langkah terakhir adalah mencoba running program. Jalankan web server dan MySQL Server terlebih dahulu. Kemudian coba run program Android yang telah dibuat di atas. Gambar 6.3: Contoh hasil akhir: Tampilan Utama 99 ✆ Android Programming - candra.web.id Gambar 6.4: Contoh hasil akhir (kiri Baca Kontak dan kanan Buat kontak) 100 Bibliography [1] Wikibook LATEX http://en.wikibooks.org/wiki/LaTeX [2] Developer Android http://developer.android.com/index.html [3] Vogella Android http://www.vogella.com/android.html [4] Android Hive http://www.androidhive.info [5] StackOverflow Android http://stackoverflow.com/questions/tagged/android [6] byte[] to Image Android http://stackoverflow.com/questions/2714700/byte-to-image-android 101