Anda di halaman 1dari 229

J.E.N.

Pengembangan Perangkat
Mobile

Versi 1.1
April 2007
Sumber : JEDI

Pengembangan Perangkat Mobile


J.E.N.I

Pengarang Persyaratan-persyaratan untuk latihan laboratorium


Joyce Avestro
Sistem Operasi yang mendukung

NetBeans IDE 5.5 berjalan pada sistem operasi yang mendukung Java VM.
Team Dibawah ini merupakan daftar dari platform-platform yang digunakan:
Joyce Avestro
Florence Balagtas
Microsoft Windows XP Professional SP2 atau yang terbaru
Rommel Feria
Mac OS X 10.4.5 atau yang terbaru
Reginald Hutcherson Red Hat Fedora Core 3
Rebecca Ong Sistem Operasi Solaris™ 10 Update 1 (SPARC® and x86/x64
John Paul Petines Platform Edition)
Sang Shin
Raghavan Srinivas NetBeans Enterprise Pack juga dapat digunakan pada platform-platform
Matthew Thompson berikut ini:

Microsoft Windows 2000 Professional SP4


Team Translator Solaris™ 8 OS (SPARC and x86/x64 Platform Edition) and Solaris 9
Frans Thamura OS (SPARC and x86/x64 Platform Edition)
Eko Subiyantoro Berbagai macam distribusi LINUX
Cahya Kusuma Ratih
Rizzatama N.S.
Mir’atul Khusna Mufida
Khansa Fitriannisa Minimum konfigurasi Hardware
Sulistyaningtyas
Fauzan Prasetyo E.P Catatan: Minimum resolusi layar NetBeans IDE's adalah 1024x768 pixels.
Allin Junikhah
Bagus Chandra Sistem Operasi Microsoft Windows:
Badar Agung Nugroho o Prosesor: 500 MHz Intel Pentium III workstation atau
setaranya
Kadek Surya Pranata
o Memori: 512 MB
o Disk space: 850 MB dari free disk space
Sistem operasi Linux:
o Prosesor: 500 MHz Intel Pentium III workstation atau
setaranya
o Memori: 512 MB
o Disk space: 450 MB dari free disk space
Solaris OS (SPARC):
o Prosesor: UltraSPARC II 450 MHz
o Memori: 512 MB
o Disk space: 450 MB of free disk space
Solaris OS (x86/x64 Platform Edition):
o Prosesor: AMD Opteron 100 Series 1.8 GHz
o Memori: 512 MB
o Disk space: 450 MB dari free disk space
Sistem Operasi Macintosh OS X:
o Prosesor: PowerPC G4
o Memori: 512 MB
o Disk space: 450 MB dari free disk space

Pengembangan Perangkat Mobile


J.E.N.I

Konfigurasi Hardware yang direkomendasikan

Sistem Operasi Microsoft Windows:


o Prosesor: 1.4 GHz Intel Pentium III workstation atau
setaranya
o Memori: 1 GB
o Disk space: 1 GB dari free disk space
Sistem Operasi Linux:
o Prosesor: 1.4 GHz Intel Pentium III atau setaranya
o Memori: 1 GB
o Disk space: 850 MB dari free disk space
Solaris™ OS (SPARC®):
o Prosesor: UltraSPARC IIIi 1 GHz
o Memori: 1 GB
o Disk space: 850 MB dari free disk space

Solaris™ OS (x86/x64 platform edition):

o Prosesor: AMD Opteron 100 Series 1.8 GHz


o Memori: 1 GB
o Disk space: 850 MB dari free disk space
Sistem Operasi Macintosh OS X:
o Prosesor: PowerPC G5
o Memori: 1 GB
o Disk space: 850 MB dari free disk space

Software yang diperlukan

NetBeans Enterprise Pack 5.5 dapat diakses pada Java 2 Platform Standard
Edition Development Kit 5.0 Update 1 atau diatasnya (JDK 5.0, versi
1.5.0_01 atau diatasnya), dimana berisi Java Runtime Environment plus
developer tools untuk meng-compile, men-debug, and menjalankan aplikasi
yang ditulis dengan bahasa Java. Sun Java System Application Server
Platform Edisi 9 telah diuji dengan JDK 5.0 update 6.

Untuk Solaris, Windows, dan Linux, Anda dapat mendownload


JDK untuk platform Anda pada
http://java.sun.com/j2se/1.5.0/download.html
Untuk Mac OS X, memerlukan Java 2 Platform Standard Edition
(J2SE) 5.0 Release 4. Anda dapat mendownload JDK dari Apple's
Developer Connection site. Pada:
http://developer.apple.com/java (untuk mendownload JDK
Anda harus melakukan registrasi terlebih dahulu).

Pengembangan Perangkat Mobile


J.E.N.I

Daftar Isi
1 Pengembangan Aplikasi Mobile
1.1 Tujuan
1.2 Perangkat Mobile
1.3 Gambaran J2ME
1.3.1 Platform Java
1.3.2 Gambaran J2ME
1.3.3 Configuration
1.3.4 Profile
1.4 CLDC
1.4.1 Fitur yang Hilang
1.4.2 Karakteristik perangkat CLDC
1.4.3 Verifikasi Class
1.4.4 Generic Connection Framework
1.5 CDC
1.6 JTWI
1.7 MIDP
1.8 MIDlet
1.8.1 Siklus MIDlet
1.8.2 MIDlet suites
1.9 Latihan

2 Memulai Pemrograman Mobile


2.1 Tujuan
2.2 Pengenalan
2.3 “Hello, world!” MIDlet
2.4 Compilation dan Packaging MIDlets
2.5 Menggunakan Sun Wireless Toolkit
2.6 Menggunakan NetBeans mobility Pack
2.7 Latihan
2.7.1 Multiple MIDlets dalam satu MIDlet suite
2.7.2 Multiple MIDlets dalam satu MIDlet suite menggunakan Wireless Toolkit

3 High Level User Interface


3.1 Tujuan
3.2 MIDP User Interface
3.2.1 Display
3.2.2 Displayable
3.2.3 Title
3.2.4 Command
3.2.5 CommandListener
3.2.6 Ticker

Pengembangan Perangkat Mobile


J.E.N.I

3.2.7 Screen
3.2.8 Item
3.3 Alert
3.4 List
3.5 Text Box
3.6 Form
3.7 ChoiceGroup
3.8 Date Field
3.9 String Item
3.10 Image Item
3.11 Text Field
3.12 Latihan
3.12.1 List Dinamis

4 Low Level User Interface


4.1 Tujuan
4.2 Pengenalan
4.3 Canvas
4.3.1 Sistem Koordinat
4.3.2 “Hello, World!”
4.3.3 Perintah
4.3.4 Event Key
4.3.5 Aksi Permainan
4.3.6 Event Pointer
4.4 Grafik
4.4.1 Warna
4.4.2 Huruf
4.4.3 Style Coretan
4.4.4 Clipping
4.4.5 Anchor Points
4.4.6 Menggambar Text
4.4.7 Menggambar Garis
4.4.8 Menggambar Kotak
4.4.9 Menggambar Sudut
4.4.10 Melukis Gambar
4.5 Game API
4.5.1 Game API
4.5.2 Layers
4.5.3 Sprites
4.5.4 LayerManager
4.6 Scalable 2D Graphics
4.7 Latihan
4.7.1 Key Codes
4.7.2 Palindrome
4.7.3 Notepad

Pengembangan Perangkat Mobile


J.E.N.I

5 Persistence
5.1 Tujuan
5.2 Record Store
5.3 Record Enumeration
5.4 Record Comparator
5.5 Record Filter
5.6 Record Listener
5.7 Latihan
5.7.1 Penyimpanan Pilihan

6 Jaringan
6.1 Generic Connection Framework
6.1.1 Hirarki dari GCF Interface
6.1.2 GCF Connection URL
6.2 Koneksi HTTP
6.2.1 Protokol HTTP
6.2.2 Menciptakan sebuah koneksi HTTP
6.2.3 Handling HTTP Redirects
6.3 Koneksi HTTPS
6.4 TCP Sockets
6.5 Server Sockets
6.6 Datagrams
6.7 Latihan
6.7.1 Mendapatkan URL

7 Security
7.1 Tujuan
7.2 Dasar Security
7.3 J2ME Security
7.4 Menggunakan Security dan Trust Services API(SATSA)
7.5 Latihan

8 Web Services
8.1 Tujuan
8.2 Pengenalan terhadap XML
8.2.1 Registrasi Listeners
8.3 Java APIs bagi XML
8.4 Web Services
8.5 J2ME Web Services API (WSA)
8.6 Membuat sebuah Mobile Web Service Client

Pengembangan Perangkat Mobile


J.E.N.I

9 Optimisasi
9.1 Tujuan
9.2 Optimisasi
9.3 Eksekusi Program
9.3.1 Gunakan StringBuffer sebagai pengganti String
9.3.2 Gunakan clipping area dalam manggambar
9.3.3 Hindari modifier yang sama
9.3.4 Lewatkan parameter sesedikit mungkin
9.3.5 Mengurangi pemanggilan method
9.3.6 Menunda semua inisialisasi
9.3.7 Gunakan Array sebagai pengganti collection
9.3.8 Menggunakan variabel lokal
9.4 Ukuran JAR
9.4.1 Gunakan Obfuscator
9.4.2 Memadatkan file JAR Anda
9.4.3 Hindari membuat class yang tidak perlu
9.4.4 Hindari membuat interfaces
9.4.5 Hindari inner dan anonymous class
9.4.6 Gunakan satu Listener untuk object yang ganda
9.4.7 Gunakan package default (package tanpa nama)
9.4.8 Batasi penggunaan dari initializer static
9.4.9 Menggabungkan gambar kedalam satu file
9.4.10 Bereksperimen dengan memampatkan gambar
9.4.11 Gunakan class yang belum diinstal
9.5 Jaringan
9.5.1 Gunakan thread yang terpisah
9.5.2 Memampatkan data jaringan
9.5.3 Mengurangi lalu lintas jaringan
9.6 Penggunaan Memori
9.6.1 Gunakan struktur data ringkas
9.6.2 Membebaskan object yang tidak terpakai untuk garbage collection
9.6.3 Jangan sering menggunakan layar on-the-fly
9.7 Latihan
9.7.1 Ide optimisasi lainnya

10 Jaringan
10.1 Konsep Dasar jaringan
10.1.1 IP Adress
10.1.2 Protokol
10.1.3 Port
10.1.4 Paradigma Client/Server
10.1.5 Sockets
10.2 The Java Networking Package
10.2.1 The ServerSocket dan The Socket Class
10.2.2 The MultiCastSocket dan DatagramPacket Class
10.3 Latihan
10.3.1 Trivia Server

Pengembangan Perangkat Mobile


J.E.N.I

11 Topik-topik Tambahan
11.1 Tujuan
11.2 Timers
11.3 Push Functionality
11.4 Latihan
11.4.1 Time MIDlet

Pengembangan Perangkat Mobile


J.E.N.I.

Bab 1

Pengembangan Aplikasi Mobile

1.1 Tujuan

Dalam bab ini, kita akan mendiskusikan karateristik dari perangkat mobile, dan bagaimana hal
tersebut mempengaruhi pengembangan program untuk perangkat ini. Kita akan diperkenalkan
kepada Java 2 Mobile Edition (J2ME), termasuk pentingnya configuration dan profilenya.
Pada akhir bab ini, pelajar diharapkan dapat menguasai :

● Mengidentifikasi karakteristik dari perangkat mobile

● Menjelaskan arsitektur J2ME

● Mengetahui peran atau aturan configuration dan profile

● Mengidentifikasi API yang disediakan oleh MIDP

● Menjelaskan daur hidup MIDlet

1.2 Perangkat Mobile


Perangkat mobile memiliki banyak jenis dalam hal ukuran, desain dan layout, tetapi mereka
memiliki kesamaan karakteristik yang sangat berbeda dari sistem desktop.

● Ukuran yang kecil


Perangkat mobile memiliki ukuran yang kecil. Konsumen menginginkan perangkat yang
terkecil untuk kenyamanan dan mobilitas mereka.

● Memory yang terbatas


Perangkat mobile juga memiliki memory yang kecil, yaitu primary (RAM) dan secondary
(disk). Pembatasan ini adalah salah satu faktor yang mempengaruhi penulisan program
untuk berbagai jenis dari perangkat ini. Dengan pembatasan jumlah dari memory,
pertimbangan-pertimbangan khusus harus diambil untuk memelihara pemakaian dari
sumber daya yang mahal ini.

● Daya proses yang terbatas


Sistem mobile tidaklah setangguh rekan mereka yaitu desktop. Ukuran, teknologi dan
biaya adalah beberapa faktor yang mempengaruhi status dari sumber daya ini. Seperti
harddisk dan RAM, Anda dapat menemukan mereka dalam ukuran yang pas dengan
sebuah kemasan kecil.

● Mengkonsumsi daya yang rendah

Pengembangan Perangkat Mobile 1


J.E.N.I.

Perangkat mobile menghabiskan sedikit daya dibandingkan dengan mesin desktop.


Perangkat ini harus menghemat daya karena mereka berjalan pada keadaan dimana
daya yang disediakan dibatasi oleh baterai-baterai.

● Kuat dan dapat diandalkan


Karena perangkat mobile selalu dibawa kemana saja, mereka harus cukup kuat untuk
menghadapi benturan-benturan, gerakan, dan sesekali tetesan-tetesan air.

● Konektivitas yang terbatas


Perangkat mobile memiliki bandwith rendah, beberapa dari mereka bahkan tidak
tersambung. Kebanyakan dari mereka menggunakan koneksi wireless.

● Masa hidup yang pendek


Perangkat-perangkat konsumen ini menyala dalam hitungan detik kebanyakan dari
mereka selalu menyala. Coba ambil kasus sebuah handphone, mereka booting dalam
hitungan detik dan kebanyakan orang tidak mematikan handphone mereka bahkan
ketika malam hari. PDA akan menyala jika anda menekan tombol power mereka.

1.3 Gambaran J2ME

1.3.1 Platform JAVA


Java dibuat pada tahun 1991 oleh James Gosling. Pada awalnya diberi nama Oak, dimana
untuk menghormati pohon yang ada di luar jendela Gosling. Kemudian namanya diubah ke
Java karena telah ada sebuah bahasa yang diberi nama Oak.
Motivasi sesungguhnya dari Java adalah kebutuhan akan sebuah bahasa yang bisa digunakan
pada berbagai platform yang bisa dimasukkan ke dalam berbagai produk elektronik seperti
pemanggang roti dan lemari es. Salah satu dari proyek pertama yang dikembangkan
menggunakan JAVA sebuah remote kontrol yang diberi nama Star 7.
Pada saat yang sama, World Wide Web dan Internet berkembang sangat cepat. Gosling
menyadari bahwa Java dapat digunakan untuk pemrograman Internet.
Dengan keluarnya versi 1.2, platform Java telah dipilah-pilah menjadi beberapa edisi :
The Standard Edition(J2SE), Enterprise Edition(J2EE), Mobile Edition(J2ME), dan JavaCard API.

J2SE – Java 2 Platform, Standard Edition Aplikasi Desktop

J2EE – Java 2 Platform, Enterprise Edition Aplikasi enterprise dengan fokus pada
pengembangan sisi webserver, termasuk
servlet,JSP,EJB, dan XML

J2ME – Java 2 Platform, Micro Edition Perangkat Mobile

JavaCard Smart Cards

Pengembangan Perangkat Mobile 2


J.E.N.I.

Servers
Servers
Desktop
machines
High-end
Optional consumer
Packages
devices Low-end
consumer
Optional
Packages devices

Smart
Cards
J2EE Personal Profile
J2SE
Foundation Profile MIDP

Java
CDC CLDC
Card

Java Virtual Machine KVM Card VM

Java 2 Micro Edition (J2ME)

Gambar 1: Platform Java

1.3.2 Gambaran J2ME


J2ME adalah satu set spesifikasi dan teknologi yang fokus kepada perangkat konsumen.
Perangkat ini memiliki jumlah memori yang terbatas, menghabiskan sedikit daya dari baterei,
layar yang kecil dan bandwith jaringan yang rendah.
Dengan perkembangbiakan perangkat mobile konsumer dari telepon, PDA, kotak permainan ke
peralatan-peralatan rumah, Java menyediakan suatu lingkungan yang portable untuk
mengembangkan dan menjalankan aplikasi pada perangkat ini.
Program J2ME, seperti semua program JAVA adalah diterjemahkan oleh VM. Program-program
tersebut dikompile ke dalam bytecode dan diterjemahkan denga Java Virtual Machine(JVM).Ini
berarti bahwa program-program tersebut tidak berhubungan langsung dengan perangkat.
J2ME menyediakan suatu interface yang sesuai dengan perangkat. Aplikasi-aplikasi tersebut
tidak harus dikompile ulang supaya mampu dijalankan pada mesin yang berbeda.
Inti dari J2ME terletak pada configuration dan profile-profile. Suatu configuration
menggambarkan lingkungan runtime dasar dari suatu sistem J2ME. Ia menggambarkan core
library, virtual machine, fitur keamanan dan jaringan.

Pengembangan Perangkat Mobile 3


J.E.N.I.

Applications

Optional OEM
Profile
Packages APIs
Libraries
Configuration {
Java Virtual Machine

Device Operating System

Gambar 2: Arsitektur J2ME

Sebuah profile memberikan library tambahan untuk suatu kelas tertentu pada sebuah
perangkat. profile-profile menyediakan user interface(UI) API,persistence, messaging library,
dan sebagainya.

Satu set library tambahan atau package tambahan menyediakan kemampuan program
tambahan. Pemasukan package ini ke dalam perangkat J2ME dapat berubah-ubah karena
tergantung pada kemampuan sebuah perangkat. Sebagai contoh, beberapa perangkat MIDP
tidak memiliki Bluetooth built-in, sehingga Bluetooth API tidak disediakan dalam perangkat ini.

1.3.3 Configuration
Suatu configuration menggambarkan fitur minimal dari lingkungan lengkap Java runtime.
Untuk menjamin kemampuan portabilitas dan interoperabilitas optimal diantara berbagai
macam perangkat yang dibatasi sumber dayanya(memory, prosesor, koneksi yang dibatasi),
configuration tidak menggambarkan fitur tambahan. Suatu configuration J2ME
menggambarkan suatu komplemen yang minimum dari teknologi JAVA. Adalah merupakan
tugas profile-profile untuk menggambarkan tambahan library untuk suatu kategori perangkat
tertentu.

configuration menggambarkan:

● Subset bahasa pemrograman JAVA

● Kemampuan Java Virtual Machine(JVM)

● Core platform libraries

● Fitur sekuriti dan jaringan

Pengembangan Perangkat Mobile 4


J.E.N.I.

1.3.4 Profile
Suatu profile menggambarkan set-set tambahan dari API dan fitur untuk pasar tertentu,
kategori perangkat atau industri. Sementara configuration menggambarkan library dasar,
profile-profile menggambarkan library yang penting untuk membuat aplikasi-aplikasi efektif.
Library ini memasukkan user interface, jaringan dan penyimpanan API.

1.4 CLDC
The Connected Limited Device Configuration (CLDC) menggambarkan dan menunjuk pada area
berikut ini:

● Fitur Bahasa Java dan Virtual Machine(VM)

● Library dasar(java.lang.*,java.util.*)

● Input/Output(java.io.*)

● Kemanan

● Jaringan

● Internationalization

1.4.1 Fitur yang hilang


Fitur tertentu dari J2SE yang dipindahkan dari CLDC adalah :

● Finalization of class instances

● Asynchronous exceptions

● Beberapa error classes

● User-defined class loaders

● Reflection

● Java Native Interface (JNI)

● Thread groups dan daemon threads

Reflection, Java Native Interface (JNI) dan user-defined class loaders potensial menjadi lubang
keamanan. JNI juga membutuhkan memory yang intensif sehingga dimungkinkan untuk tidak
mendapat dukungan dari memory rendah sebuah perangkat mobile.

1.4.2 Karakteristik perangkat CLDC


Perangkat yang diincar oleh CLDC mempunyai karateristik sebagai berikut:

● Memory minimal 192kb untuk platform Java.

● Prosesor dengan 16 atau 32 bit.

Pengembangan Perangkat Mobile 5


J.E.N.I.

● Mengkonsumsi sedikit daya.

● Terbatas, koneksi jaringan yang sementara dengan pembatasan bandwith(biasanya


wireless).

CLDC tidak menggambarkan instalasi dan daur hidup sebuah aplikasi, antarmuka(UI) dan
penanganan peristiwa(event handling). Adalah merupakan tugas profile yang berada di bawah
CLDC untuk menggambarkan area ini. Secara khusus, spesifikasi MIDP menggambarkan daur
hidup aplikasi MIDP (MIDlet), library UI dan event handling(javax.microedition.lcdui.*).

1.4.3 Verifikasi Class


Spesifikasi CLDC memerlukan semua class untuk melewati proses verifikasi dua tingkat.
Verifikasi pertama dilaksanakan diluar perangkat sebelum instalasi pada perangkat. Verifikasi
kedua terjadi pada perangkat selama runtime dan dilaksanakan oleh KVM.

File.java
Install

compile (javac) verify


(runtime)

File.class

preverify interpret

File.class

Development Machine Target Device

Gambar 3: Proses Verifikasi dua tingkat

Pengembangan Perangkat Mobile 6


J.E.N.I.

1.4.4 Generic Connection Framework


The Generic Connection Framework menyediakan API dasar untuk koneksi dalam CLDC.
Framework ini menyediakan suatu pondasi umum untuk koneksi seperti HTTP, Socket, dan
Datagrams.GCF menyediakan suatu set API yang umum dan biasa yang memisahkan semua
jenis koneksi. Perlu dicatat bahwa tidak semua jenis koneksi dibutuhkan untuk diterapkan oleh
perangkat MIDP.
Hirarki interface yang dapat diperluas dari GFC membuat proses penyamarataan menjadi
mungkin. Jenis koneksi baru mungkin bisa ditambahkan ke dalam framework ini dengan
memperluas hirarki ini.

Connection

StreamConnectionNotifier DatagramConnection

InputConnection OutputConnection

StreamConnection

ContentConnection

Gambar 4: Hirarki koneksi GCF

1.5 CDC
Connected Device Configuration (CDC) adalah super set dari CLDC. CDC menyediakan
lingkungan Java runtime yang lebih luas dibandingkan CLDC dan lebih dekat kepada
lingkungan J2SE.

Pengembangan Perangkat Mobile 7


J.E.N.I.

CDC Java Virtual Machine (CVM) mendukung penuh Java Virtual Machine (JVM). CDC berisi
semua API dari CLDC. CDC menyediakan suatu subset yang lebih besar dari semua class
J2SE.
Seperti CLDC, CDC tidak menggambarkan setiap class UI. Library UI digambarkan oleh profile-
profile di bawah configuration ini.
Semua class yang terdapat dalam CDC datang dari package ini:

● java.io
● java.lang
● java.lang.ref
● java.lang.math
● java.net
● java.security
● java.security.cert
● java.text
● java.util
● java.util.jar
● java.util.zip

CDC juga memasukkan di dalamnya GCF. CDC memerlukan jenis koneksi tambahan seperti file
dan dukungan datagram.

1.6 JTWI
The Java Technology for the Wireless Industry (JTWI) menetapkan satu set jasa dan spesifikasi
standar. Berdasar spesifikasi JTWI, kata kuncinya adalah “untuk memperkecil fragmentasi API
di dalam pasar telepon mobile, dan untuk mengirim spesifikasi yang dapat
diprediksi,spesifikasi yang jelas untuk perangkat pabrik, operator, dan pengembang aplikasi”.
Dengan penyesuaian kepada JTWI, banyak aplikasi akan berjalan di suatu set yang lebih luas
pada perangkat. Perangkat pabrik juga akan beruntung karena sebuah aplikasi yang besar
akan tersedia untuk perangkat mereka.

Pengembangan Perangkat Mobile 8


J.E.N.I.

MIDlets

WMA MMAPI Optional OEM


MIDP 2.0
1.1 1.1 Packages APIs

CLDC 1.0 or 1.1

Device Operating System

Gambar 5: Komponen JTWI

1.7 MIDP
The Mobile Information Device Profile (MIDP) berada di atas dari CLDC. Anda tidak bisa
menulis aplikasi mobile hanya dengan menggunakan CLDC API. Anda harus tetap
memanfaatkan MIDP yang mendefinisikan UI.
Spesifikasi MIDP, kebanyakan seperti CLDC dan API lainnya sudah digambarkan melalui Java
Community Process (JCP). JCP melibatkan sebuah kelompok ahli berasal dari lebih dari 50
perusahaan, yang terdiri atas pabrik perangkat mobile, pengembang software. MIDP terus
berkembang, dengan versi-versi masa depan yang telah lulus dari proses ketat JCP.

Spesifikasi MIDP menggambarkan suatu perangkat MID yang memiliki karakteristik-


karateristik ini sebagai batas minimum:
• Tampilan:
• Ukuran Layar: 96x54
• kedalaman tampilan: 1-bit
• Ketajaman pixel: sekitar 1:1

• Masukan:
• Satu atau lebih mekanisme user-input: satu keybboard, dua keyboard, atau
touch screen

• Memory:
• 256 kilobytes of non-volatile memory untuk implementasi MIDP.
• 8 kilobytes of non-volatile memory for application-created persistent data
• 128 kilobytes of volatile memory for the Java runtime (e.g., the Java heap)

• Jaringan:
• dua jalur, wireless, bandwidth terbatas

• Sound:
• Kemampuan untuk memainkan nada-nada

Pengembangan Perangkat Mobile 9


J.E.N.I.

MIDP menggambarkan model aplikasi, UI API, penyimpanan dan jaringan yang kuat,
permainan dan media API, kebijakan keamanan, penyebaran aplikasi dan ketetapan over-the-
air.

1.8 MIDlet
Suatu aplikasi MIDP disebut MIDlet. Perangkat application management software (AMS)
berinteraksi langsung dengan MIDlet dengan method MIDlet create, start, pause, dan destroy.

MIDlet adalah bagian dari package javax.microedition.midlet. Sebuah MIDlet harus di-extend
dengan class MIDlet. Dan dapat meminta parameter dari AMS seperti dirumuskan dalam
application descriptor (JAD).

Suatu MIDlet tidak harus memiliki (dan memang harus tidak mempunyai) sebuah method
public static void main(String[] argv).Method tersebut tidak akan dikenal lagi oleh AMS
sebagai titik awal sebuah program.

1.8.1 Siklus MIDlet


kehidupan MIDlet dimulai ketika di-instantiate oleh AMS. MIDlet pada awalnya masuk status
“Pause” setelah perintah baru dibuat. AMS memanggil constructor public tanpa argumen dari
MIDlet. Jika sebuah exception terjadi dalam constructor, MIDlet memasuki status “Destroyed”
dan membuangnya segera.

MIDlet masuk ke dalam status “Active” atas pemanggilan method startUp() oleh AMS.

MIDlet masuk ke dalam status “Destroyed” ketika AMS memanggil method destroyApp().
Status ini juga kembali diakses ketika method notifyDestroyed() kembali dengan sukses
kepada aplikasi. Dengan catatan bahwa MIDlet hanya bisa memasuki status “Destroyed”
sekali dalam masa hidupnya.

Pengembangan Perangkat Mobile 10


J.E.N.I.

new

destroyApp()

startApp() Paused

Destroyed
Active pauseApp()

destroyApp()

Gambar 6: Daur hidup MIDlet

1.8.2 MIDlet suites

Aplikasi-aplikasi MIDlet dibungkus dan dikirim kedalam perangkat sebagai MIDlet suites.
Sebuah MIDlet suite terdiri dari Java Archive (JAR) dan sebuah tambahan Java Application
Descriptor (JAD).

File JAD adalah suatu file teks yang berisi satu set atribut-atribut, beberapa dibutuhkan.

1.9 Latihan
1.9.1 Apa keuntungan menggunakan java sebagai pengembangan dan
platform runtime untuk perangkat mobile?
● Aplikasi yang sangat portable

● Kaya, tergambar dengan baik menghubungkan ke perangkat

● Penggunaan memori yang rendah(KVM)

● Lingkungan runtime yang aman

● aplikasi yang dinamis

Pengembangan Perangkat Mobile 11


J.E.N.I.

1.9.2 Apa yang memotivasi anda untuk menulis program untuk


perangkat mobile?
● Tantangan tentang penulisan mengoptimalkan aplikasi

● Pengalaman pelajaran baru

● Faktor kesenangan

Pengembangan Perangkat Mobile 12


J.E.N.I.

Bab 2
Memulai Pemrograman Mobile

2.1 Tujuan

In this section, we will be delving into writing, building, using the emulator and
packaging J2ME applications. The Integrated Programming Environment that we will use
is NetBeans 4.1 (www.netbeans.org) and NetBeans Mobility Pack.
Pada bagian ini, kita akan menggali tentang menulis, membangun, menggunakan
emulator dan melakukan packaging aplikasi J2ME. Integrated Programming Environment
yang akan kita gunakan adalah NetBeans 4.1 (www.netbeans.org) dan NetBeans
Mobility Pack.

Setelah menyelesaikan bagian ini, siswa diharapkan mampu:

• Membuat MIDlet sederhana


• Membuat sebuah project di NetBeans
• Membuat sebuah MIDlet menggunakan NetBeans Mobility Pack
• Menjalankan MIDlet di emulator

2.2 Pengenalan

IDE (Integrated Development Environment) adalah sebuah lingkungan pemrograman


(programming environment) yang memiliki GUI builder, text atau code editor, compiler
dan/atau interpreter dan debugger. Dalam hal ini, NetBeans Mobility Pack juga memiliki
device emulator. Fasilitas ini bisa membuat kita melihat program kita pada device yang
sesungguhnya.

2.3 "Hello, world!" MIDlet

Kita sudah mempelajari pada bagian sebelumnya tentang daur hidup MIDlet (MIDlet's
life cycle). MIDlet mulai hidup ketika MIDlet dibuat oleh Application Management System
(AMS) pada device.

Pengembangan Perangkat Mobile 1


J.E.N.I.

Agar kita dapat membuat MIDlet, kita harus membuat subclass dari MIDlet class dari
javax.microedition.midlet package. Kita juga harus melakukan override atau implement
pada method: startApp(), destroyApp() dan pauseApp(). Method-method tersebut
adalah method yang diperlukan oleh AMS untuk menjalankan dan mengkontrol MIDlet.

new

destroyApp()

startApp() Paused

Destroyed
Active pauseApp()

destroyApp()

Tidak seperti program Java pada umumnya dimana method main() hanya digunakan
sekali pada jalannya program, method startApp() mungkin akan dipanggil lebih dari
sekali dalam daur hidup MIDlet. Sehingga Anda diharuskan tidak membuat satu
inisialisasi code pada method startApp(). Daripada, anda dapat membuat MIDlet
consturctor dan melakukan inisialisasi di situ.

Berikut ini adalah code program MIDP pertama kita:

/*
* HelloMidlet.java
*
* Created on July 8, 2000, 9:00 AM
*/

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

/**
*
* @author JEDI Apprentice

Pengembangan Perangkat Mobile 2


J.E.N.I.

* @version
*/
public class HelloMidlet extends MIDlet implements CommandListener {
Display display;
Command exitCommand = new Command("Exit", Command.EXIT, 1);
Alert helloAlert;

public HelloMidlet(){
helloAlert = new Alert(
"Hello MIDlet", "Hello, world!",
null, AlertType.INFO
);

helloAlert.setTimeout(Alert.FOREVER);
helloAlert.addCommand(exitCommand);
helloAlert.setCommandListener(this);
}

public void startApp() {


if (display == null){
display = Display.getDisplay(this);
}

display.setCurrent(helloAlert);
}

public void pauseApp() {


}

public void destroyApp(boolean unconditional) {


}

public void commandAction(Command c, Displayable d){


if (c == exitCommand){
destroyApp(true);
notifyDestroyed(); // Exit
}

Pengembangan Perangkat Mobile 3


J.E.N.I.

}
}

Selanjutnya kita akan mempelajari MIDlet pertama kita, difokuskan pada line yang
penting dari code diatas:

public class HelloMidlet extends MIDlet implements CommandListener {

Seperti yang sudah kita katakan sebelumnya, kita harus membuat subclass dari MIDlet
untuk membuat MIDP program. Pada line ini, kita sudah membuat subclass dari MIDlet
dengan memberikan turunan kelas induk dan menamakannya HelloMIDlet.

Display display;
Command exitCommand = new Command("Exit", Command.EXIT, 1);
Alert helloAlert;

Line diatas ini adalah variabel properties dari MIDlet. Kita membutuhkan object Display
(hanya ada satu diplay per MIDlet) untuk melakukan fungsi menggambar pada layar.
exitCommand adalah perintah yang akan kita taruh pada layar agar kita dapat keluar
dari program. Jika kita tidak memiliki perintah keluar, maka kita tidak memiliki cara
untuk keluar dari MIDlet dengan benar.

public HelloMidlet(){
helloAlert = new Alert(
"Hello MIDlet", "Hello, world!",
null, AlertType.INFO
);

helloAlert.setTimeout(Alert.FOREVER);
helloAlert.addCommand(exitCommand);
helloAlert.setCommandListener(this);
}

Consturctor melakukan inisialisasi dari object Alert. Kita akan mempelajari lebih lanjut
dari Alert class pada bab berikutnya. Method addCommand() pada object Alert
memberikan perintah "Exit" pada layar. Method setCommandListener() memberikan
informasi kepada sistem untuk memberikan semua command events ke MIDlet.

Pengembangan Perangkat Mobile 4


J.E.N.I.

public class HelloMidlet extends MIDlet implements CommandListener {

Code "implements CommandListener" adalah untuk command/key presses, sehingga


program kita mampu menghandle "command" events. Jika kita melakukan implement
CommandListener, kita harus membuat method commandAction().

public void commandAction(Command c, Displayable d){


if (c == exitCommand){
destroyApp(true);
notifyDestroyed(); // Exit
}
}

commandAction() diatas hanya menghandle request untuk perintah "Exit". Method diatas
akan menghentikan program menggunakan notifyDestroyed() jika perintah "Exit"
dijalankan atau ditekan.

public void startApp() {


if (display == null){
display = Display.getDisplay(this);
}

display.setCurrent(helloAlert);
}

Code diatas adalah bagian awal dari program kita ketika program kita sudah siap untuk
ditampilkan oleh AMS. Perlu diingat bahwa method startApp() mungkin / bisa
dimasukkan lebih dari sekali seperti pada daur hidup MIDlet. Jika MIDlet berhenti /
dihentikan, seperti bila ada telepon masuk, program akan masuk ke state berhenti
(pausedApp). Jika panggilan sudah selesai AMS akan kembali ke program dan
memanggil method startApp() lagi. Method display.setCurrent() memberikan informasi
ke sistem bahwa kita menginginkan object Alert untuk dimunculkan ke layar. Kita dapat
mendapat tampilah object dengan memanggil method statis Display.getDisplay().

NetBeans Mobility Pack secara otomatis membuat Java Application Descriptor (JAD)
untuk program Anda. NetBeans Mobility Pack menaruh file JAD pada folder "dist" dari
folder project. Berikut ini adalah contoh file JAD yang dibuat oleh NetBeans Mobility
Pack:

MIDlet-1: HelloMidlet, , HelloMidlet


MIDlet-Jar-Size: 1415
MIDlet-Jar-URL: ProjectHello.jar

Pengembangan Perangkat Mobile 5


J.E.N.I.

MIDlet-Name: ProjectHello
MIDlet-Vendor: Vendor
MIDlet-Version: 1.0
MicroEdition-Configuration: CLDC-1.1
MicroEdition-Profile: MIDP-2.0

Sekarang kita siap untuk mengcompile, melakukan pemaketan (package) pada aplikasi
MIDlet pertama kita.

2.4 Compilation dan Packaging MIDlets

Sebelum kita menggunakan integrated tools untuk mengcompile dan melakukan


packaging aplikasi MIDlet (MIDlet suite), kita akan mencoba menggunakan command
line.

Aplikasi MIDlet biasanya dipaketkan ke dalam sebuah file yaitu file JAR. File ini adalah
file terkompres, seperti file ZIP. Pada implementasinya, Anda dapat membuka file JAR
menggunakan program dekompresor file ZIP.

Aplikasi MIDlet terdiri dari:

− File JAR
− File Java Application Descriptor (JAD)

File JAR memiliki:

− File class
− Manifest file describing the contents of the archive
− File manifest yang menjelaskan isi dari arsip
− Sumber: image/icon, video, data, dll. Digunakan oleh aplikasi

File manifest, manifest.mf adalah seperti file JAD. File ini digunakan oleh appication
manager dari device. Beberapa field yang diperlukan oleh file manifest adalah:

− MIDlet-Name
− MIDlet-Version
− MIDlet-Vendor
− MIDlet-<n> (dimana n adalah angka dari 1, untuk setiap MIDlet di file JAR)

Pengembangan Perangkat Mobile 6


J.E.N.I.

− MicroEdition-Profile
− MicroEdition-Configuration

Selanjutnya kita mengcompile file source java:

javac -bootclasspath C:\WTK23\lib\cldcapi11.jar;C:\WTK23\lib\midpapi20.jar


*.java

Program Compiler Java, "javac", harus berada pada path Anda. Jika anda melihat error
seperti "cannot find file" atau "not an executable", Anda bisa mengkonsultasikan dengan
panduan instalasi untuk distribusi Java development kit Anda tentang bagaimana
memasukkan executable PATH dari lokasi tools yang ada di Java.

Selanjutnya kita melakukan pre-verify dari file class:

preverify
-classpath C:\WTK23\lib\cldcapi11.jar;C:\WTK23\lib\midpapi20.jar;.
-d . HelloMidlet

Preverify sudah berada di wireless toolkit dari java.sun.com. Masukkan perintah ini pada
sebuah baris.

Langkah terakhir adalah membuat file JAR tersebut:

jar cvfm HelloMidlet.jar manifest.txt HelloMidlet.class

Program jar sudah berada di Java Development Kit, dan lokasinya harus dimasukkan
pada executeable path Anda. Perintah ini akan membuat file JAR dengan nama file
HelloMidlet.jar. File manifest.txt namanya diganti dengan manifest.mf pada file JAR.

2.5 Menggunakan Sun Wireless Toolkit

Sekarang kita menggunakan Sun Wireless Toolkit untuk mengcompile dan memaketkan
aplikasi MIDlet / MIDlet suite (mengandung satu MIDlet)

Pengembangan Perangkat Mobile 7


J.E.N.I.

Buka ktoolbar (dari Wireless Toolkit distribution):

Buat sebuah project:

Pada Setting window, anda dapat merubah banyak pilihan-pilihan dari beberapa opsi
konfigurasi untuk project Anda. Anda dapat memilih konfigurasi yang akan bekerja,
package/API yang diperlukan, konfigurasi Push Registry dan yang lain. Untuk tujuan kita
kali ini, kita akan menggunakan konfigurasi default project. Click "OK" untuk selesai
membuat project.

Pengembangan Perangkat Mobile 8


J.E.N.I.

Copy HelloMidlet.java kedalam direktori "src": Pada jendela ini berada di direktori:
C:\WTK23\apps\HelloMidlet\src (dimana C:\WTK23 adalah lokasi Anda menginstall
wireless toolkit). Click "Build" dan "Run":

Pengembangan Perangkat Mobile 9


J.E.N.I.

Pengembangan Perangkat Mobile 10


J.E.N.I.

Pengembangan Perangkat Mobile 11


J.E.N.I.

2.6 Menggunakan NetBeans Mobility Pack

Seperti yang telah dijelaskan pada awal bab ini tentang hal yang diperlukan, NetBeans
4.1 dan NetBeans Mobility Pack harus sudah terinstall di komputer Anda.

Langkah 1: Membuat project baru

Pengembangan Perangkat Mobile 12


J.E.N.I.

Langkah 2: Memilih kategori "Mobile"

Pengembangan Perangkat Mobile 13


J.E.N.I.

Langkah 3: Memilih "Mobile Application"

Pengembangan Perangkat Mobile 14


J.E.N.I.

Langkah 4: Beri nama project dan tentukan lokasinya


(Hilangkan tanda pada "Create Hello MIDlet", kita akan membuat MIDlet kita sendiri
nantinya)

Step 5: Memilih Platform (optional)

Pengembangan Perangkat Mobile 15


J.E.N.I.

Gambar 1: Mobile Project yang baru dibuat (NetBeans Mobility Pack)

Pengembangan Perangkat Mobile 16


J.E.N.I.

Langkah 6: Membuat sebuah MIDlet baru

Pengembangan Perangkat Mobile 17


J.E.N.I.

Langkah 7: Memilih MIDP "Category" dan MIDlet "File Type"

Pengembangan Perangkat Mobile 18


J.E.N.I.

Langkah 8: Memberi nama MIDlet

Pengembangan Perangkat Mobile 19


J.E.N.I.

Langkah 9

Gambar 2: Membuat MIDlet secara otomatis membuat method MIDlet yang diperlukan

Pengembangan Perangkat Mobile 20


J.E.N.I.

Langkah 10: Mengganti code yang dibuat secara otomatis dengan code program
kita.

Pengembangan Perangkat Mobile 21


J.E.N.I.

Langkah 11: Mengcompile dan Menjalankan (Run) MIDlet di Emulator

Pengembangan Perangkat Mobile 22


J.E.N.I.

Langkah 12: Menjalankan MIDlet kita di Emulator

Pengembangan Perangkat Mobile 23


J.E.N.I.

Gambar 3: Hello World MIDlet

Pengembangan Perangkat Mobile 24


J.E.N.I.

2.7 Latihan
2.7.1 Multiple MIDlets dalam satu MIDlet suite

Tambahkan satu MIDlet baru pada project "ProjectHello". Perlu anda catat bahwa
NetBeans Mobility Pack secara otomatis menambahkan MIDlet baru pada aplikasi file
JAD ketika anda menggunakan "New File..." Wizard.

2.7.2 Multiple MIDlets dalam satu MIDlet suite menggunakan


Wireless Toolkit

Gunakan Sun Wireless Toolkit untuk menambahkan MIDlet baru pada aplikasi MIDlet
anda.

Pengembangan Perangkat Mobile 25


J.E.N.I.

Bab 3
High Level User Interface

3.1 Tujuan

Pada akhir pembahasan, para pembaca diharapkan dapat:


• Mengetahui keuntungan dan kerugian dengan menggunakan high-level dan low-level
UI classes
• Mengetahui desain MIDlets menggunakan komponen high-level UI
• Mengidentifikasi perbedaan sub-classes pada screen
• Mengetahui perbedaan item-item yang dapat dimasukkan kedalam sebuah object
Form

3.2 MIDP User Interface

MDIP user interface didesain untuk peralatan mobile. Aplikasi MDIP ditunjukan pada area
limited screen. Peralatan memory juga menjadi faktor penting jika perlengkapan mobile
hanya memiliki kapasitas memory yang kecil.

Dengan berbagai macam peralatan mobile, dari berbagai model mobile phones sampai
PDAs, MIDP user interface telah didesain untuk lebih fleksibel dan mudah digunakan
dalam berbagai macam peralatan ini.

MIDP mempunyai class yang dapat menangani fungsi high-level dan low-level user
interface. High-level UI interfaces didesain secara fleksibel. Penampilan dari komponen
ini tidak didefinisikan secara spesifik. Penampilan screen yang sebenarnya dari berbagai
macam komponen ini digunakan dari satu peralatan ke peralatan yang lain. Tetapi para
programmer telah teryakinkan oleh kegunaan dari high-level komponen UI interfaces
memiliki persamaan dalam berbagai spesifikasi-pengimplementasi secara keseluruhan.

High Level UI Low-Level UI


highly portable across devices Memungkinkan semua peralatan
look dan feel sama dengan peralatannya Spesifik aplikasi look and feel
Memiliki interaksi seperti scrolling yang Pengimplementasiannya harus dengan
dienkapsulasi petunjuk sendiri
Penampilannya tidak dapat digambarkan Penampilannya tidak dapat digambarkan
secara aktual dalam satuan pixel

Pengembangan Perangkat Mobile 1


J.E.N.I.

High Level UI Low-Level UI


Tidak memiliki akses untuk peralatan Mengakses masukkan low-level hanya
dengan feature yang spesifik dengan menekan

Gambar: Perbedaan High-Level UI dengan Low-Level UI

Kapan menggunakan High-Level UI


• Saat membangun aplikasi text-based yang mudah
• Saat Anda ingin aplikasi Anda dapat dengan mudah dipertukarkan dengan berbagai
macam peralatan (Portabilitas)
• Saat Anda ingin aplikasi Anda memiliki tampilan yang sama dengan komponen UI
yang lain dari berbagai peralatan
• Saat Anda ingin kode Anda dapat menjadi sesedikit mungkin, ketika sebuah interaksi
ditangani oleh API

Kapan menggunakan Low-Level UI


• Saat Anda memerlukan sebuah high-level untuk mengkontrol tampilan dari suatu
aplikasi
• Saat aplikasi Anda membutuhkan tempat yang tepat dari elemen-elemen yang ada
pada screen
• Saat membuat game secara grafik; meskipun Anda tetap dapat menggunakan high-
level UI pada menu game, hal tersebut lebih disarankan untuk membuat menu UI
Anda sendiri untuk menghindari seamless atmosphere bagi para user
• Saat sebuah aplikasi membutuhkan akses ke low-level yang memiliki inputan seperti
key presses
• Jika aplikasi Anda akan diimplementasikan pada layar navigasi Anda sendiri

3.2.1 Display

Inti dari MIDP user interfaces adalah display. Yang merupakan satu-satunya kemudahan
dari Display per MIDlet. MIDlet dapat mendapatkan referensi Display object dengan
menggunakan method static Display.getDisplay(), melewatkan referensi tersebut ke
MIDlet instance.

MIDlet dijamin dengan display object tidak akan berubah dengan adanya eksistensi
instance MIDlet. Hal ini berarti bahwa variebel dikembalikan (returned) ketika Anda
memanggil getDisplay() dan tidak akan berpengaruh jika anda memenggilnya dengan
startApp() atau destroyApp() (Lihat pada gambar Midlet Life Cycle).

Pengembangan Perangkat Mobile 2


J.E.N.I.

3.2.2 Displayable

Hanya satu displayable yang ditampilkan pada satu waktu. Secara langsung, displayable
tidak ditampilkan pada layar. Seuabh displayable dapat ditampilkan dengan memanggil
method setCurrent() dari Display instance. Method setCurrent() harus dipanggil pada
saat memulai aplikasi, dengan kata lain sebuah screen kosong akan ditampilkan atau
aplikasi tersebut tidak akan dijalankan.

Gambar: MIDlet Life Cycle

Method startApp dari MIDlet merupakan suatu tempat dimana Anda dapat menaruh
method pemanggil setCurrent(). Tetapi Anda harus mempertimbangkan bahwa dalam
MIDlet startApp() dapat dipanggil lebih dari satu kali. Untuk memberhentikan MIDlet
sementara waktu dapat dipause dengan memanggil fungsi pauseApp(), dengan adanya
incoming call, memungkinkan startApp() dipanggil lagi (setelah ada telepon masuk).
Maka dengan memanggil setCurrent() pada method pada startApp(), dan ada
kemungkinan layar akan menjadi gelap (blank) pada screen displayed yang sebelumnya,
sampai adanya penghentian sementara (pause by the phone call).

Sebuah displayable dapat memiliki nama, beberapa perintah(command),


commandListener dan Ticker.

Pengembangan Perangkat Mobile 3


J.E.N.I.

Gambar: Properti dari sebuah Displayable

3.2.3 Title

Sebuah Displayable memiliki title yang berhubungan dengan dirinya sendiri. Posisi dan
penampilan dari title tersebut merupakan piranti spesifik yang hanya dapat ditentukan
oleh peralatan dari aplikasi yang sedang dijalankan. Sebuah title ditampilkan pada
Displayable dengan memanggil setTitle().Dengan memanggil method ini maka seketika
akan meng-update title pada Displayable. Jika pada saat Displayable ditampilkan pada
layar, MIDP specification states menyebutkan bahwa title harus dirubah dengan
implementasi “Memungkinkan untuk dilakukan dengan cepat”.

Memberi parameter null pada setTitle() berarti menghapus title pada Displayable.
Merubah atau menghapus sebuah title dari Displayable dapat mempengaruhi ukuran
area untuk isi dari Displayable tersebut.Jika terjadi perubahan ukuran area terjadi,
MIDlet akan diberitahu dengan memanggil kembali method sizeChanged().

3.2.4 Command

Dengan adanya kekurangan ukuran pada screen, MIDP tidak menggambarkan sebuah

menu bar. Untuk menggantikan menu bar, MIDlet memiliki Commands. Biasanya
Command diimplementasikan sebagai soft key atau item dalam sebuah menu. Object
Command hanya berisi informasi tentang action yang harus dikerjakan pada saat
Command diaktifkan. Dia tidak berisikan kode yang akan dieksekusi pada saat

Pengembangan Perangkat Mobile 4


J.E.N.I.

Command tersebut dipilih.


Properti CommandListener dari Displayable berisi action yang akan dieksekusi saat
Command diaktifkan. CommandListener merupakan interface yang spesifik pada single
method :

public void commandAction(Command command, Displayable displayable)

Mapping dari Commands pada peralatan bergantung pada nomer yang telah ditetapkan
atau programable button pada peralatan. Jika nomer dari Command tidak benar pada
semua button, maka memungkinkan peralatan menaruh beberapa atau semua
Command pada menu dan peta pada menu dan button akan diberi label “Menu”.

Command exitCommand = new Command("Exit", Command.EXIT, 1);


Command newCommand = new Command("New Item", Command.OK, 1);
Command renameCommand = new Command("Rename Item", Command.OK, 1);
Command deleteCommand = new Command("Delete Item", Command.OK, 1);
...
list.addCommand(exitCommand);
list.addCommand(newCommand);
list.addCommand(renameCommand);
list.addCommand(deleteCommand);

Gambar: Listing program untuk mapping Commands kedalam Displayable

Pengembangan Perangkat Mobile 5


J.E.N.I.

Gambar: Contoh tampilan dari multiple Commands

Command memiliki sebuah short label, long label, tipe dan prioritas.

Command Label

Diasumsikan bahwa screen yang berukuran kecil dari target sebuah peralatan, selalu
menjadi faktor ketika membangun aplikasi MIDP. Asumsi ini juga dapat diterapkan untuk
Command label. Command label harus singkat, namun deskriptif, maka hal itu harus
benar pada screen dan tetap dapat dipahami oleh user.

Ketika long label ditentukan, hal tersebut akan ditampilkan kapan saja pada saat sebuah
implementasi sistem dilihat secara sesuai. Tidak ada pemanggilan API yang menetapkan
label yang akan ditampilkan. Hal tersebut juga memungkinkan bahwa sebuah Command
akan menampilkan short label pada saat Command lain pada screen yang sama
menampilkan long labels.

Command Type

Sebuah Command yang diperkenalkan pada peralatan sering disebut device-dependent.


Seorang programer dapat mengetahui spesifikasi tipe dari Command. Tipe ini akan
ditampilkan sebagai hint pada tempat Command diletakkan.

Berbagai macam tipe Command:

Command.OK, Command.BACK,
Command.CANCEL, Command.EXIT,
Command.HELP, Command.ITEM,
Command.SCREEN, Command.STOP

Pengembangan Perangkat Mobile 6


J.E.N.I.

Gambar: Tampilan Command yang berbeda pada implementasi telepon yang berbeda

Command Priority

Aplikasi dapat menetapkan spesifikasi Command yang penting pada priority property.
Hal ini merupakan integer property dan nilai rendah yang sangat penting. Priority
property juga hanya sebuah hint pada tempat dimana seharusnya Command
ditempatkan. Biasanya implementasi menentukan posisi dari Command oleh tipenya.
Jika terdapat lebih dari satu Command dari tipe yang sama, secara normal priority akan
mempertimbangkan penempatan Command.

3.2.5 CommandListener

CommandListener merupakan interface dengan single method:

void commandAction(Command command, Displayable displayable)

Method commandAction() akan dipanggil jika Command dipilih. Variabel Command


merupakan referensi Command yang telah dipilih. Tampilan merupakan Displayable
(atau screen) dimana Command ditempatkan dan saat action “pilih” terjadi.
CommandAction() harus dikembalikan dengan seketika, jika tidak maka pengeksekusian
aplikasi akan diblock. Hal ini dikarenakan, spesifikasi MIDP tidak memerlukan
implementasi untuk membuat sebuah pembatas untuk pengiriman event.

Pengembangan Perangkat Mobile 7


J.E.N.I.

3.2.6 Ticker

Ticker adalah sebuah baris dari text yang dapat discrolling secara terus-menerus pada
display. Method konstruktor dari ticker menerima text string untuk ditampilkan. Hal
tersebut hanya memiliki dua method lain, yaitu getter dan setter untuk text ini: String
getString() dan void setString(String text). Tidak ada cara lain pada sebuah aplikasi
untuk mengontrol kecepatan dan arah dari scrolling text. Scrolling tidak dapat dipause
atau distop.

Jika spasi diletakkan pada text, hal tersebut tidak akan ditampilkan pada layar. Semua
baris text akan ditampilkan sebagai single line dari scrolling text.

Sebuah ticker dapat dipasang pada Displayable dengan memanggil setTicker(). Jika
ticker telah ada pada Displayable, maka akan diganti oleh ticker yang baru yang
terdapat dalam parameter.

Memberi parameter null pada setTicker akan mengganti semua ticker yang telah
dimasukkan pada Displayable. Menghapus ticker dari Displayable dapat menyebabkan
perubahan ukuran area dari isi Displayable tersebut. Jika perubahan ukuran area terjadi,
maka MIDlet akan memanggil sebuah ukuran dengan method sizeChanged().

Pada ticker object Displayable boleh berbagi suatu kejadian(action).

3.2.7 Screen

Screen merupakan inti abstrak class yang digunakan untuk high-level UI ketika canvas
merupakan Displayable abstrak class untuk low-level UI.

Berikut ini empat subclasses dari abstract class screen : Form, TextBox, List dan Alert.

Pengembangan Perangkat Mobile 8


J.E.N.I.

Gambar: Displayable Class Heirarchy

3.2.8 Item

Items merupakan komponen yang dapat diletakan kedalam container, seperti Form atau
Alert. Sebuah item dapat memiliki property seperti dibawah ini:

Property Default Value


Label Dikelompokan pada subclass konstruktor
Commands -
defaultCommand null
ItemCommandListener null
Layout directive LAYOUT_DEFAULT
Preferred width and height -1 (unlocked)

Pengembangan Perangkat Mobile 9


J.E.N.I.

Gambar: Item Class Heirarchy

Spesifikasi layout dari item dengan Form. Direktif layout dapat dikombinasikan
menggunkan bitwise atau operasi (|). Bagaimanapun juga, beberapa direktif bersifat
mutually exclusive. Berikut ini direktif horizontal alignment yang mutually exclusive:
LAYOUT_LEFT
LAYOUT_RIGHT
LAYOUT_CENTER

Berikut ini direktif vertical alignment yang juga mutually exclusive:


LAYOUT_TOP
LAYOUT_BOTTOM
LAYOUT_VCENTER

Berikut ini layout yang lain dari direktif (tidak mutually exclusive):
LAYOUT_NEWLINE_BEFORE
LAYOUT_NEWLINE_AFTER
LAYOUT_SHRINK
LAYOUT_VSHRINK
LAYOUT_EXPAND
LAYOUT_VEXPAND
LAYOUT_2

3.3 Alert

Alert merupakan sebuah screen yang dapat menampilkan text dan gambar. Alert
merupakan komponen untuk menampilkan error dan warning, display text dan informasi
gambar atau untuk mendapatkan informasi dari user.

Alert ditampilkan untuk spesifikasi peeriode dari waktu. Waktu di-set menggunakan
method setTimeout() dan method tersebut dispesifikasikan dalam unit millliseconds. Hal
tersebut dapat dibuat untuk ditampilkan hingga user mengaktifkan perintah (“Done”)
dengan menspesifikasikan spesial timeout dari Alert.FOREVER.

Pengembangan Perangkat Mobile 10


J.E.N.I.

Alert juga dapat menampilkan komponen Gauge (Lihat pada Gauge item) sebagai
indikator.

Ketika alert berisi text yang tidak sesuai dengan screenful dan harus discroll, maka
secara otomatis alert menge-set ke modal(timeout di set kepada Alert.FOREVER).

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class AlertExample extends MIDlet implements CommandListener {


Display display;
Form mainForm;
Command exitCommand = new Command("Exit", Command.EXIT, 0);
Command okCommand = new Command("Ok", Command.OK, 0);
Gauge gauge = new Gauge(null, false, 5, 0);
Command[] commands = {
new Command("Alarm", Command.OK, 0),
new Command("Confirmation", Command.OK, 0),
new Command("Info", Command.OK, 0),
new Command("Warning", Command.OK, 0),
new Command("Error", Command.OK, 0),
new Command("Modal", Command.OK, 0)
};

Alert[] alerts = {
new Alert("Alarm Alert",
"Example of an Alarm type of Alert",
null, AlertType.ALARM),
new Alert("Confirmation Alert",
"Example of an CONFIRMATION type of Alert",
null, AlertType.CONFIRMATION),
new Alert("Info Alert",
"Example of an INFO type of Alert",
null, AlertType.INFO),
new Alert("Warning Alert",
"Example of an WARNING type of Alert, w/ gauge indicator",
null, AlertType.WARNING),

Pengembangan Perangkat Mobile 11


J.E.N.I.

new Alert("Error Alert",


"Example of an ERROR type of Alert, w/ an 'OK' Command",
null, AlertType.ERROR),
new Alert("Modal Alert",
"Example of an modal Alert: timeout = FOREVER",
null, AlertType.ERROR),
};

public AlertExample(){
mainForm = new Form("JEDI: Alert Example");

mainForm.addCommand(exitCommand);
for (int i=0; i< commands.length; i++){
mainForm.addCommand(commands[i]);
}
mainForm.setCommandListener(this);

// Menambah sebuah gauge dan menge-set timeout (milliseconds)


alerts[3].setIndicator(gauge);
alerts[3].setTimeout(5000);

// Menambah sebuah command untuk Alert


alerts[4].addCommand(okCommand);

// Menge-Set alert
alerts[5].setTimeout(Alert.FOREVER);
}

public void startApp() {


if (display == null){
display = Display.getDisplay(this);
display.setCurrent(mainForm);
}
}

public void pauseApp() {}

Pengembangan Perangkat Mobile 12


J.E.N.I.

public void destroyApp(boolean unconditional) {}

public void commandAction(Command c, Displayable d){


if (c == exitCommand){
destroyApp(true);
notifyDestroyed(); // Exit
}
for (int i=0; i<commands.length; i++){
if (c == commands[i]){
display.setCurrent(alerts[i]);
}
}
}
}

INFO Alert Modal Alert Alert w/ gauge indicator

Gambar: Perbedaan tipe-tipe Alert.

3.4 List

List merupakan subclass dari screen yang berisi sebuah daftar dari suatu pilihan. Sebuah
list dapat dibagi menjadi tiga tipe: IMPLICIT, EXCLUSIVE atau MULTIPLE.

Pengembangan Perangkat Mobile 13


J.E.N.I.

Jika List bertipe IMPLICIT dan user mengeksekusi tombol “select”, commandAction() dari
list commandListener akan dipanggil. Default perintahnya adalah
List.SELECT_COMMAND.

Untuk tipe IMPLICIT dan EXCLUSIVE, GetSelectedIndex() mengembalikan index dari


element yang dipilih. Untuk tipe MULTIPLE, getSelectedFlags() mengembalikan sebuah
array dari boolean yang berisi state dari elemen-elemen. isSelected(int index)
mengembalikan state dari elemen dalam pemberian posisi index.

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class ListExample extends MIDlet implements CommandListener {


Display display;
List list;
Command exitCommand = new Command("Exit", Command.EXIT, 1);
Command newCommand = new Command("New Item", Command.OK, 1);
Command renameCommand = new Command("Rename Item", Command.OK, 1);
Command deleteCommand = new Command("Delete Item", Command.OK, 1);
Ticker ticker = new Ticker(
"JEDI - Java Education and Development Initiative");

public ListExample(){
list = new List("JEDI: List Example", List.IMPLICIT);
list.append("List Item #1", null);
list.append("List Item #2", null);
list.append("List Item #3", null);

list.setTicker(ticker);

list.addCommand(exitCommand);
list.addCommand(newCommand);
list.addCommand(renameCommand);
list.addCommand(deleteCommand);
list.setCommandListener(this);

Pengembangan Perangkat Mobile 14


J.E.N.I.

public void startApp() {


if (display == null){
display = Display.getDisplay(this);
display.setCurrent(list);
}
}

public void pauseApp() {


}

public void destroyApp(boolean unconditional) {


}

public void commandAction(Command c, Displayable d){


if (c == exitCommand){
destroyApp(true);
notifyDestroyed(); // Exit
}
if (c == List.SELECT_COMMAND){
int index = list.getSelectedIndex();
String currentItem = list.getString(index);
// menjalanjan suatu hal
}
}
}

Pengembangan Perangkat Mobile 15


J.E.N.I.

List.IMPLICIT List.EXCLUSIVE List.MULTIPLE

Gambar: Tipe-tipe List

3.5 Text Box

TextBox merupakan sub-class dari screen yang dapat digunakan untuk mendapatkan
input text dari user. Hal ini memperbolehkan user untuk memasukan dan mengedit text.
TextBox hampir sama dengan TextField(Lihat pada item TextField) karena dia dapat
memiliki input constraint dan input modes. Perbedaannya dengan TextField adalah user
dapat memasukan garis baru(ketika input constraint di-set untuk semua “ANY”).

Isi dari TextBox dapat diambil kembali dengan menggunakan method getString().

Pengembangan Perangkat Mobile 16


J.E.N.I.

Gambar:TextBox tipe ANY (multi-line)

Gambar: TextBox dengan modifikasi PASSWORD

3.6 Form
Form merupakan subclass dari Screen. Form merupakan conntainer untuk item subclass,
seperti TextField, StringItem, ImageItem, DateField dan ChoiceGroup. Dia menghandle
layout untuk komponen ini. Dan juga menghandle traversal antar komponen-komponen
dan scrolling dari Screen.

Item ditambahkan dan dimasukkan ke dalam sebuah Form menggunakan method


append() dan insert(), berturut-turut.

Item direferensikan menggunakan index zero-based.

3.7 ChoiceGroup

Item Choicegroup merupakan group dari selectable choice. Sebuah choice boleh berisi
sebuah text, gambar atau kedua-duanya.

Choice boleh EXCLUSIVE (hanya satu pilihan yang dapat dipilih) atau MULTIPLE (banyak
pilihan yang dapat dipilih pada suatu waktu). Jika ChoiceGroup bertipe POPUP, hanya
satu choice yang ditampilkan. Popup selection akan ditampilkan ketika item ini dipilih.
Dari popup seleksi ini, user diperbolehkan memilih pilihannya. Choice yang ditampilkan
selalu choice yang dipilih.

Pengembangan Perangkat Mobile 17


J.E.N.I.

GetSelectedIndex() mengembalikan nilai index pada element dari ChoiceGroup yang


dipilih. GetSelectedFlags() mengembalikan sebuah array dariboolean yang merespon
elemen dari Choicegroup. isSelected(int index) mengembalikan state dari elemen yang
diberikan oleh posisi index.

choiceForm = new Form("Choice Group Types");


choiceForm.addCommand(exitCommand);
choiceForm.setCommandListener(this);

choiceExclusive = new ChoiceGroup("Exclusive", Choice.EXCLUSIVE);


choiceExclusive.append("Male", null);
choiceExclusive.append("Female", null);
choiceForm.append(choiceExclusive);

choiceMultiple = new ChoiceGroup("Multiple", Choice.MULTIPLE);


choiceMultiple.append("Apple", null);
choiceMultiple.append("Orange", null);
choiceMultiple.append("Grapes", null);
choiceForm.append(choiceMultiple);

choicePopup = new ChoiceGroup("Popup", Choice.POPUP);


choicePopup.append("Asia", null);
choicePopup.append("Europe", null);
choicePopup.append("Americas", null);
choiceForm.append(choicePopup);

Pengembangan Perangkat Mobile 18


J.E.N.I.

Gambar: Tipe dari Choice Group

3.8 Date Field

Komponen DateField digunakan untuk masukan tanggal dan waktu dari user. DateField
dapat diisi dengan date entry(mode DATE), time entry (mode TIME) atau keduanya
(mode DATE_TIME).

Method getDate() mengembalikan nilai suatu item. Dia akan mengembalikan nilai null
jika item tidak diinialisasi terlebih dahulu. Jika mode dari DateField adalah DATE,
komponen time dari pengembalian nilai akan di-set menjadi nol. Jika modenya adalah
TIME, komponen date akan di-set menjadi “Januari 1, 1970”.

dateForm = new Form("DateField Modes");


dateForm.addCommand(backCommand);
dateForm.setCommandListener(this);

DateField dateonly =
new DateField("Birthday (DATE)", DateField.DATE);
DateField timeonly =
new DateField("Set Alarm (TIME)", DateField.TIME);

Pengembangan Perangkat Mobile 19


J.E.N.I.

DateField datetime =
new DateField("Departure (DATE_TIME)", DateField.DATE_TIME);

dateForm.append(dateonly);
dateForm.append(timeonly);
dateForm.append(datetime);

DateField input modes Selecting a date Time input

Gambar: mode DateField dan input screens

3.9 String Item

StringItem merupakan komponen read-only. Dia terdiri dari label dan text.

Secara bebas StringItem menerima tampilan mode parameter. Tampilan dari mode
dapat berupa Item.PLAIN, Item.HYPERLINK atau Item.BUTTON.

Jika tampilan sebuah mode bertipe HYPERLINK atau BUTTON, default Command dan
ItemCommandListener harus di-set didalam Item.

stringForm = new Form("StringField Modes");


stringForm.addCommand(exitCommand);
stringForm.setCommandListener(this);

Pengembangan Perangkat Mobile 20


J.E.N.I.

StringItem plain = new StringItem("Plain", "Plain Text", Item.PLAIN);

StringItem hyperlink = new StringItem("Hyperlink", "http://www.sun.com",


Item.HYPERLINK);
hyperlink.setDefaultCommand(new Command("Set", Command.ITEM, 0));
hyperlink.setItemCommandListener(this);

StringItem button = new StringItem("Button", "Click me", Item.BUTTON);


button.setDefaultCommand(new Command("Set", Command.ITEM, 0));
button.setItemCommandListener(this);

stringForm.append(plain);
stringForm.append(hyperlink);
stringForm.append(button);

Gambar: StringItem

Pengembangan Perangkat Mobile 21


J.E.N.I.

3.10 Image Item

ImageItem merupakan Image sederhana yang dapat dimasukan kedalam komponen,


seperti Form.

ImageItem menerima item layout sebagai parameter (Lihat pada bagian Item):
public ImageItem(
String label,
Image img,
int layout,
String altText)

Konstruktor yang lain menerima tampilan mode yang bertipe Item.PLAIN,


Item.HYPERLINK atau Item.BUTTON (Lihat pada bagian StringItem):

public ImageItem(String label,


Image image,
int layout,
String altText,
int appearanceMode)

imageForm = new Form("ImageItem");


imageForm.addCommand(backCommand);
imageForm.setCommandListener(this);

try {
Image img = Image.createImage("/jeni.png");
ImageItem image =
new ImageItem("JENI", img, Item.LAYOUT_CENTER, "jeni logo");
imageForm.append(image);
} catch (Exception e){e.printStackTrace();}

File “jeni.png” sangat penting untuk dimasukan kedalam project dengan menggunakan
operating system's manager dan menaruh image tersebut kedalam direktori project
dibawah subdirektori “src”. Kemudian project direfresh dengan mengklik kanan nama
project dan pilih “Refresh Folders”.

Pengembangan Perangkat Mobile 22


J.E.N.I.

Gambar: ImageItem

Pengembangan Perangkat Mobile 23


J.E.N.I.

3.11 Text Field

TextField merupakan Item dimana user dapat memasukan encode. Beberapa batasan
exclusive yang dapat di-set yaitu:

TextField.ANY
TextField.EMAILADDR
TextField.NUMERIC
TextField.PHONENUMBER
TextField.URL
TextField.DECIMAL

Masukan tersebut juga dapat memiliki macam-macam modifikasi:

TextField.PASSWORD
TextField.UNEDITABLE
TextField.SENSITIVE
TextField.NON_PREDICTIVE
TextField.INITIAL_CAPS_WORD
TextField.INITIAL_CAPS_SENTENCE

Modifikasi dapat di-set dengan menggunakan bit-wise OR (|) operator (atau toggled
menggunakan bit-wise XOR operator ^) pada input constraint. Sebagai konsekuensinya,
modifikasi dapat diperoleh dari pengembalian nilai dari getConstraint() bit-wise operator
AND(&).

Sejak nilai modifikasi juga dikembalikan oleh getConstraint(), Masukan main constraint
dapat diekstrak dengan menggunakan bit-wise operator AND dengan
TextBox.CONSTAINT_mask dan nilai pengembalian dari getConstaints().

GetString() mengembalikan isi dari TextField sebagai nilai sebuah String.

textForm = new Form("TextField Types");


textForm.addCommand(backCommand);
textForm.setCommandListener(this);

TextField ANY = new TextField("ANY", "", 64, TextField.ANY);


TextField EMAILADDR =
new TextField("EMAILADDR", "", 64, TextField.EMAILADDR);
TextField NUMERIC =
new TextField("NUMERIC", "", 64, TextField.NUMERIC);
TextField PHONENUMBER =

Pengembangan Perangkat Mobile 24


J.E.N.I.

new TextField("PHONENUMBER", "", 64, TextField.PHONENUMBER);


TextField URL =
new TextField("URL", "", 64, TextField.URL);
TextField DECIMAL =
new TextField("DECIMAL", "", 64, TextField.DECIMAL);

textForm.append(ANY);
textForm.append(EMAILADDR);
textForm.append(NUMERIC);
textForm.append(PHONENUMBER);
textForm.append(URL);
textForm.append(DECIMAL);

Gambar: TextField Items

Pengembangan Perangkat Mobile 25


J.E.N.I.

3.12 Latihan
3.12.1 List Dinamis
Buatlah sebuah MIDlet yang memiliki List IMPLICIT sebagai Screen main. Masukan tiga
Command kedalam List ini - “Add Item”, “Remove Item” dan “Exit”. Comman “Add Item”
akan memberikan layanan pada user untuk memasukan list menggunakan TextBox,
kemudian insert item tersebut sebelum current item yang dipilih dari list. “Remove Item”
akan menghapus currently selected list item (getSelectedIndex). Command “Exit” akan
keluar dari program.

Pengembangan Perangkat Mobile 26


J.E.N.I.

Bab 4
Low Level User Interface

4.1 Tujuan
Setelah mempelajari bab ini, Pelajar diharapkan mampu untuk :

• Memahami event handling level rendah dalam MIDP


• Menggambar dan menampilkan teks, gambar, garis, kotak, dan sudut
• Menentukan warna, huruf, dan coretan untuk operasi menggambar
• Memahami dan menggunakan class Canvas dan Graphic
• Mengetahui bagaimana menggunakan GAME API
• Menggambar grafik berskala

4.2 Pengenalan
Pada bab sebelumnya, kita telah membahas tentang bagaimana cara membuat user
interface level tinggi seperti list, form, dan field input. Mereka bersifat user interface
level tinggi dan programmer tidak perlu khawatir tentang menggambar pixel layar
atau mengatur posisi teks pada layar. Semua program telah menetapkan jenis
komponen dan label elemen. Sistem tersebut akan menangani gambar pada layar,
scrolling dan layout.

Satu kelemahan ketika hanya menggunakan komponen user interface level tinggi
adalah program tidak memiliki kendali penuh sebuah layar. Ada saat dimana kita
ingin menggambar sebuah garis, gambar beranimasi dan mempunyai kendali untuk
mengatur pixel pada layar.

Pada bab ini, kita akan berhadapan langsung dengan layar. Kita akan mempelajari
class Canvas, dimana akan menjadi pendukung dari proses menggambar kita. Kita
juga akan menyelidiki ke dalam class Graphic, dimana memiliki metode untuk
menggambar garis, kotak, sudut, dan teks. Kita juga akan membahas huruf, warna
dan gambar.

Pengembangan Perangkat Mobile 1


J.E.N.I.

4.3 Canvas
Canvas adalah subclass dari Displayable. Itu adalah sebuah class abstrak yang harus
di-extend sebelum sebuah aplikasi dapat menggunakan fungsi-fungsi yang ada.

Canvas dapat digabungkan dengan subclass Displayable level tinggi yaitu Screen.
Program dapat pindah ke dan dari Canvas dan Screen.

Canvas menggambarkan metode-metode event handling kosong. Aplikasi harus


mengesampingkan mereka untuk handle event.

Class Canvas menggambarkan sebuah metode abstrak yang disebut paint(). Aplikasi
menggunakan class Canvas harus menyediakan sebuah implementasi untuk metode
paint().

4.3.1 Sistem Koordinat

Sistem koordinat dari Canvas adalah berbasis nol. Koordinat x dan y dimulai dengan
nol. Pojok kiri atas dari Canvas berkoordinat (0,0). Koordinat x bertambah dari kiri
ke kanan. Sedangkan koordinat y bertambah dari atas ke bawah. Metode getWidth()
dan getHeight() mengembalikan nilai lebar dan tinggi berturut-turut.

Pojok kanan bawah pada layar memiliki koordinat (getWidth()-1,getWidth()-1).


Setiap perubahan yang terjadi pada ukuran yang diberikan untuk area menggambar
pada Canvas dilaporkan kepada aplikasi oleh metode sizeChanged(). Ukuran yang
tersedia pada Canvas mungkin saja berubah jika ada pergantian antara mode layar
full dan normal atau penambahan dan pengurangan sebuah komponen seperti
Command.

Pengembangan Perangkat Mobile 2


J.E.N.I.

(0,0)
increasing x value

increasing y value

(getwidth()-1,getHeight()-1)

Gambar 1: Sistem Koordinat

Pengembangan Perangkat Mobile 3


J.E.N.I.

4.3.2 ”Hello,World!”

Gambar 2: Hello World MIDlet menggunakan canvas

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

public class HelloCanvasMIDlet extends MIDlet {

private Display display;

HelloCanvas canvas;

Command exitCommand = new Command("Exit", Command.EXIT, 0);

public void startApp() {

if (display == null){

canvas = new HelloCanvas(this, "Hello, world!");

display = Display.getDisplay(this);

Pengembangan Perangkat Mobile 4


J.E.N.I.

display.setCurrent(canvas);

public void pauseApp() {

public void destroyApp(boolean unconditional) {

protected void Quit(){

destroyApp(true);

notifyDestroyed();

class HelloCanvas extends Canvas implements CommandListener {

private Command exitCommand = new Command("Exit", Command.EXIT, 0);

private HelloCanvasMIDlet midlet;

private String text;

public HelloCanvas(HelloCanvasMIDlet midlet, String text) {

this.midlet = midlet;

this.text = text;

addCommand(exitCommand);

setCommandListener(this);

Pengembangan Perangkat Mobile 5


J.E.N.I.

protected void paint(Graphics g) {

// membersihkan layar dengan mengisi semua layar dengan warna putih

g.setColor(255, 255, 255 );

g.fillRect(0, 0, getWidth(), getHeight());

// mengatur warna tulisan dengan warna hitam

g.setColor(0, 0, 0);

// dan menulis sebuah text

g.drawString(text,

getWidth()/2, getHeight()/2,

Graphics.TOP | Graphics.HCENTER);

public void commandAction(Command c, Displayable d) {

if (c == exitCommand){

midlet.Quit();

Dengan midlet “Hello,World!”, kita membuat sebuah class yang ber-extend Canvas

class HelloCanvas extends Canvas implements CommandListener {

Kemudian kita menambahkan perintah (“Exit”) dan mengatur command listener nya.

addCommand(exitCommand);

setCommandListener(this);

Kita menciptakan command listener dengan mengimplementasikan class


CommandListener. Ini berarti membuat class yang memiliki metode commandAction.

Pengembangan Perangkat Mobile 6


J.E.N.I.

class HelloCanvas extends Canvas implements CommandListener {

...

public void commandAction(Command c, Displayable d) {

...

Inti dari program ini adalah metode paint(). Set pertama dari pemanggilan metode
adalah membersihkan layar.

g.setColor(255, 255, 255 );

g.fillRect(0, 0, getWidth(), getHeight());

Dan kemudian grafik memanggil metode drawString() untuk menampilkan


“Hello,World!” pada layar :

// mengatur warna tulisan dengan warna hitam

g.setColor(0, 0, 0);

// dan menulis sebuah text

g.drawString(text, getWidth()/2, getHeight()/2,

Graphics.TOP | Graphics.HCENTER);

4.3.3 Perintah

Seperti halnya list, textBox, dan form, Canvas juga mempunyai Command yang
disediakan dan dapat merespon untuk event Command. Langkah-langkah untuk
menambahkan Command ke dalam Canvas adalah sama :

Pengembangan Perangkat Mobile 7


J.E.N.I.

1. Buatlah objek Command.

private Command exitCommand = new Command("Exit", Command.EXIT, 0);

2. Gunakan useCommand() untuk menambahkan perintah ke dalam canvas(atau


Form, list, text box)

addCommand(exitCommand);

3. Gunakan setCommandListener() untuk mendaftarkan class mana yang akan


mendapat event command untuk perintah dalam Displayable.

setCommandListener(this);

4. Buatlah sebuah commandListener dengan mengimplementasikan class


commandListener dan menyediakan sebuah metode commandAction().

class HelloCanvas extends Canvas implements CommandListener {

...

public void commandAction(Command c, Displayable d) {

if (c == exitCommand){

// do something

Pengembangan Perangkat Mobile 8


J.E.N.I.

4.3.4 Event key

Subclass dari Canvas dapat merespon sebuah event tombol dengan metode-metode
sebagai berikut :

keyPressed(int keyCode) Dipanggil ketika kunci ditekan

keyRepeated(int keyCode) Dipanggil ketika kunci diulang

keyReleased(int keyCode) Dipanggil ketika kunci dilepas

Canvas mendefinisikan kode tombol ini : KEY_NUM0, KEY_NUM1, KEY_NUM2,


KEY_NUM3, KEY_NUM4, KEY_NUM5, KEY_NUM6, KEY_NUM7, KEY_NUM8,
KEY_NUM9, KEY_STAR, and KEY_POUND.

Untuk mendapatkan “String” nama sebuah kunci, gunakan metode getKeyName(int


keyCode).

4.3.5 Aksi Permainan

Masing-masing kode tombol bisa dipetakan menjadi sebuah aksi game. Sebuah key
code bisa dipetakan kepada aksi sebuah game. Class Canvas mendefinisikan aksi
game ini : UP, DOWN, LEFT, RIGHT, FIRE, GAME_A, GAME_B, GAME_C, GAME_D.
Sebuah program dapat menerjemahkan sebuah key code ke dalam aksi game
menggunakan metode getGameAction(keyCode).

Metode getKeyCode(int gameAction) mengembalikan key code yang berkaitan


dengan suatu aksi game. Sebuah aksi game dapat memiliki lebih dari satu key code
yang berkaitan dengannya. Jika terdapat lebih dari satu key code yang berkaitan
dengan aksi game, hanya satu key code yang akan dikembalikan.

Sebuah aplikasi perlu menggunakan getGameAction(int keyCode) daripada langsung


menggunakan kode tombol yang telah didefinisikan. Secara normal, jika suatu
program ingin merespon kunci “UP”, sebaiknya menggunakan kunci KEY_NUM2 atau
key code yang spesifik untuk tombol UP. Program menggunakan metode ini tidaklah
portable sejak sebuah perangkat memiliki layout kunci yang berbeda dan key code
yang berbeda pula. KEY_NUM2 mungkin menjadi kunci “UP” untuk sebuah

Pengembangan Perangkat Mobile 9


J.E.N.I.

perangkat, tetapi mungkin juga menjadi kunci “LEFT” untuk perangkat lainnya.
GetGameAction() akan selalu mengembalikan “UP”, tidak terikat pada kunci mana
yang ditekan selama dia adalah kunci “UP” di dalam konteks dari layout kunci
sebuah perangkat.

4.3.6 Event Pointer

Disamping dari event key, program MIDP juga dapat mengatasi event pointer. Hal ini
bersifat benar jika sebuah perangkat memiliki sebuah pointer dan hal tersebut
diimplementasikan di dalam sistem JAVA pada sebuah perangkat.

Metode hasPointerEvents() mengembalikan nilai true jika sebuah perangkat


mendukung pointer yang bersifat ditekan dan dilepaskan. Metode
hasPointerMotionEvents() mengembalikan nilai true jika sebuah perangkat
mendukung event gerakan dari pointer.

public boolean hasPointerEvents()


public boolean hasPointerMotionEvents()

Sebuah event dapat di-generate oleh aktivitas pointer sebagai berikut :


pointerPressed, pointerReleased dan pointerDragged. Sebuah aplikasi
mengesampingkan metode-metode yang untuk diperhatikan ketika event ini terjadi.
Koordinat (x,y) dari event (ketika pointer ditekan, dilepas atau digeser) ditetapkan
didalam metode-metode callback ini.

protected void pointerPressed(int x, int y)


protected void pointerReleased(int x, int y)
protected void pointerDragged(int x, int y)

4.4 Grafik
Class Graphic adalah class utama untuk menulis teks, menggambar, garis, kotak
dan sudut. Dia memiliki metode untuk menentukan warna, huruf, dan coretan.

4.4.1 Warna

Class Display memiliki metode untuk menentukan apakah sebuah perangkat memiliki
fasilitas yang mendukung layar berwarna atau layar monochrome pada sebuah
perangkat.

Pengembangan Perangkat Mobile 10


J.E.N.I.

public boolean isColor() Mengembalikan nilai true jika mendukung layar


berwarna dan sebaliknya.
public int numColors() Mengembalikan nomor warna(atau level abu-abu jika
sebuah perangkat tidak mendukung warna) yang
didukung sebuah perangkat

Untuk mengatur warna yang digunakan untuk metode grafik berikutnya, gunakan
metode setColor(). SetColor() memiliki dua bentuk:

public void setColor(int red, int green, int blue)

public void setColor(int RGB)

Pada bentuk pertama, Anda menentukan komponen warna merah, hijau, dan biru.
Pada bentuk kedua komponen warna ditentukan dalam bentuk 0x00RRGGBB.
Pemanggilan setColor(int) pada contoh berikut akan melakukan hal yang sama:

int red, green, blue;

...

setColor(red, green, blue);

setColor( (red<<16) | (green<<8) | blue );

Metode lainnya untuk memanipulasi warna adalah :

public int getColor() Mengembalikan warna terbaru dalam


bentuk integer.

public int getRedComponent() Mengembalikan komponen merah sebagai


warna terbaru

public int getGreenComponent() Mengembalikan komponen hijau sebagai


warna terbaru

public int getBlueComponent() Mengembalikan komponen biru sebagai

Pengembangan Perangkat Mobile 11


J.E.N.I.

public int getColor() Mengembalikan warna terbaru dalam


bentuk integer.

warna terbaru

public int getGrayScale() Mengembalikan nilai abu-abu sebagai


warna terbaru

public void setGrayScale(int value) Memilih nilai abu-abu untuk


mengganti operasi menggambar

4.4.2 Huruf

Sebuah huruf memiliki tiga atribut yaitu bentuk, type, dan ukuran. Huruf tidak
diciptakan oleh aplikasi. Sebagai gantinya, sebuah aplikasi meminta sistem untuk
memilih model atribut huruf dan sistem mengembalikan huruf yang sesuai dengan
model atribut yang diminta. Sistem tidak menjamin akan mengembalikan semua
atribut huruf yang dipilih. Jika sistem tidak memiliki huruf yang sesuai dengan
permintaan, dia akan mengembalikan sebuah huruf hampir mirip dengan atribut
yang diminta.

Huruf adalah sebuah class yang terpisah. Seperti yang dinyatakan di atas, aplikasi
tidak menciptakan objek huruf. Sebagai gantinya, metode-metode statis getFont()
dan getDefaultFont() digunakan untuk meminta sebuah huruf dari sistem.

public static Font Mengembalikan sebuah huruf


getFont(int face, int style, int size) dari sistem yang sesuai dengan
atribut

public static Font getDefaultFont() Mengembalikan huruf default yang


digunakan oleh sistem

public static Font Mengembalikan huruf yang


getFont(int fontSpecifier) digunakan untuk komponen UI level
tinggi. FontSpecifier bisa jadi :

FONT_INPUT_TEXT

atau

FONT_STATIC_TEXT

Pengembangan Perangkat Mobile 12


J.E.N.I.

Face adalah salah satu dari FACE_SYSTEM, FACE_MONOSPACE, atau


FACE_PROPORTIONAL.

Style bisa jadi STYLE_PLAIN atau kombinasi STYLE_BOLD, STYLE_ITALIC dan


STYLE_UNDERLINED. Kombinasi style ditentukan oleh penggunaan bitwise operator
OR (|). Sebuah style huruf tebal(bold) dan garis miring(italic) dideklarasikan sebagai
:

STYLE_BOLD | STYLE_ITALIC

Ukuran huruf bisa jadi : SIZE_SMALL, SIZE_MEDIUM, SIZE_LARGE

Metode ini mengembalikan atribut huruf tertentu:

public int getStyle()


public int getFace()
public int getSize()
public boolean isPlain()
public boolean isBold()
public boolean isItalic()
public boolean isUnderlined()

4.4.3 Style Coretan


Metode setStrokeStyle(int style) menetapkan style coretan bahwa akan digunakan
untuk menggambar garis, sudut, dan kotak. Style coretan tidak mempengaruhi teks,
gambar, dan operasi mewarnai.

public void setStrokeStyle(int style) Mengatur style coretan untuk


menggambar garis, sudut, kotak, dll

public int getStrokeStyle() Mengembalikan style coretan terbaru

Nilai valid untuk style adalah SOLID dan DOTTED.

Pengembangan Perangkat Mobile 13


J.E.N.I.

4.4.4 Clipping

Suatu bidang clipping adalah suatu kotak di dalam objek Graphics yang ada. Setiap
operasi grafik hanya akan mempengaruhi pixel-pixel didalam area clip. Pixel yang
berada diluar clipping tidak akan dipengaruhi oleh setiap operasi grafik.

public void Mengatur area clip yang


setClip(int x, int y, int width, int tersedia menjadi kotak,
height) ditentukan oleh koordinat

public int getClipX() Mengembalikan offset X dari area


clip yang tersedia, sehubungan
dengan awal mula dari konteks
grafik ini

public int getClipY() Mengembalikan offset Y dari area


clip yang tersedia

public int getClipWidth() Mengembalikan lebar dari area


clip yang tersedia

public int getClipHeight() Mengembalikan tinggi dari area


clip yang tersedia

4.4.5 Anchor Points

Teks digambar sesuai dengan sebuah anchor points. Metode drawString()


mengharap sebuah koordinat (x,y) sesuai dengan anchor points.

public void drawString(String str, int x, int y, int anchor)

Anchor harus suatu kombinasi horisontal yang konstan (LEFT,HCENTER, atau RIGHT)
dan vertikal yang konstan (TOP, BASELINE, atau BOTTOM). Horisontal dan vertikal
yang konstan harus dikombinasikan mengunakan operator bitwise OR (|). Ini berarti
menggambar teks berhubungan dengan baseline dan horisontal tengah akan
membutuhkan sebuah nilai anchor BASELINE | HCENTER.

Pengembangan Perangkat Mobile 14


J.E.N.I.

TOP | HCENTER

TOP | LEFT TOP | RIGHT

BASELINE | LEFT BASELINE | RIGHT

BOTTOM | LEFT BOTTOM | RIGHT

BOTTOM | HCENTER

BASELINE | HCENTER

Gambar 3: titik anchor teks

4.4.6 Menggambar Teks

Metode untuk menggambar teks dan karakter adalah :

Pengembangan Perangkat Mobile 15


J.E.N.I.

public void Menggambar teks dalam str


drawString(String str,
menggunakan warna dan huruf yang
int x,
int y, tersedia. (x,y) adalah koordinat titik
int anchor) anchor

public void Sama seperti drawString, kecuali ini hanya


drawSubstring(String str,
akan menggambar substring dari offset
int offset,
int len, (berbasis nol) dengan panjang length.
int x,
int y,
int anchor)
public void Menggambar karakter dengan warna dan
drawChar(char character,
huruf yang tersedia
int x,
int y,
int anchor)
public void Menggambar karakter dalam data array
drawChars(char[] data,
karakter, dimulai dari indeks offset dengan
int offset,
int length, panjang length
int x,
int y,
int anchor)

Berikut adalah beberapa metode dari Font yang berguna dalam menggambar teks:

public int getHeight() Mengembalikan tinggi teks dalam huruf ini.


Tinggi dikembalikan termasuk spasi ekstra.

Pengembangan Perangkat Mobile 16


J.E.N.I.

Hal ini memastikan bahwa dua teks


digambar dengan jarak ini dari titik anchor
ke titik anchor lainnya akan berisi cukup
ruang antara dua baris teks.

public int stringWidth(String str) Mengembalikan lebar total dalam pixel dari
ruang yang ditempati oleh string ini jika
digambar menggunakan huruf ini

public int charWidth(char ch) Mengembalikan lebar total dalam pixel dari
ruang yang ditempati oleh karakter ini jika
digambar menggunaka huruf ini

public int getBaselinePosition() Mengembalikan jarak dalam pixel antara


TOP dan BASELINE pada teks, berdasarkan
pada huruf ini

g.setColor(255, 0, 0); // merah

g.drawString("JEDI",

getWidth()/2, getHeight()/2,

Graphics.TOP | Graphics.HCENTER);

g.setColor(0, 0, 255); // biru

Font font = g.getFont();

g.drawString("Java Education & Development Initiative",

getWidth()/2, getHeight()/2+font.getHeight(),

Graphics.TOP | Graphics.HCENTER);

Pengembangan Perangkat Mobile 17


J.E.N.I.

Gambar 4: Hasil operasi drawString()

4.4.7 Menggambar garis

Satu-satunya metode grafik untuk menggambar garis didefinisikan sebagai :

public void drawLine(int x1, int y1, int x2, int y2)

Metode ini menggambar sebuah garis menggunakan warna yang tersedia dan
coretan antara koordinat (x1,y1) dan (x2,y2).

g.setColor(255, 0, 0); // red

// garis dari pojok kiri atas ke pojok kanan bawah layar

g.drawLine(0, 0, getWidth()-1, getHeight()-1);

g.setColor(0, 255, 0); // green

// garis horisontal pada tengah layar

g.drawLine(0, getHeight()/2, getWidth()-1, getHeight()/2);

g.setColor(0, 0, 255); // blue

Pengembangan Perangkat Mobile 18


J.E.N.I.

// garis horisontal pada bawah layar

g.drawLine(0, getHeight()-1, getWidth()-1, getHeight()-1);

g.setColor(0, 0, 0); // black

// garis dari pojok kiri bawah ke pojok kanan atas layar

g.drawLine(0, getHeight()-1, getWidth()-1, 0);

Gambar 5: hasil pemanggilan metode drawLine()

4.4.8 Menggambar kotak

Metode grafik untuk menggambar kotak adalah :

public void drawRect(int x, int y, int width, int height)


public void drawRoundRect(int x, int y,
int width, int height,
int arcWidth, int arcHeight)
public void fillRect(int x, int y, int width, int height)
public void fillRoundRect(int x, int y,
int width, int height,
int arcWidth, int arcHeight)

Metode drawRect() menggambar sebuah kotak dengan pojok kiri atas pada koordinat
(x,y) dan luas area (width+1 x height+1). Parameter yang sama ada bersama

Pengembangan Perangkat Mobile 19


J.E.N.I.

drawRoundRect(). Parameter tambahan arcWidth dan arcHeight adalah diameter


horisontal dan vertikal dari busur dari keempat sudut.

Jika Anda akan mengenali, definisi drawRect dan drawRoundRect menetapkan lebar
dari kotak yang digambar pada layar adalah dengan width+1 dan tingginya dengan
height+1. Hal ini sangat tidak intuitif, tetapi seperti itulah spesifikasi MIDP
menggambarkan metode ini. Untuk meng-agravate tidak konsistensi dari “off-by-
one” ini, metode fillRect dan fillRoundRect hanya mengisi sebuah area kotak (width x
height). Anda akan melihat ketidakcocokan ini jika anda memasukkan parameter
yang sama untuk drawRect dan fillRect (dan drawRoundRect vs fillRoundRect). Sisi
kanan dan bawah dari kotak digambar oleh kepalsuan drawRect di luar area yang
diisi oleh fillRect.
// menggunakan tinta hitam untuk drawRect
g.setColor(0, 0, 0);
g.drawRect(8, 8, 64, 32);

// menggunakan tinta kuning untuk fillrect


// untuk menampilkan perbedaan antara drawRect dan fillrect
g.setColor(255, 255, 0);
g.fillRect(8, 8, 64, 32);

Gambar 6: hasil dari penggunaan parameter yang sama untuk drawRect dan
fillRect

// mewarnai warna pena dengan warna hitam

g.setColor(0, 0, 0);

// menggambar kotak pada (4,8) dengan lebar 88 dan tinggi 44

Pengembangan Perangkat Mobile 20


J.E.N.I.

// kotak pada kiri atas

g.drawRect(4,8,88,44);

// elips pada kanan atas

g.drawRoundRect(108,8,88,44,18,18);

// kotak pada kiri bawah

g.fillRect(4,58,88,44);

// elips pada kanan bawah

g.fillRoundRect(108,58,88,44,18,18);

Gambar 7:drawRect(), fillRect(), drawRoundRect(), dan fillRoundRect()

Pengembangan Perangkat Mobile 21


J.E.N.I.

4.4.9 Menggambar Sudut

Metode untuk menggambar bundar atau eclips adalah :

public void drawArc(int x, Menggambar arc dengan pusat pada (x,y)


int y,
dan dimensi (width+1 x height+1). Arc
int width,
int height, digambar mulai dari startAngle dan
int startAngle, extend untuk derajat arcAngle. 0 derajat
int arcAngle) terletak pada jarum jam 3.

public void fillArc(int x, Mewarnai bidang bundar dan eclips yang


int y,
telah dibuat dengan warna yang tersedia.
int width,
int height,
int startAngle,
int arcAngle)

g.setColor(255, 0, 0);

g.drawArc(18, 18, 50, 50, 0, 360); // menggambar sebuah lingkaran

g.setColor(0, 255, 0);

g.drawArc(40, 40, 100, 120, 0, 180);

g.setColor(0, 0, 255);

g.fillArc(100, 200, 80, 100, 0, 90);

Pengembangan Perangkat Mobile 22


J.E.N.I.

Gambar 8: Hasil pemanggilan metode drawArc dan fillArc

4.4.10 Melukis gambar

Gambar digambar dengan metode drawImage()


public void drawImage(Image img, int x, int y, int anchor)

Selama dengan drawString, x dan y adalah koordinat titik anchor. Perbedaannya


adalah bahwa vertikal anchor tetap adalah VCENTER yang berdasar BASELINE.

Anchor harus berupa kombinasi dari horizontal constant(LEFT, HCENTER atau RIGHT)
dan vertical constant (TOP,VCENTER atau BOTTOM). Horizontal dan Vertical
Constants dikombinasikan dengan menggunakan operator bitwise OR(|).

Pengembangan Perangkat Mobile 23


J.E.N.I.

TOP | HCENTER

TOP | LEFT TOP | RIGHT

VCENTER | LEFT VCENTER | RIGHT

BOTTOM | LEFT BOTTOM | RIGHT

VCENTER | HCENTER BOTTOM | HCENTER

Gambar : Image Anchor Points

try {
Image image = Image.createImage("/jedi.png");
g.drawImage(image,
getWidth()/2, getHeight()/2,
Graphics.VCENTER | Graphics.HCENTER);
} catch (Exception e){}

Gambar : Output dari drawImage()

Pengembangan Perangkat Mobile 24


J.E.N.I.

4.5 Game API

4.5.1 Game API

Aplikasi games memiliki peranan utama pada aplikasi mobile. Sebagian besar
aplikasi dibuat pada pangsa pasar mobile adalah games. Action, strategy, board and
card games dan sebagainya, seluruhnya terdapat pada aplikasi mobile.

Sebagian besar produsen game telah membuat API tersendiri untuk berbagai fungsi
bermain game yang hanya akan bekerja pada handset yang dibuat oleh perusahaan
tersebut. Hal ini berarti bahwa sebuah game yang dibangun menggunakan API dari
salah satu produsen tidak akan berjalan pada device hasil produksi dari produsen
lain.

Untuk menjembatani perbedaan ini, MIDP versi 2 telah memiliki fungsionalitas dasar
yang secara spesifik ditujukan aplikasi game.

Class utama Game API dari MIDP adalah class GameCanvas. Class GameCanvas
merupakan perluasan dari class Canvas yang kita gunakan dalam pembuatan low –
level user interface. Dua kelemahan utama dari class Canvas dalam pemrograman
game adalah tidak memadainya kemampuan untuk mengatur proses repaint dan
ketidakmampuan untuk mengatur bagaimana pointer events serta quick keys
diteruskan pada canvas.

Komponen user interface dari MIDP umumnya berupa event driven. Events berupa
antrian berurutan dan diteruskan terhadap aplikasi satu persatu, beserta tunda
waktu antar waktu dimana event dibuat (key press).

GameCanvas memungkinkan aplikasi mengumpulkan events yang terbuat dan


melakukan proses repaint pada canvas dengan cepat. Struktur program menjadi
lebih bersih karena terdapat rangkaian perulangan utama dimana proses painting
dan pengumpulan events dilakukan.

GameCanvas menggunakan teknik double buffering. Seluruh proses pembuatan


interface dilakukan di off-screen buffer, kemudian di transfer dari area buffer
tersebut menuju area yang terlihat pada canvas. Aplikasi anda harus menggunakan
instance method dari class Graphics berupa method getGraphics(). Setiap
pemanggilan terhadap method ini mengembalikan sebuah instance baru dari off-
screen buffer yang anda gunakan dalam proses pembuatan user interface.

Untuk memperbaharui screen tersebut, anda harus memanggil flushGraphics() untuk


melakukan proses repaint secara cepat dengan isi dari off-screen buffer. Perhatikan
bahwa anda hanya perlu memanggil method getGraphics() sekali saja, karena
sebuah buffer teralokasi setiap kali anda memanggil method ini.

Pengembangan Perangkat Mobile 25


J.E.N.I.

MyCanvas.java :
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;

public class MyCanvas extends GameCanvas implements Runnable {


private boolean running;
private long delay;
private int currentX, currentY;
private int screenWidth;
private int screenHeight;

public MyCanvas() {
super(true);
screenWidth = getWidth();
screenHeight = getHeight();
currentX = screenWidth / 2;
currentY = screenHeight / 2;
delay = 20;
}

public void start() {


running = true;
Thread thread = new Thread(this);
thread.start();
}
public void stop() { running = false; }
// The Game Loop
public void run() {
Graphics g = getGraphics();
while (running == true) {
getInput();
drawScreen(g);
try { Thread.sleep(delay); } catch (InterruptedException ie) {}
}
}

private void getInput() {


int keyStates = getKeyStates();
if ((keyStates & LEFT_PRESSED) != 0) {
currentX = Math.max(0, currentX - 1);
}
if ((keyStates & RIGHT_PRESSED) != 0) {
currentX = Math.min(screenWidth, currentX + 1);
}
if ((keyStates & UP_PRESSED) != 0) {
currentY = Math.max(0, currentY - 1);
}
if ((keyStates & DOWN_PRESSED) != 0) {
currentY = Math.min(screenHeight, currentY + 1);
}
}

private void drawScreen(Graphics g) {


g.setColor(0xffffff);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(0x0000ff);
g.drawString("JEDI", currentX, currentY,
Graphics.TOP|Graphics.LEFT);
flushGraphics();
}
}

Pengembangan Perangkat Mobile 26


J.E.N.I.

GameMidlet.java:
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class GameMidlet extends MIDlet {


private Display display;
public void startApp() {
display = Display.getDisplay(this);
MyCanvas gameCanvas = new MyCanvas();
gameCanvas.start();
display.setCurrent(gameCanvas);
}
public Display getDisplay() {
return display;
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
exit();
}
public void exit() {
System.gc();
destroyApp(false);
notifyDestroyed();
}
}

4.5.2 Layers

Layers adalah elemen visual dari sebuah screen. Layer adalah abstract class yang
merepresentasikan objects pada screen. Sprite dan TiledLayer adalah subclasses dari
class Layer.

Tiled Layer adalah rangkaian dari beberapa persegi empat yang berukuran sama dan
gambar – gambar yang memadai untuk ditempatkan pada persegi empat tersebut.
Layer ini dibangun dengan menempatkan gambar – gambar dan elemen – elemen
visual dalam area ini. Sebuah gambar dapat digunakan oleh lebih dari satu persegi
empat sehingga dapat menghemat ruang dan memory. Tiled Layers umumnya
digunakan sebagai background pada game.

4.5.3 Sprites

Sprites adalah objects grafis yang anda lihat pada game. Object ini dapat berupa
character, kunci, tombol, pintu ataupun peluru. Sebuah sprite bersifat statis ataupun
animasi.

Animasi sprite terbuat dari beberapa elemen sprite dengan perbedaan – perbedaan
kecil dan tersusun sedemikian hingga membentuk kesan bergerak. Rangkaian sprite
ini disebut sebagai frame.

Pengembangan Perangkat Mobile 27


J.E.N.I.

Contoh kode berikut ini (dari Project Game2) mendemonstrasikan cara penggunaan
sprites. Program ini menggunakan sprite sederhana dengan dua frame. Frame
ditampilkan menurut penekanan tombol oleh user (UP, DOWN, LEFT atau RIGHT).

GameCanvas dengan Sprite :

import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;

public class MyCanvas extends GameCanvas implements Runnable {


private boolean running;
private long delay;
private int currentX, currentY;
private int screenWidth;
private int screenHeight;
private Sprite sprite;

public MyCanvas() throws Exception {


super(true);
screenWidth = getWidth();
screenHeight = getHeight();
currentX = screenWidth / 2;
currentY = screenHeight / 2;
delay = 20;
Image image = Image.createImage("/jedi.png");
sprite = new Sprite(image, 32, 32);
}

public void start() {


running = true;
Thread thread = new Thread(this);
thread.start();
}
public void stop() { running = false; }
// The Game Loop
public void run() {
Graphics g = getGraphics();
while (running == true) {
getInput();
drawScreen(g);
try { Thread.sleep(delay); } catch (InterruptedException ie) {}
}
}

private void getInput() {


int keyStates = getKeyStates();
sprite.setFrame(0);
if ((keyStates & LEFT_PRESSED) != 0) {
currentX = Math.max(0, currentX - 1);
sprite.setFrame(0);
}

Pengembangan Perangkat Mobile 28


J.E.N.I.

if ((keyStates & RIGHT_PRESSED) != 0) {


currentX = Math.min(screenWidth, currentX + 1);
sprite.setFrame(1);
}
if ((keyStates & UP_PRESSED) != 0) {
currentY = Math.max(0, currentY - 1);
sprite.setFrame(1);
}
if ((keyStates & DOWN_PRESSED) != 0) {
currentY = Math.min(screenHeight, currentY + 1);
sprite.setFrame(0);
}
}

private void drawScreen(Graphics g) {


g.setColor(0xffffff);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(0x0000ff);
sprite.setPosition(currentX, currentY);
sprite.paint(g);

flushGraphics();
}
}

Pengembangan Perangkat Mobile 29


J.E.N.I.

4.5.4 LayerManager

Class LayerManager akan memberikan kemudahan dalam pengaturan keseluruhan


Sprites dan TiledLayers. LayerManager mengatur seluruh Sprites dan TiledLayers
yang anda buat. Dan anda tidak perlu untuk membuat seluruh object tersebut satu
persatu. LayerManager yang akan melakukannya untuk anda. LayerManager juga
mengatur pengurutan objek dari dasar hingga paling atas.

4.6 Scalable 2D Graphics


JSR 226 menyediakan method untuk proses rendering dan transforming atas grafis
vector-based 2D.

Format gambar raster-based seperti GIF melakukan proses encode terhadap


pewarnaan pada tiap-tiap pixel pada area persegi empat yang menunjukkan bentuk
gambar. Gambar dengan tipe vector-based hanya memiliki instruksi penggambaran
yang menentukan bagaimana pixel-pixel dari gambar tersebut harus diwarnai.
Vector tersebut merepresentasikan sebuah gambar yang berukuran jauh lebih kecil,
sebuah nilai lebih dalam penggunaan resource pada mobile devices.

4.7 Latihan
4.7.1 Key Codes

Buatlah sebuah MIDlet yang akan menampilkan kode dan nama dari tombol yang
ditekan oleh user. Gunakan sebuah Canvas dan tempatkan keterangan kode dan
nama tepat di tengah dari tampilan pada layer.

Pengembangan Perangkat Mobile 30


J.E.N.I.

Pengembangan Perangkat Mobile 31


J.E.N.I.

Bab 5
Persistence
MIDP menyediakan sebuah API dimana program dapat menyimpan data-data
aplikasi secara lokal didalam device tersebut. MIDP Record Management System
adalah sebuah fasilitas yang dimiliki oleh MIDlets untuk menyimpan data-data
aplikasi pada saat MIDlet invocations. Data akan disimpan dalam non-volatile
memory didalam device. Hal ini berarti, data-data program yang telah disimpan
tidak akan hilang walaupun program di restart maupun device dimatikan.

5.1 Tujuan

Pada akhir pembelajaran, siswa diharapkan dapat:

• Memahami mengenai konsep dari Record Store

• Membuat dan membuka sebuah Record Store

• Menambah, memanggil kembali, mengupdate, dan mendelete record

• Memanggil record satu persatu (enumerate) record dengan menggunakan


RecordEnumerate

• Membuat sebuah Record Comparator

• Membuat sebuah Record Filter

5.2 Record Store

Sebuah Record Store adalah sebuah koleksi daripada record-record. Record Id


didalam Record Store selalu unique. Record Id akan secara otomatis dialokasikan
pada saat pembentukan sebuah record dan bertindak sebagai index atau primary
key. Pemberian record Id dilaksanakan secara sekuensial dan nilai yang diberikan
kepada record Id pertama pada setiap Record Store adalah 1 (satu).

Pada saat sebuah record dihapus, record id-nya tidak akan bisa digunakan kembali.
Jika kita membuat empat buah record dan menghapus record ke-empat, maka
record Id selanjutnya yang akan diberikan oleh system adalah 5 (lihat gambar)

Pengembangan Perangkat Mobile 1


J.E.N.I.

Record ID Byte array


1 Data dari record #1
2 Data dari record #2
3 Data dari record #3
5 Data dari record #5

MIDlets dapat menciptakan lebih dari satu Record Store. Nama dari sebuah record
store didalam MIDlet suite haruslah unique. Nama dari record store juga case
sensitive dan memiliki panjang maksimal 32 karakter.

Pada saat MIDlet suite dihapus dari sebuah device, maka semua record store yang
terkoneksi dengan MIDlet didalam suite tersebut juga akan terhapus.

Membuat dan membuka sebuah Record Store

Method-method dibawah ini digunakan untuk membuat dan membuka sebuah record
store:

static RecordStore openRecordStore(String recordStoreName,


boolean createIfNecessary)
static RecordStore openRecordStore(String recordStoreName,
boolean createIfNecessary, int authmode,
boolean writable)
static RecordStore openRecordStore(String recordStoreName,
String vendorName, String suiteName)

Jika createIfNecessary di-set menjadi true dan Record Store belum ada, maka
Record Store akan dibangun. Jika createIfNecessary di-set menjadi false dan Record
Store tersebut belum dibuat, maka sebuah RecordStoreNotFoundException akan
dijalankan.

Authmode paramater dapat di-set menjadi RecordStore.AUTHMODE_PRIVATE


atau RecordStore.AUTHMODE_ANY. Penggunaan AUTHMODE_PRIVATE akan
menyebabkan Record Store hanya mampu diakses oleh MIDlet suite si
pemilik MIDlet. Sedangkan setting authmode ke AUTHMODE_ANY akan
menyebabkan Record Store untuk diakses oleh MIDlet manapun. Access mode
ini dispesifikasikan oleh sebuah writable boolean parameter. Untuk
memperbolehkan MIDlet yang lain (diluar MIDlet suite) untuk menggunakan
record store tersebut, parameter ini harus diubah menjadi true.

Penggunaan bentuk pertama dari method openRecordStore()akan menyebabkan


Record Store untuk dapat diakses oleh MIDlet-MIDlet didalam suite yang
sama (authmode di-set ke AUTHMODE_PRIVATE).

Untuk membuka sebuah Record Store dari MIDlet suite yang berbeda,
bentuk ketiga dari method openRecordStore harus digunakan. Anda harus
menspesifikasikan nama vendor (vendorName) dan nama dari Midlet suite
(suiteName).

Pengembangan Perangkat Mobile 2


J.E.N.I.

Jika sebuah Record Store terlanjur dibuka, method ini akan


mengembalikan reference kepada record store tersebut. System akan tetap
menghitung berapa kali Record Store telah dibuka dan setiap Record
Store harus ditutup dengan jumlah yang sama pada saat ia dibuka.

Menambahkan sebuah record

int addRecord(byte[] data, int offset, int numBytes)

Method addRecord akan membuat record yang baru didalam Record Store dan akan
mengembalikan record ID.

Mengambil kembali Record

byte[] getRecord(int recordId)


int getRecord(int recordId, byte[] buffer, int offset)
int getRecordSize(int recordId)

Bentuk pertama dari method getRecord akan mengembalikan copy dari data stored
yang ada didalam record tertentu berdasarkan RecordID. Bentuk kedua akan meng-
copy data pada paramater byte array yang telah disediakan. Pada saat
menggunakan bentuk kedua, byte array tersebut haruslah dialokasikan terlebih
dahulu. Jika ukuran dari record lebih besar daripada ukuran dari parameter, maka
akan terjadi ArrayIndexOutOfBoundsException. Anda akan menggunakan method
getRecordSize secara berurutan untuk mengetahui ukuran dari record sebelum Anda
mulai untuk membacanya.

Meng-update sebuah Record

Anda tidak dapat memodifikasi hanya sebagian dari data record. Jika Anda ingin
untuk memodifikasi sebuah record Anda harus:
1. Membaca tiap record dengan menggunakan getRecord
2. Meng-update record didalam memory
3. Memanggil setRecord untuk mengupdate data record

void setRecord(int recordId, byte[] newData, int offset,


int numBytes)

Menghapus Record

void deleteRecord(int recordId)

Pada saat sebuah record dihapus, record Id akan digunakan kembali di pemanggilan
berikutnya pada addRecord. Hal ini berarti, ada sebuah celah didalam Record Id.
Oleh karena itu, tidak disarankan untuk menggunakan counter increment untuk

Pengembangan Perangkat Mobile 3


J.E.N.I.

membuat list dari keseluruhan record didalam record store. Anda harus
menggunakan Record Enumerator untuk mengetahui tiap record didalam sebuah list
store.

Menutup sebuah Record Store

void closeRecordStore()

Record store yang akan ditutup dengan cara pemanggilan method


closeRecordStore() tidak akan benar-benar ditutup sampai closeRecordStore()
dipanggil sejumlah pemanggilan dari openRecordStore() sebelumnya. Pemanggilan
closeRecordStore() lebih dari jumlah pemanggilan openRecordStore() akan berakibat
exception RecordStoreNotOpen.

Potongan kode dari contoh RmsExample1 adalah MIDlet sederhana yang


mendemonstrasikan bagaimana untuk membuat sebuah record store, menambah
record, dan memanggil kembali semua record didalam record store:

// Buka dan buatlah record store dengan nama “RmsExample1”


recStore= RecordStore.openRecordStore("RmsExample1", true);

// Masukkan content kedalam record store


for(int recId=1; recId<=recStore.getNumRecords(); recId++){

// getRecord memiliki return value berupa panjang dari record


recLength = recStore.getRecord(recId, data, 0);

// Mengkonversikan byte array menjadi String


String item = new String(data, 0, recLength);
...
}

...
// Ini adalah String yang akan kita masukkan kedalam record
String newItem = "Record #" + recStore.getNextRecordID();

// Konversikan String ke byte array


byte[] bytes = newItem.getBytes();

// Tulislah record kedalam record store


recStore.addRecord(bytes, 0, bytes.length);

Tips Pemrograman:

1. Record ID dimulai dari 1, bukan 0. Oleh karena itu, apabila menggunakan loop,
ingatlah untuk menggunakan 1 sebagai index pertama dan bukan 0.
2. Lebih baik digunakan Record Enumerator daripada menggunakan index
incrementing (seperti contoh). Record yang telah dihapus, tetapi masih tetap
ingin dibaca pada contoh disini akan menyebabkan InvalidRecordIDException.

Pengembangan Perangkat Mobile 4


J.E.N.I.

Mendapatkan list dari Record Store didalam MIDlet Suite

static String[] listRecordStores()

Method ini akan mengembalikan array dari nama record store tersebut yang dimiliki
oleh MIDlet suite. Jika MIDlet suite tidak memiliki sebuah Record Store, maka
method ini akan memiliki nilai pengembalian null.

String[] storeNames = RecordStore.listRecordStores();


System.out.println("Record Stores for this MIDlet suite:");

for (int i=0; storeNames != null && i<storeNames.length; i++){


System.out.println(storeNames[i]);
}

Contoh: RmsListStores

Record Stores for this MIDlet suite:


Prefs
RmsExample1
RmsExample2

Contoh output dari RmsListStores

Urutan penamaan yang akan dikembalikan tidak akan didefinisikan dan akan
diimplementasikan secara independent. Oleh karena itu, apabila Anda ingin untuk
menampilkan nama tersebut secara alphabetic, maka Anda harus melakukan sorting
array terlebih dahulu.

Menyimpan Data Primitif Java

Sejauh ini, data yang telah dibuat dan dibaca dari Record Store adalah berupa
String. CLDC memiliki standard classes dalam manipulasi data primitif. Class
tersebut berasal dari standard library platform Java 2, yaitu Standard Edition (J2SE).

Anda dapat menulis data Java primitif dengan mengkombinasikan class


ByteArrayOutputStream dan DataOutputStream. Pembacaan tipe data primitive(int,
long, short, string, Boolean, dan sebagainya) dapat pula dilakukan dengan
menggunakan ByteArrayInputStream dan DataInputStream.

ByteArrayOutputStream out = new ByteArrayOutputStream();


DataOutputStream dOut = new DataOutputStream(out);
// Menyimpan sebuah integer
dOut.writeInt(recStore.getNextRecordID() * recStore.getNextRecordID());
// Menyimpan sebuah string
dOut.writeUTF("Record #" + recStore.getNextRecordID());
byte[] bytes = out.toByteArray();
// Menuliskan Record pada Store
recStore.addRecord(bytes, 0, bytes.length);
...

Pengembangan Perangkat Mobile 5


J.E.N.I.

// Menuju Record selanjutnya


byte[] recBytes = enumerator.nextRecord();
ByteArrayInputStream in = new ByteArrayInputStream(recBytes);
DataInputStream dIn = new DataInputStream(in);
int count = dIn.readInt();
String item = dIn.readUTF();

Method lain untuk Record Stores

long getLastModified()
int getVersion()

Sistem merekam bilamana sebuah Record Store mengalami modifikasi terakhir.


Method getLastModified memberikan informasi bahwa sebuah Record Store
mengalami perubahan terakhir, dalam bentuk long dan sesuai format yang
digunakan oleh System.currentTimeMillis().

Seluruh Record Store memiliki version information. Setiap kali sebuah record
mengalami modifikasi, maka version number juga akan terupdate. Penggunaan
method addRecord, setRecord dan deleteRecord menyebabkan penambahan version
number dari record store tersebut.

static void deleteRecordStore(String recordStoreName)


Menghapus record store.
String getName()
Mengetahui nama dari RecordStore.
int getNextRecordID()
Mengetahui recordId dari record selanjutnya untuk
disimpan pada record store.
int getNumRecords()
Mendapatkan jumlah record yang terdapat pada
Record Store.
int getSize()
Mengetahui space (dalam bytes) yang dipakai oleh
record store.
int getSizeAvailable()
Mengetahui sisa space yang tersedia (dalam
bytes).
void setMode(int authmode, boolean writable)
Mengubah access mode dari RecordStore.

Pengembangan Perangkat Mobile 6


J.E.N.I.

5.3 Record Enumeration

Memeriksa sebuah record store menggunakan incerementing index adalah tidak


efisien. Record stores yang telah dihapus akan terlewati jika Record Id dari record
tersebut tidak digunakan kembali.

Penggunaan record enumeration dapat menyelesaikan permasalahan tersebut


dengan melakukan pemeriksaaan pada record yang telah dihapus. Anda juga dapat
mengurutkan enumerasi dengan menggunakan method pembanding. Dengan
penggunaan method pembanding, anda dapat melewati record yang tidak
diharapkan pada output.

RecordEnumeration enumerateRecords(RecordFilter filter,


RecordComparator comparator, boolean keepUpdated)

Method enumerateRecords dari sebuah record store akan menghasilkan enumerasi


untuk memeriksa seluruh record pada sebuah record store. Ini adalah cara yang
direkomendasikan untuk melewatkan seluruh record dalam record store. Filter dan
Comparator akan dibahas dalam pembahasan selanjutnya.

Cara paling sederhana dalam menggunakan method ini adalah memberikan nilai null
untuk filter dan comparator. Hal ini akan menghasilkan enumerasi dari seluruh
record pada sebuah store dalam urutan acak.

// Membuka atau membuat sebuah record store dengan nama "RmsExample2"


recStore = RecordStore.openRecordStore("RmsExample2", true);

// Mengambil isi dari record store


RecordEnumeration enumerator
= recStore.enumerateRecords(null, null, false);
while (enumerator.hasNextElement()){
// Mendapatkan record selanjutnya dan konversi byte array menjadi string
String item = new String(enumerator.nextRecord());
// Area kode manipulasi record
...
}

5.4 Record Comparator

Pengurutan sebuah enumerasi dapat didefinisikan menggunakan sebuah Record


Comparator. Record Comparator digunakan pada method enumerateRecords. Jika
anda ingin mengurutkan output dari enumerasi, anda harus membuat comparator
dan mengimplementasikannya sebagai parameter kedua pada enumerateRecords.

int compare(byte[] rec1, byte[] rec2)

Pengembangan Perangkat Mobile 7


J.E.N.I.

Untuk membuat sebuah record comparator, anda harus mengimplementasikan


interface RecordComparator. Interface tersebut mendefinisikan method tunggal,
compare(byte[] rec1, byte[] rec2). Method ini harus menghasilkan return value,
RecordComparator.FOLLOWS atau RecordComparator.PRECEDES.

RecordComparator.EQUIVALENT harus dihasilkan jika rec1 adalah ekuivalen terhadap


rec2 dalam pengurutan.

// Membuat enumerasi, diurutkan menurut alfabet


RecordEnumeration enumerator
= recStore.enumerateRecords(null, new AlphaOrder(), false);
...

// Pengurutan menurut alfabet


class AlphaOrder implements RecordComparator {
public int compare(byte[] rec1, byte[] rec2){
String record1 = new String(rec1).toUpperCase();
String record2 = new String(rec2).toUpperCase();
if (record1.compareTo(record2) < 0){
return(PRECEDES);
} else {
if (record1.compareTo(record2) > 0){
return(FOLLOWS);
} else {
return(EQUIVALENT);
}
}
}
}

5.5 Record Filter

Contoh – contoh selama ini membaca seluruh record dari sebuah store. Kita dapat
menggunakan sebuah filter untuk mendapatkan hanya record yang kita inginkan.

Program Anda harus mengimpelementasikan method match() untuk menyeleksi


record. Method tersebut akan menghasilkan nilai true jika record sesuai dengan
criteria.

boolean matches(byte[] candidate)

public boolean matches(byte[] candidate){


boolean isaMatch = false;
try {
ByteArrayInputStream bin = new ByteArrayInputStream(candidate);
DataInputStream dIn = new DataInputStream(bin);

Pengembangan Perangkat Mobile 8


J.E.N.I.

int count = dIn.readInt();


String item = dIn.readUTF();
// mendapatkan record dengan akhiran “0”
if (item.endsWith("0")){
isaMatch = true;
} else {
isaMatch = false;
}
} catch (Exception e){items.append(e.toString(), null); }
return(isaMatch);
}

5.6 Record Listener

Sebuah Record Store dapat menggunakan lebih dari satu record listener. Record
listener adalah object yang dipanggil pada saat sebuah record ditambahkan, diubah
atau dihapus dari record store. Record listeners harus mengimplementasikan
interface RecordListener.

Record Listener diregristrasikan pada record store menggunakan method


addRecordListener(). Pada saat sebuah record store ditutup, seluruh record listener
yang terkait juga akan dihapus.

Penggunaan method deleteRecordStore() tidak akan menghasilkan pemanggilan


recordDeleted() pada record listener manapun yang terkait.

void recordAdded(RecordStore recordStore, int recordId)


Dipanggil saat sebuah record ditambahkan pada record store.

void recordChanged(RecordStore recordStore, int recordId)


Dipanggil setelah sebuah record pada record store diubah.

void recordDeleted(RecordStore recordStore, int recordId)


Dipanggil setelah sebuah record dihapus dari record store.

Pengembangan Perangkat Mobile 9


J.E.N.I.

5.7 Latihan
5.7.1 Penyimpanan Pilihan

Buat sebuah class yang dapat melangsungkan pemilihan pada program. Class
tersebut akan menyimpan pilihan pada sebuah Record Store. Setiap record akan
memiliki variabel name dan value. Setiap pasangan variabel disimpan pada sebuah
record. Name dan value disimpan pada database sebagai string.

Class Anda harus mengimplementasikan method sebagai berikut :

public String readVar(RecordStore recStore, String name, String defaultValue){


public void writeString(RecordStore recStore, String name, String value);

Pengembangan Perangkat Mobile 10


J.E.N.I.

Bab 6
Jaringan
Pada bagian ini, kita akan belajar bagaimana menerapkan sebuah MIDlet yang
mempunyai kemampuan untuk koneksi kedalam jaringan.

Pada bagian akhir dari sesi ini, siswa diharapkan dapat:


• Mendeskripsikan Generic Connection Framework, dan bagaimana ia dapat
digunakan untuk mendukung method koneksi yang berbeda-beda.
• Menspesifikasikan parameter-parameter koneksi dengan menggunakan format
pengalamatan GCF URL
• Membuat koneksi HTTP/HTTPS
• Menciptakan MIDlet dengan menggunakan TCP sockets dan UDP datagram

6.1 Generic Connection Framework

Generic Connection Framework mendukung koneksi packet (socket) dan stream


(datagram). Sesuai dengan namanya, framework ini menyediakan API dasar bagi
koneksi di CLDC. Framework ini menyediakan pondasi umum dari berbagai koneksi
seperti HTTP, socket, dan datagram. Walaupun Bluetooth dan serial I/O termasuk
kedalam API ini, GCF menyediakan satu set API yang lebih generic dan mendasar yang
menjadi abstraksi dari berbagai tipe koneksi. Harus dicatat, bahwa tidak semua tipe
koneksi dibutuhkan bagi implementasi sebuah MIDP device.

6.1.1 Hirarki dari GCF Interface

Perluasan dari hirarki GCF interface memungkinkan terjadinya generalization. Sebuah


tipe koneksi yang baru mungkin dapat ditambahkan kepada framework ini dengan cara
memperluas hirarki.

Pengembangan Perangkat Mobile 1


J.E.N.I.

Gambar 8.1: Hirarki dari GCF Interface

Pengembangan Perangkat Mobile 2


J.E.N.I.

6.1.2 GCF Connection URL

Parameter-parameter koneksi telah dispesifikasikan dengan menggunakan sebuah


format pengalamatan:

scheme://username:password@host:port/path;parameters

1. Scheme adalah sebuah protokol atau method koneksi. Misalnya: http,ftp, https.
2. Username bersifat optional, akan tetapi bila kita ingin mendefinisikannya, harus
didahului dengan tanda @
3. Password juga bersifat optional dan hanya dapat dispesifikasikan jika username telah
didefinisikan sebelumnya. Jika password didefinisikan, maka ia harus dipisahkan dari
username dengan menggunakan tanda titik dua (:)
4. Host – parameter ini wajib dicantumkan. Bisa berupa nama host atau fully qualified
domain name (FQDN) atau alamat IP dari host yang dituju.
5. Port – parameter ini juga bersifat optional. Jika tidak dispesifikasikan, maka default
port akan digunakan
6. Path
7. parameters – bersifat optional, tetapi harus didahuli dengan titik koma (;) apabila ia
dicantumkan

Jika kita menggunakan kurung siku untuk memberi tanda pada parameter-parameter
yang bersifat optional pada format pengalamatan diatas, kita dapat mengubah format
diatas menjadi seperti berikut:

scheme://[username[:password]@]host[:port]/path[;parameters]

Format pengalamatan tersebut haruslah sesuai dengan Uniform Resource Indicator (URI)
seperti yang didefinisikan pada RFC 2396.

Pada MIDP 2.0, hanya skema “http” dan “https” dibutuhkan untuk diimplementasikan
pada device.

Pengembangan Perangkat Mobile 3


J.E.N.I.

6.2 Koneksi HTTP

6.2.1 Protokol HTTP

HTTP merupakan kepanjangan dari HyperText Transfer Protocol. Ia merupakan protocol


yang digunakan untuk memindahkan web pages dari web server (misal: www.sun.com)
kepada web browser. Client(web browser) akan me-request sebuah web page dengan
cara mespesifikasikan path dengan command Get atau POST.

Pada method GET, parameter telah dispesifikasikan dan dilekatkan pada URL. Sebagai
contoh, untuk memberikan sebuah variable dengan nama “id” dan memiliki nilai 100
kepada index.jsp, url tersebut akan dispesifikasikan sebagai :
“http://hostname/index.jsp?id=100”. Parameter tambahan dipisahkan dengan dengan
tanda &, "http://hostname/index.jsp?id=100&page=2.

Jika method “POST” digunakan, parameter bukanlah menjadi bagian dari URL tetapi
dikirim dengan pada baris terpisah pada command POST.

Pengembangan Perangkat Mobile 4


J.E.N.I.

Client / Web Browser HTTP Server


GET /index.jsp?id=100 HTTP/1.1
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Date: Wed, 18 Jun 2005 14:09:31 GMT
Connection: close

<html>
<head>
<title>Test Page</title>
</head>
<body>
<h1 align="center">Test Page</h1>
</body>
</html>

Gambar 8.2: Contoh dari transaksi HTTP GET

Pengembangan Perangkat Mobile 5


J.E.N.I.

Client / Web Browser HTTP Server


GET /non-existent.html HTTP/1.0
HTTP/1.1 404 /non-existent.html
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 983
Date: Mon, 11 Jul 2005 13:21:01 GMT
Connection: close

<html><head><title>Apache Tomcat/5.5.7 -
Error report</title><style>...
<body><h1>HTTP Status 404</h1>
...
The requested resource (non-existent.html)
is not available.
...
</body></html>

Gambar 8.3: Contoh dari transaksi HTTP GET dengan response error

6.2.2 Menciptakan sebuah koneksi HTTP

Anda dapat membuka sebuah koneksi HTTP dengan menggunakan Connector.open() dan
meng-casting nya dengan salah satu dari ketiga interface berikut ini: StreamConnection,
ContentConnection, dah HTTPConnection. Bagaimanapun, dengan StreamConnection dan
ContentConnection, Anda tidak dapat menspesifikasikan dan menurunkan parameter-
parameter spesifik dari HTTP dan juga result-nya.

Bila Anda menggunakan StreamConnection, panjang dari sebuah reply, tidak dapat
ditentukan sebelumnya. Sedangkan pada ContentConnection atau HTTPConnection,
selalu ada cara untuk menentukan panjang dari sebuah reply. Akan tetapi penentuan
panjang ini, tidak selalu tersedia. Oleh karena itu, program Anda harus bisa
mendapatkan reply tersebut tanpa harus mengetahui panjang content terlebih dahulu.

Pengembangan Perangkat Mobile 6


J.E.N.I.

import javax.microedition.io.*;

HttpConnection connection = null;


InputStream iStream = null;
byte[] data = null;

try {
connection = (HttpConnection) Connector.open("http://www.sun.com/");
int code = connection.getResponseCode();

switch (code){
case HttpConnection.HTTP_OK:
iStream = connection.openInputStream();
int length = (int) connection.getLength();
if (length > 0){
data = new byte[length];
int totalBytes = 0;
int bytesRead = 0;
while ((totalBytes < length) && (bytesRead > 0)) {
bytesRead = iStream.read(
data, totalBytes, length - totalBytes);
if (bytesRead > 0){
totalBytes += bytesRead;
}
}
} else {
//panjang tidak diketahui, baca tiap karakter
...
}
break;
default:
break;
}

...

Pengembangan Perangkat Mobile 7


J.E.N.I.

6.2.3 Handling HTTP Redirects

Terkadang server akan melakukan redirect dari sebuah browser/client ke web page yang
lain dengan cara me-reply HTTP_MOVED_PERM (301), HTTP_MOVED_TEMP (302),
HTTP_SEE_OTHER (303) atau HTTP_TEMP_REDIRECT (307) daripada menggunakan
reply HTTP_OK yang biasa dilakukan. Program Anda harus dapat mengidentifikasi-nya
dengan menggunakan getResponseCose(), mendapatkan URI yang baru dari header
dengan menggunakan getHeaderField(“Location”), dan mendapatkan kembali dokumen
dari lokasi yang baru.

int code = connection.getResponseCode();

switch(code){
case HttpConnection.HTTP_MOVED_PERM:
case HttpConnection.HTTP_MOVED_TEMP:
case HttpConnection.HTTP_SEE_OTHER:
case HttpConnection.HTTP_TEMP_REDIRECT:
String newUrl = conn.getHeaderField("Location");

...

Pengembangan Perangkat Mobile 8


J.E.N.I.

6.3 Koneksi HTTPS

HTTPS adalah sebuah HTTP diatas sebuah koneksi secure transport. Membuka sebuah
koneksi HTTPS, hampir sama untuk membuka koneksi HTTP. Perbedaan utamanya
adalah URL akan memberikan kepada Connector.open() dan meng-casting hasilnya
kepada HttpsConnection class variable.

Sebuah tipe exception tambahan juga harus dijalankan melalui Connector.open()


misalnya IllegalArgumentException, ConnectionNotFoundException,
java.io.IOException dan SecurityException. Sebuah CertificateException
juga dapat dijalankan untuk melaporkan kesalahan pada certificate.

import javax.microedition.io.*;

HttpsConnection connection = null;


InputStream iStream = null;
byte[] data = null;

try {
connection = (HttpsConnection) Connector.open("https://www.sun.com/");
int code = connection.getResponseCode();
...
} catch (CertificateException ce){
switch (ce.getReason()){
case CertificateException.EXPIRED:
...
}
}

Pengembangan Perangkat Mobile 9


J.E.N.I.

static byte BAD_EXTENSIONS


Mengindikasikan bahwa sertifikat memiliki extenstion yang tidak
teridentifikasi.
static byte BROKEN_CHAIN
Mengindikasikan bahwa sertifikat terletak didalam sebuah rantai
yang tidak terautentikasi pada mata rantai berikutnya.
static byte CERTIFICATE_CHAIN_TOO_LONG
Mengindikasikan bahwa sertifikat server dari rantai tersebut
melebihi panjang yang disepakati pada policy dari pembuat sertifikat.
static byte EXPIRED
Mengindikasikan bahwa sertifikat tersebut telah berakhir jangka
waktunya.
static byte INAPPROPRIATE_KEY_USAGE
Mengindikasikan bahwa public key dari sertifikat tersebut telah
digunakan tidak sesuai dengan ketetapan yang dibuat oleh pembuat
sertifikat.
static byte MISSING_SIGNATURE
Mengindikasikan bahwa object dari sertifikat tidak memiliki sebuah
tanda tangan digital.
static byte NOT_YET_VALID
Mengindikasikan bahwa sertifikat tersebut tidak berlaku.
static byte ROOT_CA_EXPIRED
Mengindikasikan bahwa root dari public key CA telah habis jangka
waktunya.
static byte SITENAME_MISMATCH
Indicates a certificate does not contain the correct site name.
static byte UNAUTHORIZED_INTERMEDIATE_CA
Mengindikasikan bahwa ada sebuah sertifikat intermediate
certificate didalam rantai yang tidak punya otoritas sebagai intermediate
CA.
static byte UNRECOGNIZED_ISSUER
Mengindikasikan bahwa sertifikat tersebut telah dikeluarkan oleh
entity yang tidak teridentifikasi.
static byte UNSUPPORTED_PUBLIC_KEY_TYPE
Mengindikasikan bahwa tipe public key didalam sertifikat tidak
didukung oleh device.
static byte UNSUPPORTED_SIGALG
Mengindikasikan bahwa sertifikat telah ditandatangani dengan
menggunakan algorithma yang tidak disupport.
static byte VERIFICATION_FAILED
Mengindikasikan bahwa sertifikat tersebut gagal di-verifikasi.

Gambar 8.4: Berbagai alasan pada CertificateException


(kutipan dari spesifikasi MIDP 2.0 – JSR 118)

Pengembangan Perangkat Mobile 10


J.E.N.I.

6.4 TCP Sockets

Banyak implementasi dari HTTP dijalankan diatas layer TCP. Jika Anda mengirim data
menggunakan layer TCP, data tersebut akan dipotong menjadi bagian yang lebih kecil
yang disebut dengan packet. Layer TCK akan memastikan bahwa semua packet akan
dikirim oleh sender dan diterima oleh recipient, dengan susunan yang sama seperti pada
saat ia dikirimkan. Jika sebuah packet tidak diterima oleh recipient, ia akan
mengirimkannya kembali. Hal ini berarti, sekali Anda mengirim sebuah pesan, Anda
dapat memastikan bahwa pesan tersebut akan berhasil dikirim kepada recipient dengan
format yang sama seperti pada saat Anda mengirimkannya, tanpa ada data yang hilang
atau disisipi (dihalangi oleh sebuah siklus tertentu seperti recipient disconnect dari
jaringan) .

Layer TCP menangani reassembly dan retransmission pada packet secara transparan.
Sebagai contoh, pada protokol HTTP kita tidak perlu khawatir terhadir prosess
disassembly dan assembly packet karena hal ini akan dihandle pada layer TCP.

Kadang-kadang, ukuran dari pesan tersebut terkadang terlalu kecil dan sangat tidak
efisien untuk dikirimkan sebagai packet tunggal (overhead dari packet sangat tinggi jika
dibandingkan dengan payload). Bayangkan banyak packet dikirimkan melalui jaringan
dengan satu byte payload dan multi byte overhead(misal 16 bytes). Hal ini akan
menyebabkan jaringan sangat tidak effisien, banyak packets membanjiri jaringan
dengan hanya satu byte payload.

Pada kasus ini, implementasi dari TCP dimungkinkan untuk menunggu sebuah pesan
dikirim dengan sukses. Pesan tersebut kemudian akan dipaket sebagai banyak pesan
didalam sebuah packet sebelum dikirimkan. Jika hal ini terjadi, maka akan terjadi
keterlambatan pada koneksi. Jika aplikasi Anda menginginkan sesedikit mungkin terjadi
keterlambatan, anda harus mengeset DELAY socket option ke nol (0). Atau jika aplikasi
Anda dapat tetap berjalan dengan beberapa paket yang hilang atau tidak tersusun
secara benar, Anda mungkin harus mencoba menggunakan UDP atau koneksi datagram.
Koneksi UDP juga menggunakan sesedikit mungkin overhead packet.

SocketConnection conn =
(SocketConnection) Connector.open("socket://www.sun.com:80");

client.setSocketOption(DELAY, 0);

InputStream iStream = conn.openInputStream();


OutputStream oStream = conn.openOutputStream();

os.write("GET / HTTP/1.0\n\n".getBytes());

int c = 0;
while((c = is.read()) != -1) {
// memproses data yang diterima
...
}

Pengembangan Perangkat Mobile 11


J.E.N.I.

iStream.close();
oStream.close();
conn.close();

6.5 Server Sockets

Didalam model client-server, server akan secara terus menerus menunggu sebuah
koneksi dari client atau dari port tertentu yang telah disetujui. Kita juga dapat
menggunakan method Connector.open untuk menciptakan sebuah server socket.
Sebuah URL akan memberikan sebuah format yang sama seperti pada TCP socket
kepada method open(), dengan nama hostname yang dibiarkan kosong (misal
socket://:8899).

ServerSocketConnection conn =
(ServerSocketConnection) Connector.open("socket://:8889");

// Dengarkan koneksi dari client


SocketConnection client = (SocketConnection) conn.acceptAndOpen();

client.setSocketOption(DELAY, 0);

InputStream iStream = client.openInputStream();


OutputStream oStream = client.openOutputStream();

// baca/tulis untuk input/output streams


...

is.close();
os.close();
client.close();
server.close();

Pengembangan Perangkat Mobile 12


J.E.N.I.

6.6 Datagrams

Koneksi dari TCP socket adalah koneksi yang dapat dipercaya. Sebaliknya,
tersampaikannya pesan dengan menggunakan packet UDP tidak dijamin. Tidak ada
jaminan bahwa packet yang dikirimkan dengan menggunakan paket datagram akan
diterima oleh pasangan. Susunan dari packet yang diterima juga tidak terpercaya.
Susunan packet yang dikirimkan dimungkinkan untuk tidak sama dengan susunan
packet yang diterima.

UDP datagrams atau packet digunakan apabila aplikasi dapat tetap berjalan walaupun
ada packet yang hilang atau packet tersebut tidak lagi memiliki susunan yang sama
seperti yang dikirimkan.

String url;
try {
if (isServer){
// memulai sebagai server, mendengarkan port 8888
url = "datagram://:8888";
} else {
// memulai sebagai client, koneksi dengan port 8888 sebagai
//localhost
url = "datagram://localhost:8888";
}
dc = (DatagramConnection) Connector.open(url);

while (true) {
Datagram dgram = dc.newDatagram(128);
dc.receive(dgram);
if (isServer){
// memulai sebagai server, mendapatkan alamat koneksi
// bagi pesan kita selama proses pengiriman
url = dgram.getAddress();
}
if (dgram.getLength() > 0){
String mesg =
new String(dgram.getData(), 0, dgram.getLength()));
}
}

Pengembangan Perangkat Mobile 13


J.E.N.I.

}
catch (IOException ioe) {}
catch (Exception e) {}

...

private void sendMesg(String line){


try {
byte[] bytes = line.getBytes();
Datagram dgram = null;

dgram = dc.newDatagram(bytes, bytes.length, url);

dc.send(dgram);
} catch (Exception ioe) {}
}

6.7 Latihan
6.7.1 Mendapatkan URL
Buatlah sebuah MIDlet yang mendapatkan HTTP URL. Aplikasi tersebut akan
mendapatkan URL dengan method GET dan menampilkan jenis koneksi/ content
properties (jika tersedia): Reponse Code, Response Message, Length, Type, Encoding,
Expiration dan Last Modified Date.

Pengembangan Perangkat Mobile 14


J.E.N.I.

Pengembangan Perangkat Mobile 15


J.E.N.I.

Bab 7
Security

7.1 Tujuan
Pada akhir pembahasan bab ini, siswa diharapkan mampu :
o Memahami dasar security dan kriptografi
o Memahami proteksi domains dan permissions
o Bagaimana menambahkan permissions pada MIDlet Suite
o Bagaimana membuat MIDlet Suite menggunakan NetBeans Mobility Pack
o Bagaimana membuat message digest menggunakan SATSA
o Bagaimana melakukan enkripsi menggunakan symmetric keys

7.2 Dasar Security

Kriptografi

Kriptografi adalah cabang dari ilmu matematika yang memiliki banyak fungsi dalam
pengamanan data. Kriptografi adalah proses mengambil message dan menggunakan
beberapa fungsi untuk menggenerasi materi kriptografis (sebuah digest atau
message terenkripsi).

Kriptografi adalah salah satu dari teknologi yang digunakan dalam layanan security
seperti integrity, confidentiality, identity dan non repudiation.

Tipe Security Services

Sebelum kita memasuki bahasan dasar fungsi kriptografi, kita pelajari terlebih
dahulu beberapa security services penting yang digunakan dalam sebuah aplikasi :

Authentification – Adalah proses verifikasi indentitas dari pengguna pada akhir


jalur komunikasi.

Confidentiality – Jika kita mengirimkan data sensitive melalui sebuah jaringan, kita
ingin memastikan bahwa hanya penerima yang dituju yang dapat membacanya.

Pengembangan Perangkat Mobile 1


J.E.N.I.

Integrity – Kita ingin memastikan bahwa data yang kita terima tidak mengalami
pengubahan, penambahan ataupun pemisahan.

Non-repudiation – Service ini dapat menunjukkan bukti bahwa pengirim telah


mengirimkan message, atau penerima telah menerima message.

Authorization – Untuk memastikan bahwa user memiliki hak akses spesifik


terhadap data penting maupun sumber data.

Message Digests

Sebuah message digest juga disebut sebagai digital fingerprint. Sebuah message
digest adalah sebuah kesimpulan matematis dari sebuah message atau file. Hal ini
untuk memastikan integritas dari message atau file. Sehingga dapat memberikan
informasi bahwa sebuah message telah mengalami perubahan atau tidak. Mengubah
satu karakter dari sebuah file atau message dapat menyebabkan perubahan drastis
dari message digest. Digest terbuat melalui sebuah proses yang sangat menyulitkan
untuk membuat dua file atau message yang berbeda dengan message digest yang
sama.

Sebuah message digest berfungsi dalam satu alur fungsi. Sebuah message digest
relatif mudah untuk diproses, namun sangat sulit jika dilakukan dengan cara
sebaliknya. Dari sebuah message digest, sangat sulit untuk mengolah dan membuat
sebuah message yang dapat menghasilkan message digest yang sama.

Kriptografi Symmetric Key

Dengan kriptografi symmetric key, sebuah message dapat terenkripsi dan terdekripsi
menggunakan key yang sama. Baik pengirim maupun penerima message harus
memiliki key yang sama supaya proses tersebut berjalan dengan sukses. Pengirim
menggunakan key rahasia untuk mengenkripsi message, sedangkan penerima
menggunakan kunci yang sama untuk mendekripsi message. Sekali message telah
terenkripsi, message tersebut dapat dikirimkan melalui jaringan tanpa dipahami oleh
penyadap.

Secret Key Secret Key

Encrypted
Message ENCODE ENCODE Message
Message

Pengembangan Perangkat Mobile 2


J.E.N.I.

Kriptografi Asymmetric Key

Permasalahan dari symmetric key adalah kedua pihak harus memiliki key yang
sama. Key tersebut harus dikirimkan secara aman menuju penerima dari beberapa
sebab sehingga key dapat dicuri dan digunakan untuk mendekripsi sebuah message.

Dengan menggunakan asymmetric keys, pengirim mengenkripsi message dengan


menggunakan public key penerima. Kemudian penerima mendekripsi message
tersebut menggunakan private key. Private key hanya dimiliki oleh penerima. Antara
private dan public key merupakan komplemen matematis sehingga message yang
terenkripsi menggunakan public key dapat terdekripsi menggunakan private key. Hal
tersebut secara komputasi juga sulit untuk membuat private key ulang
menggunakan public key.

Public Key Private Key

Encrypted
Message ENCODE ENCODE Message
Message

Kriptografi Public Key

Algoritma public key menuntut penggunaan complementary key secara terpisah


dalam proses enkripsi dan dekripsi. Hal ini menunjukkan kepastian bahwa akan
memakan waktu yang sangat lama untuk mengetahui private key melalui
pengolahan public key. Tuntutan ini membuat distribusi public key menjadi mudah
tanpa mengkhawatirkan kerahasiaan dari private key.

Algoritma public key yang amat popular adalah algortima RSA. Keamanan dari RSA
telihat dari tingkat kesulitan faktorial numerik dalam cakupan yang besar.

Digital Signature

Sebuah digital signature mirip dengan message digest kecuali bahwa digest
dihasilkan oleh private key dari sebagian personal atau entitas. Public key digunakan
dalam verifikasi bahwa message yang ditandai berasal dari penanda.

Key Management

Salah satu permasalahan dari kriptografi public key adalah key management.
Bagaimana anda mengetahui bahwa public key yang anda gunakan dalam verifikasi
otentifikasi dari digital signature adalah public key asli yang dikirimkan oleh
pengirim?

Pengembangan Perangkat Mobile 3


J.E.N.I.

Digital Certificates adalah messages yang dibuat oleh Certification Authority (CA)
yang menyertakan keabsahan entitas dari public key. Pada dasarnya, Digital
Certificates adalah container dari Public Keys.

Untuk mendapatkan sertifikat dari CA, sebuah entitas menyertakan dokumentasi


yang membuktikan eksistensi dari identitas. Setelah melalui proses verifikasi
identifikasi, CA kemudian menandai public key dari identitas yang menggunakan
private key dari CA.

Namun kita telah menciptakan problem yang lain. Bagaimana kita memverifikasi
bahwa public key dari CA adalah asli? Anda akan mengetahui bahwa kita hanya
membuat rangkaian dari keabsahan.

Solusinya adalah penandaan certificate secara pribadi. CA menandai public key


menggunakan private key yang sesuai. Kemudian certificate yang telah ditandai dan
mengandung public key dari CA akan didistribusikan secara bebas. Hal ini dikenal
sebagai root certificate. Certificate yang ditandai secara pribadi dapat dibuat dengan
mudah oleh siapapun. Aplikasi seperti web browser dan email umumnya disertai
dengan root certificates dari Certificate Authorities yang diterima secara luas.

Signature Generation
Signature Verification

Sender's
Message Create Digest
Private
Key

Create Digest Message Digest

Message

Message Digest Encrypted Digest


Compare

Encrypt
Decrypted
Message Digest

Encrypted
Message Digest
Decrypt

Sender's
Public
Key

Pengembangan Perangkat Mobile 4


J.E.N.I.

7.3 J2ME Security


Protection Domains – Sebuah protection domains mendefinisikan rangkaian
permissions yang disertakan pada MIDlet Suite. MIDP 2.0 menjelaskan bahwa paling
tidak terdapat dua buah protection domains : untrusted dan trusted domains.
Untrusted domains adalah pembatasan dimana akses terhadap protected API pada
kondisi default tidak diijinkan. Seorang user secara eksplisit harus mengatur tipe
akses MIDlet Suite terhadap API. Untrusted MIDlets (berjalan di untrusted domains)
tidak memerlukan user permission dalam mengakses protected API.

Untrusted dan trusted domain menyediakan akses yang tak terbatas pada Record
Management, MIDlet life cycle, LDCUI, Game dan Multimedia API. Bagaimanapun,
API untuk koneksi HTTP dan HTTPS menuntut kejelasan permissions dari user jika
MIDlet Suite berjalan pada untrusted domain.

Sebuah protection domain adalah rangkaian dari ”Allowed” dan ”User” permissions
yang diberikan kepada MIDlet Suite.

Permissions

Terdapat dua tipe mode interaksi permissions, mode Allowed dan User. Pada mode
Allowed, user tidak diminta melakukan pengaturan permission saat MIDlet
mengakses sebuah API yang terproteksi. Sebuah aplikasi secara otomatis
memberikan hak akses terhadap resource dan interaksi dari user tidak diperlukan.

Dalam mode User, device menanyakan apakah user menginginkan untuk mencabut
atau memberikan hak akses MIDlet terhadap resource. Frekuensi dari pertanyaan
bergantung pada mode interaksi yang dipilih oleh user.

Mode Interaksi User

Sebuah user permission memiliki salah satu dari 3 mode interaksi berikut :

Blanket – User memberikan permission pada MIDlet Suite untuk mengakses


resource atau API secara permanen. User tidak akan lagi diminta melakukan
pengaturan setiap MIDlet Suite berjalan. Permission yang ada akan tetap eksis
hingga MIDlet Suite dihapus dari device atau user merubah permission tersebut.

Membuat sebuah permission adalah salah satu dari cara pengamanan akses
terhadap restricted APIs. Dalam MIDP, nama dari permission menggunakan nama
dari package dari API tersebut sebagai prefix dan bersifat case sensitive. Jika
permission tersebut ditujukan kepada sebuah class, maka penamaan permission
harus mengandung nama class dan package.

Sebuah MIDlet dapat menuntut adanya permission dengan mendeklarasikan MIDlet-


Permissions ataupun atribut MIDlet-Permissions-Opt pada application descriptor. Jika
MIDlet Suite menyertakan atribut MIDlet-Permissions, atribut permission tersebut

Pengembangan Perangkat Mobile 5


J.E.N.I.

harus diberi hak akses terhadap protection domain. Jika hak akses tidak diberikan,
maka proses instalasi akan dibatalkan.

Multiple permissions dituliskan menggunakan tanda koma (,) sebagai pemisah.

MIDlet-Permissions: javax.microedition.io.Connector.http

MIDlet-Permissions-Opt: javax.wireless.messaging.sms.receive,
javax.wireless.messaging.sms.send

Membuat permissions pada MIDlet Suite menggunakan NetBeans Mobility Pack :

Pengembangan Perangkat Mobile 6


J.E.N.I.

Trusted MIDlets – Sebuah MIDlet dapat diputuskan sebagai trusted application jika
authentifikasi dan integritas dari file JAR dapat terverifikasi oleh device dan terbatas
pada sebuah protection domain. Proses verifikasi dilakukan oleh device
menggunakan certificates.

Menandai MIDlet pada NetBeans Mobility Pack :

Untuk memberi tanda pada MIDlet Suite menggunakan NetBeans Mobility Pack, buka
project properties (klik kanan project name pada projects tab dan pilih Properties).
Periksa bagian ”Sign Distribution” :

Pengembangan Perangkat Mobile 7


J.E.N.I.

7.4 Menggunakan Security dan Trust Services


API (SATSA)

Security and Trust Services API (SATSA) terdefinisi dalam Java Spesification Request
(JSR) 177. SATSA adalah sebuah pilihan package yang menyediakan APIs untuk
fungsi – fungsi security seperti manajemen digital signatures, pembuatan message
digest dan digital signatures, berhubungan dengan Java Cards dan operasi
kriptografi lainnya.

Contoh berikut ini menunjukkan cara pembuatan message digest dan enkripsi
sebuah message menggunakan symmetric keys :

Membuat Message Digest :

/*
* DigestMidlet.java
*
*/

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.security.*;

public class DigestMidlet extends MIDlet {


public void startApp() {
String message = "I LOVE JENI!";
System.out.println("Generating digest for message: " +
message);

byte[] digest = generateDigest(message.getBytes());

System.out.println("SHA-1 Digest:");
for (int i=0; i<digest.length; i++) {
System.out.print(digest[i] + " ");
}
System.out.println();
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public byte[] generateDigest(byte[] message) {
String algorithm = "SHA-1";
int digestLength = 20;
byte[] digest = new byte[digestLength];
try {
MessageDigest md;
md = MessageDigest.getInstance(algorithm);
md.update(message, 0, message.length);
md.digest(digest, 0, digestLength);
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
return digest;
}
}

Pengembangan Perangkat Mobile 8


J.E.N.I.

Sun Java Wireless Toolkit 2.3 menyediakan dukungan JSR 177 (atau SATSA) :

Proses Build dan Run file DigestMidlet :

1. Buka aplikasi Ktoolbar dari Wireless Toolkit :

2. Pilih “New Project” kemudian tentukan nama project dan class MIDlet :

Pengembangan Perangkat Mobile 9


J.E.N.I.

3. Pilih “JWTI” sebagai Target Platform. Tandai pilihan “Security and Trust Services
APIs (JSR 177) dan kilik “OK”.

4. Buat file dengan nama DigestMidlet.java pada direktori : WTK/apps/SATSA/src

Pengembangan Perangkat Mobile 10


J.E.N.I.

(WTK adalah direktori instalasi dari Sun Java Wireless Toolkit, secara default
adalah C:\WTK23, dan SATSA adalah nama project).

5. Klik ”Build”

6. Klik ”Run” untuk menjalankan MIDlet pada emulator. Jika anda menjalankan
MIDlet pada emulator, anda tidak akan mendapatkan output grafis apapun. Output
yang akan dihasilkan adalah berupa console pada WTK Tollbar.

Enkripsi dan Dekripsi Messages menggunakan symmetric keys :

/*
* SymmetricCipherMidlet.java
*
*/

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.microedition.securityservice.*;

public class SymmetricCipherMidlet extends MIDlet {


private static final byte[] key = {
(byte) 0xab, (byte) 0xcd, (byte) 0xef, (byte) 0x88,
(byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78

Pengembangan Perangkat Mobile 11


J.E.N.I.

};
String message = "I LOVE JEDI!";

public SymmetricCipherMidlet() {
try {
System.out.println("Original Message: " + message);
printBytes(message.getBytes());
byte[] encryptedMessage =
encrypt("DES/ECB/PKCS5Padding",
message.getBytes(), key, "DES");
System.out.println("Encrypted Message:");
printBytes(encryptedMessage);
byte[] decryptedMessage =
decrypt("DES/ECB/PKCS5Padding",
encryptedMessage, key, "DES");
System.out.println("Decrypted Message:");
printBytes(decryptedMessage);
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
e.printStackTrace();
}
}
private void printBytes(byte[] bytes) {
for (int i = 0; i<bytes.length; i++){
System.out.print(toHex(bytes[i]) + " ");
}
System.out.println();
}
private String toHex(byte b) {
char d1 = toHexDigit((byte) ((b>>4) & 0x0F));
char d2 = toHexDigit((byte) (b & 0x0F));
return ("0x"+d1+d2);
}
private char toHexDigit(byte x) {
if (x > 9) {
return ((char) ('A' + (x-10)));
} else {
return ((char) ('0' + x));
}
}
private byte[] encrypt(String algorithm,
byte[] message, byte[] keybytes, String keyAlgo)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, ShortBufferException,
IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance(algorithm);
Key key = new SecretKeySpec(keybytes, 0, keybytes.length,
keyAlgo);
int blockSize = 16;
int cipherLength =
((message.length / blockSize)
+ ((message.length % blockSize) > 0 ? 1 : 0))
* blockSize;
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherText = new byte[cipherLength];
cipher.doFinal(message, 0, message.length, cipherText, 0);
return(cipherText);
}
public byte[] decrypt(String algorithm,
byte[] cipherText, byte[] keybytes, String keyAlgo)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, ShortBufferException,
IllegalBlockSizeException, BadPaddingException {

Pengembangan Perangkat Mobile 12


J.E.N.I.

Cipher cipher = Cipher.getInstance(algorithm);


Key key = new SecretKeySpec(keybytes, 0, keybytes.length,
keyAlgo);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decrypted = new byte[message.length()];
cipher.doFinal(cipherText, 0, cipherText.length, decrypted,
0);
return(decrypted);
}

public void startApp() {


}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}

Pengembangan Perangkat Mobile 13


J.E.N.I.

7.5 Latihan

Buat sebuah method yang akan melakukan verifikasi atas


integritas dari sebuah message dengan cara mengolah dan
membandingkan antaradigest dari message tersebut dengan
message digest asli.

public boolean verifyDigest(byte[] message, byte[] originalDigest)

Pengembangan Perangkat Mobile 14


J.E.N.I.

Bab 8
Web Services

8.1 Tujuan

Diakhir pembahasan, diharapkan siswa dapat :

• Mengetahui bagaimana memodelkan data menggunakan XML

• Mengetahui beberapa Java API yang digunakan dalam pemrosesan XML

• Mendeskripsikan apa yang bisa dilaksanakan oleh web service

• Mengetahui beberapa key standard dalam web service

• Mengetahui bagaiamana membuat web service mobile sebagai client

8.2 Pengenalan terhadap XML

XML (eXtensible Markup Language) adalah sebuah meta-language untuk


mendeskripsikan data. XML merupakan sebuah cara merepresentasikan data tanpa
tergantung kepada system. Ia juga dapat digunakan sebagai extension markup
languages. XML adalah berbasis text, sehingga ia dapat dengan mudah dipindahkan dari
satu sistem komputer ke sistem yang lain. Dengan XML, data direpresentasikan dalam
sebuah dokumen yang terstruktur dan ia juga telah menjadi sebuah standard industri.

Element

Sebuah dokumen XML adalah sebuah dokumen yang mudah dibaca dan terdiri dari XML
tag atau element. Sama halnya dengan HTML, XML tag didefinisikan dengan kurung siku
<>. Sebuah dokumen XML memiliki struktur seperti entities didalam sebuah tree.

Anda dapat menggunakan tag sesuai dengan yang Anda inginkan, selama semua aplikasi
yang menggunakan dokumen tersebut menggunakan tag dengan nama yang sama. Tag
dapat memiliki attributes. Dalam contoh dibawah ini, “task” pertama memiliki “id”
dengan attribut “1”, sedangkan “task” yang kedua memiliki “id” dengan attribute “2”.

<tasks>
<task id="1">

Pengembangan Perangkat Mobile 1


J.E.N.I.

<name>connect to database</name>
<duration>2</duration>
<assignedTo>alex</assignedTo>
<progress>50</progress>
</task>
<task id="2">
<name>list table rows</name>
<duration>4</duration>
<assignedTo>alex</assignedTo>
<progress>100</progress>
</task>
</tasks>

Attributes

Tag dapat juga terdiri dari attribute-attribute. Didalam contoh, tag “task” memiliki
attribute dengan nama “id”. Sebuah attribut diikuti dengan tanda sama dengan (=) dan
diikuti dengan value atau nilainya.

Pada saat mendesai sebuah struktur XML, permasalahan yang selalu muncul adalah
apakah sebuah data element harus menjadi attribute dari sebuah element atau menjadi
sebuah sub-element. Seperti contoh, XML diatas juga dapat kita tulis lagi sebagai
berikut:

<tasks>
<task>
<id>1</id>
<name>connect to database</name>
...
</tasks>

Tidak ada aturan yang pasti, struktur element seperti apa yang harus kita anut. Akan
tetapi dalam beberapa situasi, aturan-aturan dibawah ini harus dipenuhi:
• Data akan memiliki beberap sub-struktur, pada kasus dimana Anda harus
menggunakan sebuah sub-element karena ia tidak boleh dimodelkan sebagai attribut.
• Data akan terdiri dari beberapa baris apabila attribut ingin dibuat sesederhana
mungkin – sebuah string yang pendek tetapi mudah untuk dibaca dan digunakan.

Pengembangan Perangkat Mobile 2


J.E.N.I.

• Data element dimungkinkan untuk muncul kembali.


• Data akan sering berubah.

XML Schema

XML tag harus bersifat extensible, dimana seorang desainer system dimungkinkan untuk
menuliskan sendiri XML tag-nya dalam pendeskripsian sebuah content. Anda dapat
menciptakan tag-tag yang berbeda untuk setiap format dokumen yang Anda inginkan
didalam aplikasi atau sistem Anda.

Tag didefinisikan menggunakan XML schema language. Sebuah schema mendefinisikan


struktur dari dokumen XML. Sebuah skema juga digunakan membatasi content dari
sebuah dokumen XML kedalam sebuah element, attributes, dan values tertentu.

Sebuah Document Type Definition schema adalah bagian dari spesifikasi XML. Kita akan
memanggil schema yang ditulis dalam bahasa ini disebut sebagai DTD. DTD ini juga
mendefinisikan tag atau attribute mana yang sangat diperlukan dan mana yang bersifat
optional.

<!ELEMENT tasks (task)*>


<!ELEMENT task (name, duration, assignedTo, progress) >
<!ATTLIST task
id CDATA #REQUIRED
>
<!ELEMENT task (name, duration, assignedTo, progress) >
<!ELEMENT name (#PCDATA) >
<!ELEMENT duration (#PCDATA) >
<!ELEMENT assignedTo (#PCDATA) >
<!ELEMENT progress (#PCDATA) >

Namespace

Ada beberapa kasus dimana tag atau element Anda memiliki nama yang sama. Misalnya, ada
beberapa element yang mempunya nama yang sama yaitu “name”. Untuk mengatasi hal tersebut,
sebuah namespace digunakan. Spesifikasi dari namespace akan digunakan oleh penulis
dokumentasi untuk mengetahui schema atau DTD mana yang digunakan pada element tertentu.
Namespace dapat diaplikasikan pada attribut dan juga pada elements.

Pengembangan Perangkat Mobile 3


J.E.N.I.

8.3 Java APIs bagi XML

JAXP

JAXP atau Java API for XML Processing (JAXP) adalah sebuah fleksible API yang
mendukung Anda untuk mendukung sembarang XML-complient parser didalam aplikasi
Java Anda. Ia memiliki sebuah layer plugability, dimana Anda dapat menambahkan
sembarang implementasi dari SAX atau DOM APIs.

JAXP juga telah mendukung namespaces, sehingga ia akan mendukung Anda untuk
bekerja dengan schema XML dalam mengatasi permasalahan penamaan.

DOM API

Document Object Model (DOM) adalah sebuah struktur tree, dimana tiap node akan
terdiri dari sebuah komponen dari struktur XML. DOM API mendukung Anda untuk
membuat atau menghilangkan sebuah node didalam tree. Ia juga dapat digunakan
untuk mengganti content dari node dan mengubah hierarki node.

Oleh karena, sebuah tree me-representasikan keseluruhan XML data, DOM API
membutuhkan banyak memori didalam runtime-nya.

SAX API

Simple API for XML (SAX) adalah sebuah event-based XML parser API. Ia akan membaca
XML dokumen dari awal hingga akhir. Setiap saat bertemu dengan sebuah construction
syntax, ia akan memberikan tanda (notify) untuk menjalankan program tersebut.
Sebuah SAX parser akan memberikan tanda kepada aplikasi dengan jalan memanggil
method dari interface ContentHandler.

Sebagai contoh, pada saat parser mencapai simbol kurang dari (<), ia akan memanggil
method startElement. Pada saat bertemu dengan tag terakhir (sebuah slash yang diikuti
dengan tanda lebih besar dari), hal ini disebut method endElement.

SAX sangatlah cepat dan efisien. Ia membutuhkan memori yang lebih sedikit daripada
DOM, karena ia tidak mengharuskan untuk membuat sebuah struktur tree internal dari
data-data XML. SAX hanya akan mengirimkan data setiap kali aplikasi ingin membaca
data tersebut.

XLST API

Pengembangan Perangkat Mobile 4


J.E.N.I.

Extensible Stylesheet Language Transformation (XSLT) standard mendefinisikan


mekanisme untuk pengalamatan (addressing) data-data XML dan untuk menspesifikkan
transformasi data.

Extensible Stylesheet Language (XSL) memiliki tiga sub-komponen:

XSL-FO – Formatting Objects standard. XSL-FO adalah sebuah standard yang


menyediakan mekanisme untuk mendeskripsikan aspek-aspek dari sebuah object
misalnya ukuran huruf dan layout halaman. Sub komponen ini tidak tercover didalam
JAXP.

XSLT – adalah sebuah transformation language dimana Anda diharapkan dapat


mendefisinikan sendiri transformasi dari sebuah XML ke format yang lain seperti HTML.

Xpath – adalah sebuah language spesification, dimana Anda diharapkan dapat


menspesifikasikan sendiri bagian-bagian dari struktur XML yang direference setiap saat.
Xpath adalah sebuah mekanisme pengalamatan yang mendukung Anda untuk
mendefinisikan sebuah path kepada element.

JAX-RPC

Java API for XML-based RPC (JAX-RPC) adalah sebuah teknologi untuk membangun web
services dan client web service yang dapat mengaktifkan remote procedure calls (RPC).
RPC model mendukung client untuk mengeksekusi procedure pada remote system.

Didalam JAX-RPC, remote procedure calls dan hasilnya direpresentasikan pada protocol
berbasis XML. SOAP adalah salah satu protokol yang menggunakan JAX-RPC. JAX-RPC
akan meng-convert API pemanggilan dan beraksi dari dan untuk SOAP/XML messages.
Hal ini akan menyebabkan SOAP menjadi lebih mudah dan menghilangkan
kekompleksan.

8.4 Web Services

Web Services Messaging

W3C mendefinisikan web service sebgai “sebuah software aplikasi yang dapat
teridentifikasi oleh URI dan memiliki interface yang didefiniskan, dideskripsikan, dan
dimengerti oleh XML dan juga mendukung interaksi langsung dengan software aplikasi
yang lain dengan menggunakan message berbasis XML melalui protokol internet”

Pengembangan Perangkat Mobile 5


J.E.N.I.

Web service adalah sebuah sofware aplikasi yang tidak terpengaruh oleh platform, ia
akan menyediakan method-method yang dapat diakses oleh network. Ia juga akan
menggunakan XML untuk pertukaran data, khususnya pada dua entities bisnis yang
berbeda.

Beberapa karakteristik dari web service adalah:


− Message-based
− Standards-based
− Programming language independent
− Platform-neutral

Beberapa key standard didalam web service adalah: XML, SOAP, WSDL and UDDI.

SOAP (Simple Object Access Protocol) adalah sebuah XML-based mark-up language
untuk pergantian pesan diantara aplikasi-aplikasi. SOAP berguna seperti sebuah amplop
yang digunakan untuk pertukaran data object didalam network. SOAP mendefinisikan
empat aspek didalam komunikasi: Message envelope, Encoding, RPC call convention,
dan bagaimana menyatukan sebuah message didalam protokol transport.

Sebuah SOAP message terdiri dari SOAP Envelop dan bisa terdiri dari attachments atau
tidak memiliki attachment. SOAP envelop tersusun dari SOAP header dan SOAP body,
sedangkan SOAP attachment membolehkan non-XML data untuk dimasukkan kedalam
SOAP message, di-encoded, dan diletakkan kedalam SOAP message dengan
menggunakan MIME-multipart.

Web Services Description

WSDL (Web Services Description Language) adalah sebuah XML-based language untuk
mendeskripsikan XML. Ia menyediakan service yang mendeskripsikan service request
dengan menggunakan protokol-protokol yang berbeda dan juga encoding. Ia akan
memfasilitasi komunikasi antar aplikasi. WSDL akan mendeskripsikan apa yang akan
dilakukan oleh web service, bagaimana menemukannya dan bagaimana untuk
mengoperasikannya.

Spesifikasi WSDL mendefinisikan tujuh tipe element:


− Types – element untuk mendefinisikan tipe data. Mereka akan
mendefinisikan tipe data (seperti string atau integer) dari element didalam
sebuah message.
− Message - abstract, pendefinisian tipe data yang akan dikomunikasikan.
− Operation – sebuah deskripsi abstract dari sebuah action yang didukung
oleh service.

Pengembangan Perangkat Mobile 6


J.E.N.I.

− Port Type – sebuah koleksi abstract dari operations yang didukung oleh
lebih dari satu endpoints.
− Binding – mendefinisikan penyatuan dari tipe port (koleksi dari operasi-
operasi) menjadi sebuah protokol transport dan data format (ex. SOAP
1.1 pada HTTP). Ini adalah sebuah protokol konkret dan sebuah
spesifikasi data format didalam tipe port tertentu.
− Port – mendefinisikan sebuah komunikasi endpoint sebagai kombinasi dari
binding dan alamat network. Bagi protokol HTTP, ini adalah sebuah bentuk
dari URL sedangkan bagi protokol SMTP, ini adalah sebuah form dari email
address.
− Service – satu set port yang terkorelasi atau suatu endpoints.

WSDL mendefinisikan service sebagai sebuah koleksi dari endpoints network. Sebuah
definisi abstrak dari endpoints dan messages adalah ia bersifat terpisah dari
pembangunan network atau penyatuan data format. Pembagian ini menyebabkan
penggunaan kembali abstract description dari data yang akan dipertukarkan (message
exchange) dan abstract collection dari operasi (ports)
Protokol konkret dan spesfikasi data format bagi tipe port tertentu menentukan binding
yang dapat digunakan kembali(reusable). Sebuah port adalah sebuah network address
yang dikombinasikan reusable binding; sebuah service adalah koleksi dari port-port.

Web Service Discovery

UDDI (Universal Description, Discovery and Integration) adalah sebuah service registry
bagi pengalokasian web service. UDDI mengkombinasikan SOAP dan WSDL untuk
pembentukan sebuah registry API bagi pendaftaran dan pengenalan service. Ia
menyediakan sebuah area umum dimana sebuah organisasi dapat mengiklankan
keberadaan mereka dan service yang mereka berikan (web service).

UDDI adalah sebuah framework yang mendefinisikan sebuah XML-based registry dimana
sebuah organisasi dapat meng-upload informasi mengenai service yang mereka berikan.
XML-based registry berisi nama-nama dari organisasi tsb, beserta service dan deskripsi
dari service yang mereka berikan.

Pengembangan Perangkat Mobile 7


J.E.N.I.

8.5 J2ME Web Services API (WSA)

Web Services API(JSR 172) menyediakan fungsi-fungsi tambahan yang mendukung web
service. API ini berisi fungsi-fungsi dasar yang digunakan dalam web service client
seperti remote web invocation dan XML parsing. WSA hanya merupakan subset dari
J2SE API.
WSA hanya mendukung pemakaian dari web service. Hal ini berarti, aplikasi J2ME
dengan menggunakan WSA hanya dapat menjadi konsumen dari service dan bukan
merupakan producer service. UDDI juga tidak disupport oleh JSR 172.
JAXP subset disupport oleh WSA spesification yang didukung oleh SAX. Ia tidak berisi
dukungan bagi DOM dan XSLT.

Dokumen parsing XML menggunakan SAX

Untuk mendapatkan instance dari SAX Parser, pertama-tama kita harus mendapatkan
instance dari SAXParserFactory:

// Dapatkan instance dari SAX parser factory


SAXParserFactory factory = SAXParserFactory.newInstance();

Kemudian, kita akan mendapatkan instance dari SAX Parser:

SAXParser parser = factory.newSAXParser();

Pada akhirnya, kita akan membuat sebuah source input dan menggunakan event
handler untuk mem-parser. Untuk mempermudah contoh, kita akan membuat sebuah
stream dari sebuah String. Biasanya, hal ini bisa terlaksana dengan menggunakan
resource dari file atau network. Contoh yang kita buat juga tidak memiliki sebuah GUI-
ia hanya mencetak sebuah outcome dari sebuah parsing menjadi sebuah standard
output.

ByteArrayInputStream stream =
new ByteArrayInputStream(sampleXML.getBytes());
InputSource inputSource = new InputSource(stream);
SaxEventHandler handler = new SaxEventHandler();
parser.parse(inputSource, handler);

Kode berikut ini adalah kode untuk Event Handler:

Pengembangan Perangkat Mobile 8


J.E.N.I.

import java.util.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;

public class SaxEventHandler extends DefaultHandler {


private boolean finished;
private Stack qNameStack = new Stack();
private Vector tasks = new Vector();

private static final String TASKS_ELEMENT = "tasks";


private static final String TASK_ELEMENT = "task";
private static final String NAME_ELEMENT = "name";
private static final String ID_ATTRIBUTE= "id";

public void startDocument() throws SAXException {


finished = false;
qNameStack.removeAllElements();
tasks.removeAllElements();
}

public void endDocument()


throws SAXException {
finished = true;

// Akhir dari dokumen, sekarang lakukan proses untuk memparsing object


for (int i=0; i<tasks.size(); i++) {
Task task = (Task) tasks.elementAt(i);
System.out.println("Task: " + task.name);
}
}

public void startElement(


String uri,
String localName,
String qName,
Attributes attributes)
throws SAXException {

if (TASK_ELEMENT.equals(qName)) {
// Dapatkan id attribute dari sebuah task
String id = attributes.getValue(ID_ATTRIBUTE);

Pengembangan Perangkat Mobile 9


J.E.N.I.

Task task = new Task(id);


tasks.addElement(task);
}

qNameStack.push(qName);
}

public void characters(


char[] ch,
int start,
int length)
throws SAXException {

String name = new String(ch, start, length);

String qName = (String) qNameStack.peek();


if (NAME_ELEMENT.equals(qName)) {
if (tasks.size() > 0) {
Task task = (Task) tasks.lastElement();
task.name = name;
}
}
}

public void endElement(


String uri,
String localName,
String qName)
throws SAXException {

qNameStack.pop();
}
}

Pengembangan Perangkat Mobile 10


J.E.N.I.

8.6 Membuat sebuah Mobile Web Service Client

Kita akan membuat secara sederhana aplikasi mobile dan kita akan menamakannya
“arithmeticClient”.

Pengembangan Perangkat Mobile 11


J.E.N.I.

Kemudian, kita akan menggunakan stub generator (Tools->Java Platform Manager ->
Wireless Toolkit -> Tools and Extensions -> Open Utilities -> Stub Generator):

Pengembangan Perangkat Mobile 12


J.E.N.I.

Sebelum kita dapat membuat sebuah web service client, kita harus memiliki sebuah file
WSDL atau lokasi URL dimana terdapat service yang dapat kita pergunakan. Seperti
yang telah disebutkan dalam bagian sebelumnya, JSR 172 tidak mendukung UDDI atau
automatic discovery bagi service.

Masukkan lokasi WSDL dari sebuah web service. Path dari outputnya harus menjadi path
dari direktori sumber project Anda (PROJECT_PATH/src). Sebuah stub generator tidak
menerima package tanpa penamaan. Oleh karena itu, Anda harus meng-inputkan
sebuah nama package.

Pengembangan Perangkat Mobile 13


J.E.N.I.

Kemudian, kita akan membuat sebuah Midlet yang akan menggunakan stub yang telah
kita buat untuk mengakses sebuah web service:

/*
* arithemeticClient.java
*
*/

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import jedi.*;

public class WSClient extends MIDlet {


private ArithmeticSEI_Stub stub;

public void startApp() {


System.out.println("Creating stub...");
stub = new ArithmeticSEI_Stub();

System.out.println("Invoking operation...");
WebServiceClient client = new WebServiceClient();
Thread thread = new Thread(client);
thread.start();

Pengembangan Perangkat Mobile 14


J.E.N.I.

public void pauseApp() {


}

public void destroyApp(boolean unconditional) {


}

class WebServiceClient implements Runnable {


public void run() {
try {
int reply = stub.multiply(4, 5);

System.out.println("Reply: " + reply);

} catch (java.rmi.RemoteException rex) {


System.out.println("Remote Exception: " + rex.getMessage());
}
}
}
}

Pengembangan Perangkat Mobile 15


J.E.N.I.

Bab 9

Optimisasi
9.1 Tujuan
Setelah menyelesaikan bab ini, pelajar diharapkan menguasai :

● Mengetahui teknik yang berbeda dalam optimisasi aplikasi mobile

9.2 Optimisasi
Sebelum benar-benar melakukan setiap optimisasi pada program Anda, Anda seharusnya perlu
memastikan bahwa package software anda memiliki kualitas yang baik. Anda perlu
meletakkan optimisasi dalam agenda Anda. Beberapa teknik yang dibahas pada bab ini
seharusnya dapat membantu dalam menghindari beberapa kesalahan pemrograman.

9.3 Eksekusi program

9.3.1 Gunakan StringBuffer sebagai pengganti String.


Anda perlu ingat bahwa pada Java, object String bersifat absolut atau abadi. Menggunakan
method String menciptakan suatu object String terpisah. Perangkaian String yang sederhana
menciptakan suatu object String ganda (kecuali jika String itu bersifat konstan dan kompiler
cukup pandai untuk menggabungkan mereka pada proses compile berlangsung).
Menggunakan StringBuffer tidak hanya mengoptimalkan runtime program Anda (lebih sedikit
menimbulkan object runtime), itu juga mengoptimalkan pemakaian memori ( lebih sedikit
object String dibuat).

String StringBuffer

String a, b, c; String a, b, c;
... ...

String message = StringBuffer message = new StringBuffer(255);


"a=" + a + "\n" message.append("a=");
+ "b=" + b + "\n" message.append(a);
+ "c=" + c + "\n"; message.append("\n");
message.append("b=");

Pengembangan Perangkat Mobile 1


J.E.N.I.

String StringBuffer

message.append(b);
message.append("\n");
message.append("c=");
message.append(c);
message.append("\n");

9.3.2 Gunakan clipping area dalam menggambar

Menggunakan Graphics.setClip() akan mengurangi waktu eksekusi karena Anda hanya akan
menggambar nomor-nomor yang optimal dari pixel-pixel di layar. Ingat, bahwa menggambar
grafik pada layar meminta banyak terminologi pada waktu eksekusi. Mengurangi banyaknya
pixel-pixel untuk digambar akan sangat mempengaruhi kinerja runtime program Anda.

Graphics g;
int x1, y1, x2, y2;
...

g.setClip(x1, y1, x2, y2);


g.drawString("JEDI", x, y, Graphics.TOP | Graphics.HCENTER);
// Operasi menggambar yang lainnya...

9.3.3 Hindari modifier yang sama

Menggunakan modifier yang sama mengambil sesuatu tanpa diduga pada kecepatan eksekusi
program Anda karena hal tersebut menimbulkan beberapa ukuran tambahan sehingga itu tidak
akan diakses secara bersamaan.

9.3.4 Lewatkan parameter sesedikit mungkin

Ketika memanggil suatu method, penerjemah akan mendorong semua parameter ke atas
tumpukan eksekusi. Melewatkan banyak parameter akan mempengaruhi kecepatan eksekusi
dan pemakaian Heap Memory.

9.3.5 Mengurangi pemanggilan method

Memanggil method menghabiskan Heap Memory dan waktu eksekusi. Lihat subbab
sebelumnya.

9.3.6 Menunda semua inisialisasi

Untuk mempercepat awal permulaan aplikasi, tunda semua inisialisasi yang sangat besar
sampai mereka dibutuhkan. Jangan meletakkan inisialisasi dalam konstruktor MIDlet atau

Pengembangan Perangkat Mobile 2


J.E.N.I.

method startApp. Mempercepat waktu load sebuah aplikasi akan menambah penggunaan
aplikasi Anda. Kebanyakan user akan meninggalkan aplikasi ketika aplikasi tersebut
membutuhkan waktu yang lama untuk start up. Ingat bahwa waktu load aplikasi anda secara
langsung mempengaruhi kesan pertama pengguna aplikasi Anda.
9.3.7 Gunakan array sebagai pengganti collection

Mengakses Array lebih cepat daripada menggunakan vektor

9.3.8 Menggunakan variabel lokal

Hal tersebut lebih cepat mengakses variabel lokal daripada mengakses variabel instance.

9.4 Ukuran JAR

9.4.1 Gunakan Obfuscator

Tujuan utama obfuscator adalah untuk mengacak file class yang dikompile sehingga sulit
untuk di decompile. Tetapi proses obfuscator juga mengurangi ukuran sebuah aplikasi. Salah
satu method yang digunakan oleh obfuscator adalah memberi nama baru pada class menjadi
sebuah nama. Karena obfuscator melakukan hal ini berdasar kepada modifier dari method-
method. Jika method memiliki private atau protected modifier, lalu itu dapat diasumsikan
aman ketika method ini tidak akan digunakan oleh package lainnya dan oleh karena itu dapat
diberi nama baru kembali.

Netbeans Mobility Pack datang dengan satu obfuscator. Dia tidak diaktifkan sebagai default.
Buka tab property dan klik pada cabang “Obfuscating” :

Pengembangan Perangkat Mobile 3


J.E.N.I.

Ada sepuluh tingkat obfuscation, dari tanpa obfuscation sampai ke obfuscation yang paling
agresif.

Pengembangan Perangkat Mobile 4


J.E.N.I.

9.4.2 Memadatkan file JAR Anda

Pastikan bahwa sebelum mendistribusikan aplikasi Anda, Anda memampatkan file akhir JAR
untuk distribusi. Sebuah file JAR adalah sebuah arsip ZIP, dan suatu arsip ZIP mempunyai
beberapa tingkat tekanan (termasuk tanpa tekanan). NetBeans Mobility Pack tidak mendukung
tingkat tekanan.

Untuk mengatur pilihan tekanan JAR, buka halaman properti dari aplikasi dan pilih cabang
“Creating JAR”. Centang radio box “Compress JAR” untuk memampatkan file JAR proyek Anda.
Jangan lupa untuk membangun kembali proyek Anda.

Pengembangan Perangkat Mobile 5


J.E.N.I.

9.4.3 Hindari membuat class yang tidak perlu

Ini akan tampak berlawanan untuk prinsip berorientasi object, tapi apakah Anda mengetahui
bahwa suatu class kosong yang sederhana seperti ini :

public class EmptyClass {


public EmptyClass(){}
}

akan dikompile menjadi file class dengan ukuran file sebesar 250kb (tanpa dimampatkan)?

Anda dapat mencoba mengkompile class kosong ini dan buktikan sendiri. Netbeans Mobility
Pack menyimpan package file JAR di dalam folder distribusi dibawah folder proyek. Anda dapat
merubah nama file .jar menjadi file .zip dan buka dengan program ZIP favorit Anda untuk
melihat ukuran dari file class yang Anda kompile.

9.4.4 Hindari membuat interfaces


Teknik ini berkaitan dengan teknik sebelumnya. Memiliki banyak class dan interfaces akan
menambahkan lebih ukuran file (kilobytes) dalam aplikasi Anda.

Pengembangan Perangkat Mobile 6


J.E.N.I.

9.4.5 Hindari inner dan anonymous class


Sama seperti diatas. Inner class adalah semua class yang sama. Anonymous class mungkin
tidak memiliki nama, tetapi mereka mengambil ruang yang sama untuk definisi class.

9.4.6 Gunakan satu Listener untuk object yang ganda


Ini akan mengurangi banyaknya class dalam aplikasi Anda. Buatlah MIDlet Anda
mengimplementasikan CommandListener interface sehingga membantu anda memangkas
package Anda oleh satu class (Dimana mengurangi 250 + byte).

9.4.7 Gunakan package default (package tanpa nama)


Didalam permintaan kita untuk package berukuran kecil, memendekkan (atau tidak
menggunakan) nama package tersebut mendukung pengurangan byte.

9.4.8 Batasi penggunaan dari initializer static


Menggunakan inisialisasi static seperti ini :

int[] tones = { 64, 63, 65, 76, 45, 56, 44, 88 };

Akan dikompile oleh kompiler Java menjadi pernyataan berikut :

tones[0] = 64;
tones[1] = 63;
tones[2] = 65;
tones[3] = 76;
tones[4] = 45;
tones[5] = 56;
tones[6] = 44;
tones[7] = 88;

Contoh ini menggambarkan hanya delapan anggota array. Bayangkan jika inisialisasi ratusan
nilai menggunakan statemen terpisah. Hal tersebut akan menjadikan overhead pada ukuran
aplikasi Anda.
Sebagai salah satu alternatif, Anda dapat menggunakan method getResourceAsStream()
untuk mendapatkan nilai dari sebuah file atau menggunakan single string untuk menyimpan
nilai array Anda.

9.4.9 Menggabungkan gambar ke dalam satu file


Memampatkan gambar lebih baik ketika di-kelompokkan menjadi satu file gambar. Karena
memampatkan format gambar (contohnya PNG) adalah lebih spesifik untuk gambar daripada
memampatkan method pengarsipan JAR. Ada teknik-teknik untuk mendapatkan gambar yang

Pengembangan Perangkat Mobile 7


J.E.N.I.

spesifik dari sebuah gambar yang besar yaitu dengan memotongnya.

9.4.10 Bereksperimen dengan memampatkan gambar


method tekanan(compressing) tidak diciptakan sama. Beberapa mungkin memampatkan lebih
baik pada beberapa jenis gambar tetapi kadang memiliki rasio yang rendah dalam
memampatkan jenis gambar yang lain. Pilih sebuah format gambar yang dapat meningkatkan
rasio pemampatan gambar Anda. Terkadang, rasio pemampatan juga dipengaruhi oleh
software pengolah gambar yang anda gunakan. Cobalah bereksperimen dengan berbagai
macam jenis software pengolah gambar untuk mendapatkan ukuran gambar yang lebih baik.

9.4.11 Gunakan class yang belum diinstal


Gunakan semua class yang bisa diterapkan yang tersedia pada platform yang anda gunakan.
Buatlah class Anda sendiri yang tidak akan menambah ukuran aplikasi Anda, tetapi juga
mengurangi stabilitas aplikasi Anda.

9.5 Jaringan
9.5.1 Gunakan thread yang terpisah
Gunakan thread yang terpisah untuk jaringan Anda yang berfungsi untuk menghindari screen
lockups.

9.5.2 Memampatkan data jaringan


Menggunakan data yang dimampatkan untuk mengurangi lalu lintas jaringan dari aplikasi
Anda. Hal ini akan membutuhkan client dan server Anda untuk menggunakan protokol dan
method pemampatan yang sama.
Memampatkan XML akan memberikan rasio yang lebih baik karena data XML terwakili dalam
suatu format teks.

9.5.3 Mengurangi lalu lintas jaringan


Karena komunikasi jaringan semakin lambat dan mahal, cobalah sebisa mungkin untuk
memasukkan beberapa perintah kedalam satu permintaan jaringan. Ini akan mengurangi
overhead yang dikenakan oleh protokol jaringan.

9.6 Penggunaan Memori


9.6.1 Gunakan struktur data ringkas
Gunakan struktur data memory yang sering digunakan. Array jarang bisa diwakili dengan cara
lain tanpa mengkonsumsi jumlah yang sama dari memory.
Ada tradeoff ketika mengoptimalkan untuk ukuran dan kecepatan. Menggunakan struktur data
komplek akan mempengaruhi kecepatan eksekusi program Anda.

Pengembangan Perangkat Mobile 8


J.E.N.I.

9.6.2 Membebaskan object yang tidak terpakai untuk garbage


collection
Membebaskan object yang tak terpakai untuk garbage collection layar, koneksi jaringan,
rekaman RMS. Menentukan variabel untuk menunjuk kepada object yang tak terpakai menjadi
null dan akan memberi isyarat kepada garbage collector bahwa object ini aman untuk tidak di-
load dari memory.

9.6.3 Jangan sering menggunakan layar on-the-fly


Tidak sering menggunakan object Screen (seperti Help dan about screen)on-the-fly akan
banyak bebaskan banyak kebutuhan Anda yang menumpuk pada memory. Meski Anda harus
membayar harga yaitu loading yang lambat untuk screen tertentu. Layar ini akan diduga
menimbun pada heap memory sementara mereka tidak digunakan untuk membantu dalam
penghematan memory

public void commandAction(Command c, Displayable d) {


if (c == helpCommand) {
display.setCurrent(new HelpForm());
}
}

9.7 Latihan
9.7.1 Ide optimisasi lainnya.
Diskusikan ide-ide tentang optimisasi lainnya yang ada pada pikiran Anda atau teknik yang
telah Anda kembangkan.

Pengembangan Perangkat Mobile 9


J.E.N.I.

Bab 10
Optional Packages

10.1 Tujuan

Bab ini akan mempelajari tentang penulisan, build, menggunakan emulator dan
packaging aplikasi J2ME. IDE yang digunakan adalah NetBeans (www.netbeans.org)
dan NetBeans mobility pack.

Setelah menyelesaikan pembahasan bab ini, siswa diharapkan :


• mengetahui fungsionalitas yang disediakan oleh Mobile Media API (MMAPI)
• memainkan nada sederhana
• menjalankan file audio dari jaringan dan file JAR
• mengirim dan menerima pesan SMS
• berkomunikasi wireless menggunakan protokol bluetooth

10.2 Pengenalan
Tidak seluruh device terbuat sama dan tiap class device memiliki fitur yang berbeda
– beda pula. Sangatlah sulit untuk membuat spesifikasi standar yang meliputi
seluruh device yang telah ada.

Untuk mengakomodasi perbedaan kemampuan dari device, MIDP memiliki beberapa


optional packages. Packages – packages tersebut adalah spesifik dan memenuhi fitur
– fitur umum spesifik.

Bab ini akan membahas bagaimana memulai penggunaan Mobile Media API (MMAPI)
dan Wireless Messaging API (WMA).

10.3 Mobile Media API (MMAPI)


Mobile Media API (MMAPI) memfasilitasi pembuatan nada, memankan serta
merekam audio dan video pada device yang cocok.

Memainkan atau merekam sebuah media ditangani oleh dua object : DataSource dan
Player.

Pengembangan Perangkat Mobile 1


J.E.N.I.

DataSource Player

DataSource menangani detail cara mendapatkan data dari source yang tersedia.
Source dapat berasal dari file JAR atau jaringan (melalui protokol HTTP), record dari
RMS, streaming connection dari sebuah server atau sumber properietary lain. Player
tidak perlu terlalu mempermasalahkan darimana data berasal atau bagaimana cara
mendapatkannya. Player hanya perlu membaca data yang berasal dari DataSource,
memproses, menampilkan dan memainkan playback media pada output device.

Pihak ketiga dalam skenario ini adalah Manager. Manager membuat Player dari
DataSource. Manager memiliki method untuk membuat Player dari lokasi sumber
media (URL), DataSource dan InputStreams.

Manager

DataSource Player

Anda dapat menjalankan query terhadap properties MMAPI melalui String


System.getProperty(String key).

Key Deskripsi

microedition.media.version Versi dari spesifikasi MMAPI yang


diterapkan oleh device. Contoh : “1.1”

supports.mixing Menghasilkan return value “true” jika


device mendukung audio mixing : dapat
memainkan minimal dua nada secara
bersamaan, dapat memiliki minimal dua

Pengembangan Perangkat Mobile 2


J.E.N.I.

Key Deskripsi

player yang memainkan audio secara


simultan, serta dapat memainkan sebuah
nada meskipun paling tidak satu Player
memainkan audio pada waktu yang sama

supports.audio.capture Menghasilkan return value “true” jika


mendukung fitur audio capture, dan juga
sebaliknya akan dihasilkan value “false”

supports.video.capture Menghasilkan return value “true” jika


mendukung fitur video capture, dan juga
sebaliknya akan dihasilkan value “false”

supports.recording Menghasilkan return value “true” jika


mendukung fitur perekaman.

10.3.1 Pembuatan Nada

Memainkan sebuah nada cukup dilakukan dengan memanggil static method


Manager.playTone(int tone, int duration, int volume). Nilai yang valid untuk nada
adalah antara 0 hingga 127. Durasi dalam memainkan nada diatur dalam ukuran
millisecond. Parameter volume memiliki jangkauan antara 0 hingga 100.

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;

import java.io.*;

public class ToneMIDlet extends MIDlet implements CommandListener{


private Command exitCommand, playCommand;
private Form form;
private Gauge volumeGauge;
private Gauge durationGauge;
private Gauge toneGauge;
private Display display;
private int duration = 2; // seconds
private int volume = 100;
private int tone = ToneControl.C4;
private static int MAX_VOLUME = 100;
private static int MAX_TONE = 127;
private static int MAX_DURATION = 5;
public ToneMIDlet() {
playCommand = new Command("Play", Command.OK, 1);
exitCommand = new Command("Exit", Command.EXIT, 1);
volumeGauge = new Gauge("Volume", true, MAX_VOLUME, volume);
toneGauge = new Gauge("Tone", true, MAX_TONE, tone);
durationGauge = new Gauge("Duration",true,MAX_DURATION,duration);

form = new Form("Tone Player");


form.addCommand(playCommand);

Pengembangan Perangkat Mobile 3


J.E.N.I.

form.addCommand(exitCommand);
form.append(volumeGauge);
form.append(durationGauge);
form.append(toneGauge);
}

public void startApp() {


display = Display.getDisplay(this);
form.setCommandListener(this);
display.setCurrent(form);
}

public void pauseApp() {}


public void destroyApp(boolean unconditional) {}

public void commandAction(Command c, Displayable d) {


if (c == exitCommand) {
notifyDestroyed();
}
if (c == playCommand){
try {
volume = volumeGauge.getValue();
tone = toneGauge.getValue();
duration = durationGauge.getValue();
Manager.playTone(tone, duration*1000, volume);
} catch (MediaException mex){}
}
}
}

10.3.2 Audio Playback

Method Manager.createPlayer(String URI) memudahkan pembuatan sebuah Player


yang akan memainkan data dari URI.

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;

import java.io.*;

public class NetAudioMidlet extends MIDlet implements CommandListener{


private Command exitCommand, playCommand;
private Form form;
private Gauge volumeGauge;
private Display display;
private int volume = 100;
private static int MAX_VOLUME = 100;
Player player;

public NetAudioMidlet() {
playCommand = new Command("Play", Command.OK, 1);
exitCommand = new Command("Exit", Command.EXIT, 1);
volumeGauge = new Gauge("Volume", true, MAX_VOLUME, volume);
form = new Form("Audio Player");

Pengembangan Perangkat Mobile 4


J.E.N.I.

form.addCommand(playCommand);
form.addCommand(exitCommand);
form.append(volumeGauge);
}

public void startApp() {


display = Display.getDisplay(this);
form.setCommandListener(this);
display.setCurrent(form);
try {
player = Manager.createPlayer(
"http://localhost:8084/Chapter07/bong.wa
v");
player.realize();
// pre-fetch media untuk mengurangi latency
player.prefetch();
} catch (IOException ioex) {
display.setCurrent(new Alert("IO Exception",
ioex.getMessage(),
null, AlertType.ERROR));
} catch (MediaException mex) {
display.setCurrent(new Alert("Media Exception",
mex.getMessage(),
null, AlertType.ERROR));
}
}

public void pauseApp() {}


public void destroyApp(boolean unconditional) {}

public void commandAction(Command c, Displayable d) {


if (c == exitCommand) {
notifyDestroyed();
}
if (c == playCommand){
try {
VolumeControl control = (VolumeControl)
player.getControl("VolumeControl");
if (control != null){
control.setLevel(volumeGauge.getValue());
}

player.start();
} catch (MediaException mex) {
display.setCurrent(new Alert("Media Exception",
mex.getMessage(), null, AlertType.ERROR));
} catch (Exception ex){
display.setCurrent(new Alert("Exception",
ex.getMessage(), null, AlertType.ERROR));
}
}
}
}

Pengembangan Perangkat Mobile 5


J.E.N.I.

Anda juga dapat memainkan media yang berasal dari file JAR dengan membuat
Stream dari resource file dan meneruskannya pada method Manager.createPlayer()

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;

import java.io.*;

public class AudioMidlet extends MIDlet implements CommandListener{


private Command exitCommand, playCommand;
private Form form;
private Gauge volumeGauge;
private Display display;
private int volume = 100;
private static int MAX_VOLUME = 100;
Player player;
public AudioMidlet() {
playCommand = new Command("Play", Command.OK, 1);
exitCommand = new Command("Exit", Command.EXIT, 1);
volumeGauge = new Gauge("Volume", true, MAX_VOLUME, volume);
form = new Form("Audio Player");
form.addCommand(playCommand);
form.addCommand(exitCommand);
form.append(volumeGauge);
}
public void startApp() {
display = Display.getDisplay(this);
form.setCommandListener(this);
display.setCurrent(form);
}
public void pauseApp() {}
public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable d) {
if (c == exitCommand) {
notifyDestroyed();
}
if (c == playCommand){
try {
InputStream stream = getClass().
getResourceAsStream("bong.wav");
player = Manager.createPlayer(stream, "audio/x-wav");
player.realize();
VolumeControl control = (VolumeControl)
player.getControl("VolumeControl");
if (control != null){
control.setLevel(volumeGauge.getValue());
}
player.start();
} catch (MediaException mex) {
display.setCurrent(new Alert("Media Exception",
mex.getMessage(), null, AlertType.ERROR));
} catch (Exception ex){
display.setCurrent(new Alert("Exception",
ex.getMessage(), null, AlertType.ERROR));
}

Pengembangan Perangkat Mobile 6


J.E.N.I.

}
}
}

10.4 Wireless Messaging API (WMA)

10.4.1 Mengirim SMS

Menggunakan Wireless Messaging API serupa dengan ketika menyambungkan via


Socket dan Datagram. Dalam kenyataannya, hal tersebut menggunakan framework
yang sama – the Generic Connection Framework (GCF). Format koneksi URL yang
digunakan adalah “sms://+639178888888”, dimana “+639178888888” adalah
nomor telepon yang ingin Anda kirimkan sebuah pesan.

public void sendSMS(String number, String message) throws Exception{


String url = "sms://" + number;
MessageConnection connection =
(MessageConnection) Connector.open(url);
TextMessage msg = (TextMessage) connection.newMessage(
MessageConnection.TEXT_MESSAGE);
msg.setPayloadText(message);
connection.send(msg);
connection.close();
}

Pengembangan aplikasi wireless pada NetBeans Mobility Pack 4.1 sangat nyaman.
Anda tidak perlu untuk mencoba mengirim pesan SMS hanya untuk mengetes
aplikasi Anda. NetBeans Mobility Pack hadir dengan J2ME Wireless Toolkit. Toolkit ini
hadir dengan emulator di dalamnya. Dan juga terdapat tool-tool untuk tes mengirim
dan menerima pesan SMS. Anda dapat mengkonfigurasikan nomor telepon dari
telepon yang di-emulasikan dengan membuka pilihan pada WMA.

 Tools
 Java Platfrom Manager
 J2ME Wireless Toolkit 2.2
 Tool dan Ekstensi :
1. Membuka Preferences -> WMA
2. Membuka Utility -> WMA: Open Console

Pengembangan Perangkat Mobile 7


J.E.N.I.

Pengembangan Perangkat Mobile 8


J.E.N.I.

Pengembangan Perangkat Mobile 9


J.E.N.I.

Pengembangan Perangkat Mobile 10


J.E.N.I.

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import javax.wireless.messaging.*;

public class SMSMidlet extends MIDlet implements CommandListener,


Runnable {

private Command exitCommand, sendCommand;


private Form form;
private TextField addressField, mesgField;
private Display display;

public SMSMidlet() {
sendCommand = new Command("Send", Command.OK, 1);
exitCommand = new Command("Exit", Command.EXIT, 1);

addressField = new TextField(


"Phone Number", "+5550000", 32, TextField.ANY);
mesgField = new TextField(
"Message", "hello, world!", 160, TextField.ANY);

form = new Form("SMS Message");


form.append(addressField);
form.append(mesgField);
form.addCommand(sendCommand);
form.addCommand(exitCommand);
}

public void startApp() {


display = Display.getDisplay(this);
form.setCommandListener(this);
display.setCurrent(form);
}

public void pauseApp() {}


public void destroyApp(boolean unconditional) {}

Pengembangan Perangkat Mobile 11


J.E.N.I.

public void commandAction(Command c, Displayable d) {


if (c == exitCommand) {
notifyDestroyed();
}
if (c == sendCommand) {
Thread thread = new Thread( this );
thread.start();
}
}

/**
* Sends an SMS message to number. This method will throw an
exception
* if there is an error in connecting or sending the message.
* @param number
* @param message
*/
public void sendSMS(String number, String message) throws Exception{
String url = "sms://" + number;
MessageConnection connection =
(MessageConnection) Connector.open(url);
TextMessage msg = (TextMessage) connection.newMessage(
MessageConnection.TEXT_MESSAGE);
msg.setPayloadText(message);
connection.send(msg);
connection.close();
}

public void run() {


try {
String address = addressField.getString();
String message = mesgField.getString();
sendSMS(address, message);
display.setCurrent(new Alert("SMS Message",
"Message Sent\n"
+ "To: " + address + "\n"
+ "Message: " + message,
null, AlertType.INFO));

Pengembangan Perangkat Mobile 12


J.E.N.I.

} catch (Exception ex) {


display.setCurrent(new Alert("SMS Error", ex.getMessage(),
null, AlertType.ERROR));
}
}
}

Pengembangan Perangkat Mobile 13


J.E.N.I.

Pengembangan Perangkat Mobile 14


J.E.N.I.

Pengembangan Perangkat Mobile 15


J.E.N.I.

Pengembangan Perangkat Mobile 16


J.E.N.I.

10.4.2 Menerima SMS

Untuk menerima sebuah pesan teks, buka sebuah port yang spesifik dari
MessageConnection. String protocol untuk pesan SMS adalah “sms”. Perintah ini
akan menangkap kedatangan pesan SMS dari port 8888:

conn = (MessageConnection) Connector.open("sms://:8888");

Kita harus mendaftarkan aplikasi Kita untuk menjadi sebuah Message Listener
sehingga AMS akan memperhatikan MIDlet Kita dari pesan yang masuk.

conn.setMessageListener(this);

NotifyIncomingMessage akan dipanggil oleh AMS ketika sebuah sebuah pesan


diterima oleh perangkat. Kita akan membutuhkan pembuatan sebuah Thread yang
terpisah untuk membaca pesan sehingga method panggilan ulang Listener dapat
berakhir tiba-tiba.

public void notifyIncomingMessage(MessageConnection messageConnection) {


if (thread == null){
thread = new Thread(this);
thread.start();

Pengembangan Perangkat Mobile 17


J.E.N.I.

}
}
Dalam method run() Kita, Kita telah siap untuk mendapatkan sebuah pesan :

public void run(){


try {
// menunggu dan menerima pesan
Message mesg = conn.receive();

// menerima pesan
// Mengecek apakah pesan berbentuk Teks
if (mesg != null && mesg instanceof TextMessage) {
TextMessage text = (TextMessage) mesg;
addressField.setText(text.getAddress());
mesgField.setText(text.getPayloadText());
dateField.setText("" + text.getTimestamp());
statusField.setText("Message received.");
}
} catch (Exception e) {
statusField.setText("Error: " + e.getMessage());
}
thread = null;
}

Berikut adalah listing program yang lengkap untuk penerima SMS :


import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import javax.wireless.messaging.*;

public class SMSReceiverMidlet extends MIDlet


implements CommandListener, MessageListener, Runnable {

private Command exitCommand, sendCommand;


private Form form;
private StringItem statusField, addressField, mesgField, dateField;
private Display display;

Pengembangan Perangkat Mobile 18


J.E.N.I.

private MessageConnection conn;


private Thread thread;
private String port = "8888";

public SMSReceiverMidlet() {
exitCommand = new Command("Exit", Command.EXIT, 1);

statusField = new StringItem("Status:", "");


addressField = new StringItem("From:", "");
mesgField = new StringItem("Message:", "");
dateField = new StringItem("Timestamp:", "");

form = new Form("SMS Receiver");


form.append(statusField);
form.append(addressField);
form.append(mesgField);
form.append(dateField);
form.addCommand(exitCommand);
}

public void startApp() {


display = Display.getDisplay(this);
form.setCommandListener(this);

startReceiver();
display.setCurrent(form);
}

public void pauseApp() {


thread = null;
}
public void destroyApp(boolean unconditional) {
thread = null;
if (conn != null){
try {
conn.close();
} catch (Exception ex){}

Pengembangan Perangkat Mobile 19


J.E.N.I.

}
}

public void commandAction(Command c, Displayable d) {


if (c == exitCommand) {
notifyDestroyed();
}
}

private void startReceiver(){


try {
String addr = "sms://:" + port;
if (conn == null){
conn = (MessageConnection) Connector.open(addr);

conn.setMessageListener(this);
statusField.setText(
"waiting for message at port " + port);
}
} catch (Exception ex){
statusField.setText("Cannot open connection on port "
+ port + ":" + ex.getMessage());
}

thread = new Thread(this);


thread.start();
}

public void notifyIncomingMessage(MessageConnection messageConn){


if (thread == null){
thread = new Thread(this);
thread.start();
}
}

public void run(){


try {

Pengembangan Perangkat Mobile 20


J.E.N.I.

// menunggu dan menerima pesan


Message mesg = conn.receive();

// menerima pesan
// mengecek apakah pesan berbasis teks
if (mesg != null && mesg instanceof TextMessage) {
TextMessage text = (TextMessage) mesg;
addressField.setText(text.getAddress());
mesgField.setText(text.getPayloadText());
dateField.setText("" + text.getTimestamp());
statusField.setText("Message received.");
} else {
statusField.setText(
"Non-text message received: "
+ mesg.getClass().toString());
}
} catch (Exception e) {
statusField.setText("Error: " + e.getMessage());
}
thread = null;
}
}

Pengembangan Perangkat Mobile 21


J.E.N.I.

Pengembangan Perangkat Mobile 22


J.E.N.I.

Pengembangan Perangkat Mobile 23


J.E.N.I.

10.5 Penggunaan Bluetooth bagi komunikasi


Wireless

Gambaran Umum
Bluetooth telah didesain bagi alat komunikasi personal yang mendukung komunikasi
tanpa kabel(wireless) seperti pada mobile phone maupun PDA dengan jarak sampai
10 kilometer. Bluetooth adalah sebuah protokol komunikasi yang beroperasi pada
frekuensi 2.4 GHz. Sinyal dari bluetooth adalah omni-directional yang dapat
menembus tembok. Ia dapat menerima data dan juga suara. Device yang
mendukung komunikasi bluetooth dapat dengan mudah menemukan koneksi dan
juga berkomunikasi dengan device yang lain secara otomatis.
Bluetooth dapat digunakan untuk mengirim file, membangun sebuah jaringan
tertentu, sinkronisasi data, mengkoneksikan sekitar misalnya dengan hands-free kits
dan gaming.

Berikut ini adalah beberapa karakteristik dari Bluetooth:


1. Tiga penggolongan yang berbeda berdasarkan jangkauan: kelas 1: 100m,
kelas2 = 20m, dan kelas 3=10m
2. Kecepatan 1Mb/s
3. Mengkonsumsi energi yang cukup rendah
4. Dapat mentransfer baik suara maupun data
5. Menggunakan signal Omni-direction
6. 2.4GHz – 2.482GHz band

Jaringan Bluetooth
Bluetooth devices dibagi lagi menjadi group-group kecil yang disebut piconet.
Didalam piconet, ada sebuah master dan satu atau lebih slaves. Sampai 7 buah
slaves bisa diterima didalam sebuah piconet. Sedangkan master unit adalah sesuatu
yang memulai proses komunikasi. Ia akan menggunakan komunikasi point-to-
multipoint.

Sebuah device didalam sebuah piconet mampu berkomunikasi dengan bluetooth


device didalam piconet yang lain. Sebuah slave didalam piconet tertentu mungkin
dapat menjadi slave didalam piconet yang berbeda. Sebuah master didalam sebuah
piconet dapat menjadi slave pada piconet yang lain. Komunikasi antar piconet
tersebut dapat berasal dari jaringan manapun.

Dalam rangka untuk pemeliharaan baterai, bluetooth memiliki tiga low modus
operasi yang hemat energi:

Pengembangan Perangkat Mobile 24


J.E.N.I.

Pada modus sniff, sebuah slave device akan memperhatikan berkurangnya level
energi, dimana ia tidak berpengaruh terhadap piconet.
Pada modus hold, sebuah device tidak hanya mengirimkan data tetapi ia juga
melakukan synkronisasi secara konstan dengan master. Ia bukanlah member aktif
dari piconet, tetapi ia menyimpan alamat member yang aktif.
Sebuah device pada modus park berlaku seperti device pada modus hold, akan
tetapi ia tidak menyimpan alamat member yang aktif.

Profile Bluetooth
Profile dari bluetooth telah ditentukan dengan memperhatikan interoperability antara
device dan aplikasi dari beberapa manufaktur. Sebuah profile mendefinisikan roles
dan kemampuan yang dimiliki oleh tipe aplikasi tertentu. Sebuah device hanya dapat
berkomunikasi dengan device yang lain apabila mereka memiliki profile yang sama.
Semua bluetooth device harus menggunakan Generic Access Profile. Profile ini
menentukan prosedure koneksi, device discovery, dan management link.
Sebuah Service Discovery Profile mendefinisikan fitur dan prosedur bagi aplikasi
bluetooth untuk mengenali segala servis yang telah ditentukan pada bluetooth
device yang lain.
Sebuah profile sinkronisasi menentukan hal-hal apa saja yang dibutuhkan pada dua
atau lebih devices untuk mensinkronisasikan data.
Profile bluetooth yang lain telah didefinisikan juga pada spesifikasi bluetooth. Akan
tetapi tidak akan dibicarakan dalam materi ini.

Keamanan pada Bluetooth

Spesifikasi dari Bluetooth telah menyediakan spesifikasi untuk keamanan dalam tiga
hal. Pertama dengan menggunakan frekuensi, yang diharapkan dapat membuat
eavesdropper dari komunikasi bluetooth mengalami kesulitan. Limit pada koneksi
autentikasi pada device tertentu. Enkripsi dengan secret key untuk membuat data
tidak dapat dibaca oleh eavesdropper.

Generic Access Profile telah mendefinisikan sebuah security model yang melingkupi
tiga modus security:

Mode 1: Sebuah modus yang tidak aman karena tidak adanya prosedur keamanan.
Mode 2: Keamanan yang berada pada level servis. Tidak ada prosedur keamanan
yang diinisialisasi sebelum channel komunikasi dibangun. Aplikasi mungkin
mendapatkan kesulitan policy akses.
Mode 3: Keamanan yang berada pada level link. Sebuah prosedur keamanan akan
diinisialisasi sebelum menyelesaikan link-setup.

Pengembangan Perangkat Mobile 25


J.E.N.I.

Protocol Stack pada Bluetooth


Berikut ini adalah ilustrasi dari Bluetooth protokol stack yang pertama.

Application

Java Bluetooth API


JSR-82

OBEX

Service
RFCOMM
Discovery

L2CAP

Host Controller Interface (HCI)

Bluetooth J2ME optional package seperti telah didefinisikan pada pada JSR 82 akan
mendukung Anda untuk mengontrol bluetooth device. Untuk mengirimkan data
diantara device yang mendukung bluetooth, Anda mungkin dapat menggunakan satu
dari tiga koneksi berikut ini: L2CAP, RFCOMM, dan OBEX.

L2CAP –untuk data packet


RFCOMM – satu layer diatas protokol L2CAP dan digunakan untuk data streaming.
OBEX – digunakan untuk data object

Aplikasi RFCOMM

Contoh aplikasi berikut ini menggunakan protokol serial RFCOMM untuk


berkomunikasi dengan device bluetooth. Aplikasi ini adalah tulang punggung dari
sebuah information server dan client-nya.

Server pertama kali akan mendaftarkan service-nya:

Pengembangan Perangkat Mobile 26


J.E.N.I.

localDevice = LocalDevice.getLocalDevice();
localDevice.setDiscoverable(DiscoveryAgent.GIAC);
notifier = (StreamConnectionNotifier) Connector.open(URL);

Kemudian ia akan menunggu koneksi:

StreamConnection conn = notifier.acceptAndOpen();

Sekali sebuah koneksi diterima, kemudian ia akan membaca command dan


menjawab dengan jawaban yang tepat dengan menggunakan method untuk koneksi
serial.

Client pertama kali akan mencari device yang tersedia untuk service tersebut:

LocalDevice localDevice = LocalDevice.getLocalDevice();


discoveryAgent = localDevice.getDiscoveryAgent();

discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);

Client akan meng-implement DiscoveryListener dan meng-override method yang


diperlukan untuk menerima notifikasi dari device. Sekali device ditemukan dan
proses pencarian servis sudah selesai dilaksanakan, kemudian command tertentu
akan dibutuhkan.

InfoServer.java:

import javax.bluetooth.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;

public class InfoServer implements Runnable {


InputStream input;
OutputStream output;
StreamConnectionNotifier notifier;
StreamConnection conn;
LocalDevice localDevice;
ServiceRecord serviceRecord;

Pengembangan Perangkat Mobile 27


J.E.N.I.

public static String SERVICE_NAME = "chat";


public static UUID PORT = new UUID(0x0518);

private boolean isRunning = false;


private static String URL = "btspp://localhost:" + PORT +
";name=" + SERVICE_NAME + ";authorize=true";

public InfoServer() {
isRunning = false;
Thread thread = new Thread(this);
thread.start();
}

public void run() {

if (!isRunning) {
try {
conn = null;

localDevice = LocalDevice.getLocalDevice();
localDevice.setDiscoverable(DiscoveryAgent.GIAC);

notifier = (StreamConnectionNotifier)
Connector.open(URL);

} catch (BluetoothStateException e) {
System.err.println("Bluetooth Exception: " +
e.getMessage());
} catch (IOException e) {
System.err.println( "IO Exception: " + e.getMessage());
}

isRunning = true;
}

while (true) {

Pengembangan Perangkat Mobile 28


J.E.N.I.

try {
System.out.println("Waiting for connection...\n");

// Menunggu koneksi
conn = notifier.acceptAndOpen();

// Membaca command
String msg = BluetoothMidlet.read(conn);
System.out.println("Received from Client: " + msg);

// Mengirim balasan
msg = "InfoServer: Your command was: " + msg;
output = conn.openOutputStream();
output.write(msg.length());
output.write(msg.getBytes());
output.close();
} catch (Exception ex) {
System.err.println("Bluetooth Server Exception: " + ex);
}
}
}
}

InfoClient.java:
import javax.bluetooth.*;
import javax.microedition.io.*;
import java.io.*;

class InfoClient implements DiscoveryListener {


private DiscoveryAgent discoveryAgent;
private RemoteDevice[] remoteDevices;
private UUID[] UUIDSet;
private String URL;

public InfoClient() {
try {

Pengembangan Perangkat Mobile 29


J.E.N.I.

LocalDevice localDevice = LocalDevice.getLocalDevice();


discoveryAgent = localDevice.getDiscoveryAgent();

discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);
} catch (Exception e) {
System.out.println(e);
}
}

public void deviceDiscovered(RemoteDevice btDevice, DeviceClass


cod) {
try {
// Mendapatkan informasi dari device
System.out.println("deviceDiscovered()");
System.out.println("Address: " +
btDevice.getBluetoothAddress());
System.out.println("Major Device Class: " +
cod.getMajorDeviceClass());
System.out.println("Minor Device Class: " +
cod.getMinorDeviceClass());
System.out.println("Friendly Name: " +
btDevice.getFriendlyName(true));

UUIDSet = new UUID[1];


UUIDSet[0] = InfoServer.PORT;

int searchID = discoveryAgent.searchServices(null, UUIDSet,


btDevice, this);

} catch (Exception e) {
System.out.println("Exception: " + e);
}
}

public void servicesDiscovered(int transID, ServiceRecord[]


servRecord) {
System.out.println("servicesDiscovered()");

for (int i=0; i<servRecord.length; i++) {

Pengembangan Perangkat Mobile 30


J.E.N.I.

URL = servRecord[i].getConnectionURL(0, false);


}
}

public void serviceSearchCompleted(int transID, int responseCode) {


switch (responseCode) {
case SERVICE_SEARCH_COMPLETED:
System.out.println("SERVICE_SEARCH_COMPLETED\n");
System.out.println("Service URL: " + URL);

StreamConnection conn = null;


try {
String msg = "INFO";
conn = (StreamConnection)Connector.open(URL);
OutputStream output = conn.openOutputStream();
output.write(msg.length());
output.write(msg.getBytes());
output.close();

System.out.println(BluetoothMidlet.read(conn));

} catch (Exception ex) {


System.out.println(ex);
} finally {
try {
conn.close();
} catch (IOException ioe) {
System.out.println("Error Closing connection "
+ ioe);
}
}

break;

case SERVICE_SEARCH_ERROR:
System.out.println("SERVICE_SEARCH_ERROR\n");
break;
case SERVICE_SEARCH_TERMINATED:

Pengembangan Perangkat Mobile 31


J.E.N.I.

System.out.println("SERVICE_SEARCH_TERMINATED");
break;
case SERVICE_SEARCH_DEVICE_NOT_REACHABLE:
System.out.println("SERVICE_SEARCH_DEVICE_NOT_REACHABLE
");
break;
case SERVICE_SEARCH_NO_RECORDS:
System.out.println("SERVICE_SEARCH_NO_RECORDS");
break;

default: break;
}
}

public void inquiryCompleted(int discType) {


System.out.println("inquiryCompleted()");
}
}

BluetoothMidlet.java:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import javax.bluetooth.*;
import java.io.*;

public final class BluetoothMidlet extends MIDlet implements


CommandListener {

private final Command okCmd = new Command("Start", Command.OK, 1);


private final Command exitCmd = new Command("Exit", Command.EXIT,
1);

private static final String[] commands = { "Server", "Client" };


private final List menu = new List("Bluetooth Application",
List.IMPLICIT, commands, null);

Pengembangan Perangkat Mobile 32


J.E.N.I.

Display display;
private InfoClient chatClient;
private InfoServer chatServer;

public BluetoothMidlet() {
menu.addCommand(exitCmd);
menu.addCommand(okCmd);
menu.setCommandListener(this);
}

public void startApp() {


display = Display.getDisplay(this);
display.setCurrent(menu);
}

protected void destroyApp(boolean unconditional) {


}

protected void pauseApp() {


}

public void commandAction(Command c, Displayable d) {


if (c == exitCmd) {
destroyApp(true);
notifyDestroyed();
return;
}

switch (menu.getSelectedIndex()) {
case 0: chatServer = new InfoServer(); break;
case 1: chatClient = new InfoClient(); break;
default: break;
};
}

Pengembangan Perangkat Mobile 33


J.E.N.I.

public final static String read(StreamConnection conn) {

InputStream is = null;
byte[] dataBytes = null;
int len;

try {
is = conn.openInputStream();

len = is.read();
dataBytes = new byte[len];
len = 0;

while (len != dataBytes.length) {


int readLen = is.read(dataBytes, len, dataBytes.length
- len);
if (readLen == -1) {
System.err.println("Error reading data.");
}
len += readLen;
}
} catch (IOException ex) {
System.err.println(ex);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ex) { }
}
}
return new String(dataBytes);
}

Pengembangan Perangkat Mobile 34


J.E.N.I.

10.6 Lokasi API


Location-based Services

Location based services memanfaatkan lokasi dari device untuk menyediakan


informasi mengenai lokasi. Pertanyaan utama yang dijawab oleh Location Based
Service adalah “Dimana saya?” . Untuk lebih spesifiknya adalah “Dimana letak
device?”.

Aplikasi yang lebih popular mengenai penginformasian lokasi adalah dengan


menggunakan telepone genggam, orang tua dapat melacak dimana anaknya
sekarang berada. Atau dengan telepone genggam tersebut dapat menemukan toko
atau restoran yang paling dekat, mendapatkan informasi mengenai lalu lintas pada
lokasi tertentu dan mendapatkan sebuah arahan menuju tempat tertentu.
Penggunakan data mengenai lokasi untuk mendapatkan pengalaman yang lebih pada
game dan juga bagi aplikasi-aplikasi social networking adalah beberapa contoh dari
banyaknya kemungkinan aplikasi yang dapat memanfaatkan penginformasian lokasi.

Lokasi dari device ditentukan oleh salah satu dari beberapa location service yang
telah tersedia seperti Global Positioning System (GPS) atau informasi dari jaringan
seluler itu sendiri (seperti site ID dari seluler). GPS memanfaatkan network dari
satelit untuk digunakan dan dikontrol oleh Departemen pertahanan US. GPS dapat
menjadi tidak efektif, apabila ia didalam bangunan atau diantara tumbuh-tumbuhan
yang lebat. Akan tetapi, ia sangat akurat sampai 5-30 meter.

Penginformasian lokasi dari dari seluler site dapat digunakan apabila aplikasi tidak
membutuhkan banyak akurasi. Lingkup dari cell site sangat bervariasi, dari beberapa
kilometer sampai dengan 20 kilometer.

The Location API for J2ME (JSR 179)

javax.microedition.location package memiliki class-class yang digunakan untuk


mendapatkan informasi mengenai lokasi sebuah device.

Beberapa method khusus digunakan untuk menentukan terminal dari lokasi device.
API tersebut akan mengembalikan informasi-informasi berikut ini:
1. Garis Lintang
2. Garis Bujur
3. Keakuratan dari informasi mengenai garis lintang dan bujur
4. Timestamp pada saat penentuan sebuah lokasi

Ketersediaan dari fitur-fitur diatas bergantung pada method yang digunakan untuk
menentukan informasi lokasi:

Pengembangan Perangkat Mobile 35


J.E.N.I.

• Ketinggian dari permukaan laut dan keakuratan dari pengukuran


tersebut.
• Informasi mengenai kecepatan dan jalan raya
• Informasi mengenai alamat
• Proximity landmark pada event tertentu
• Sebagai kompas yang menunjuk ke arah utara sesuai dengan
orientasi dari device
• Informasi mengenai pitch (puncak) dan roll

Location Provider

Location provider berfungsi sebagai sumber dari penginformasian lokasi. Aplikasi


dapat menyediakan sebuah kriteria (dimungkinkan juga termasuk akurasinya) pada
saat mendapatkan instance dari LocationProvider. Method yang mengakses informasi
mengenai lokasi akan melalui SecurityException jika aplikasi tidak mendapatkan
permission untuk mengakses informasi tertentu.

Pengembangan Perangkat Mobile 36


J.E.N.I.

Security
Tabel Loc01 terdiri dari nama-nama permission dan method yang dilindungi oleh
permission tersebut.

Nama Permission Method yang dilindungi


javax.microedition.location.Location LocationProvider.getLocation(),
LocationProvider.setLocationListener()
javax.microedition.location.Orientatio Orientation.getOrientation()
n
javax.microedition.location.ProximityL LocationProvider.addProximityListener(
istener )
javax.microedition.location.LandmarkSt LandmarkStore.getInstance(),

Pengembangan Perangkat Mobile 37


J.E.N.I.

Nama Permission Method yang dilindungi


ore.read LandmarkStore.listLandmarkStores()
javax.microedition.location.LandmarkSt LandmarkStore.addLandmark(),
ore.write LandmarkStore.deleteLandmark(),
LandmarkStore.removeLandmarkFromCatego
ry(),
LandmarkStore.updateLandmark()
javax.microedition.location.LandmarkSt LandmarkStore.addCategory(),
ore.category LandmarkStore.deleteCategory()
javax.microedition.location.LandmarkSt LandmarkStore.createLandmarkStore(),
ore.management LandmarkStore.deleteLandmarkStore()

Landmarks

Location API juga mendukung penyimpanan informasi mengenai landmark dengan


menggunakan LandmarkStores. Device yang menggunakan JSR 179 memerlukan
paling tidak satu LandmarkStore untuk menyimpan sebuah landmark.

Sebuah landmark adalah sebuah lokasi yang nama-nya diketahui oleh user. Sebuah
landmark juga dapat terdiri dari penjelasan-penjalasan (text), garis koordinat, dan
informasi mengenai alamat (optional). Sebuah landmark direpresentasikan dengan
Location API dalam class javax.microedition.location.landmark. Class ini hanya
merupakan sebuah container dari informasi.

LandmarkStore class terdiri dari method-method pada proses penyimpanan data,


pengambilan kembali data yang sudah ada, dan juga menghapus sebuah landmark
didalam sebuah persistent landmark store. Penggunaan dari Location API paling
tidak memiliki sebuah landmark store, sebagai default. Implementasi yang lain dari
Location API dimungkinkan untuk mendukung lebih dari sebuah landmark store dan
kemudian semua data yang disimpan akan digunakan secara bersama-sama oleh
beberapa aplikasi.

Penamaan sebuah landmark sangat dibutuhkan dan nama tersebut akan


dipresentasikan kepada user. Landmark dapat ditempatkan pada Category nol atau
yang lain. Nama sebuah category haruslah unique didalam landmark store, akan
tetapi nama sebuah landmark dimungkinkan untuk diduplikasi didalam sebuah
landmark store.

Location Listener

Sebuah location listener tunggal dapat meregistrasikan dirinya kepada sebuah


instance Landmark provider. Listener ini harus implement LocationListener interface.
Method locationUpdate() akan dipanggil berulang kali didalam sistem tergantung
kepada interval yang diberikan oleh aplikasi.

Pengembangan Perangkat Mobile 38


J.E.N.I.

Sistem tidak akan menggaransi bahwa method tersebut akan dipanggil pada interval
tertentu. Akan tetapi, dimungkinkan location provider memberikan informasi yang
tidak akurat terutama apabila location provider tersebut tidak dapat memberikan
informasi mengenai lokasi tersebut tepat waktu.

Method providerStateChanged() juga akan dipanggil kemudian status dari location


provider akan berubah. Implementasi dari method ini akan di-return seketika.
Apabila method ini membutuhkan waktu yang cukup lama pada saat implementasi,
maka aplikasi tersebut harus menggunakan thread secara terpisah.

Proximity Listener

Baik nol maupun lebih proximity listener harus didaftarkan pada object dari
landmark provider. Method proximityEvent() dari proximity listener akan dipanggil
apabila device tersebut terletak didalam jangkauan koordinat yang telah didaftarkan.
Sebuah proximity listener harus didaftarkan lagi (jika diperlukan) setelah
pemanggilan sebuah method karena proses pendaftaran akan tertunda pada saat
listener dipanggil.

Pengidentifikasian Location API

Sebuah aplikasi dapat mengetest eksistensi dan versi dari Location API dengan cara
meng-query sistem property dengan kunci “microedition.location.version”. Method
System.getProperty yang telah disediakan dengan kunci tersebut akan me-return
versi string. Misalnya, implementasi dari JSR 179 pada versi 1.0 akan me-return
string “1.0”.

Location API yang didukung oleh Sun Java Wireless Toolkit

Pengembangan Perangkat Mobile 39


J.E.N.I.

Pengembangan Perangkat Mobile 40


J.E.N.I.

Sejak versi 2.3, Sun Java Wireless Toolkit memberikan dukungan pada Location API.
Preference pada API dapat dimodifikasi dengan cara: Tools-> Java Platform Manager
-> J2ME -> Sun Java Wireless Toolkit -> Tools and Extensions -> Open Preferences
-> Location. Landmark dapat di-manage pada bagian Utilities dari Toolkit.
Dari MIDlet window (pada saat Anda menjalankan aplikasi dari emulator), window
“External Events” dapat diakses pada menu. Pada tab Location, Anda dapat
mensimulasikan dan memodifikasi lokasi device saat ini.

Location01.java:
/*
* LocationMidlet.java
*
*/

package jedi;

Pengembangan Perangkat Mobile 41


J.E.N.I.

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.location.*;

/**
*
* @author jedi
* @j
*/
public class LocationMidlet extends MIDlet implements CommandListener,
Runnable {
private final Command exitCmd = new Command("Exit", Command.EXIT,
1);
private final Command locationCmd = new Command("Location",
Command.ITEM, 1);
private Display display;
private Form mainForm = new Form("JEDI: Location Example");
private StringItem latitude = new StringItem("Latitude:", "",
Item.PLAIN);
private StringItem longtitude = new StringItem("Longtitude:", "",
Item.PLAIN);
private StringItem altitude = new StringItem("Altitude:", "",
Item.PLAIN);
private StringItem speed = new StringItem("Speed:", "", Item.PLAIN);
private StringItem course = new StringItem("Course:", "",
Item.PLAIN);
private StringItem locMethod = new StringItem("Method:", "",
Item.PLAIN);
private StringItem timestamp = new StringItem("Timestamp:", "",
Item.PLAIN);
private StringItem status = new StringItem("Status:", "",
Item.PLAIN);
private StringItem version = new StringItem("Version:", "Unknown",
Item.PLAIN);
private LocationProvider locationProvider;

public LocationMidlet() {
mainForm.addCommand(exitCmd);
mainForm.addCommand(locationCmd);
mainForm.setCommandListener(this);

Pengembangan Perangkat Mobile 42


J.E.N.I.

version.setText(System.getProperty("microedition.location.versi
on"));

mainForm.append(version);
mainForm.append(latitude);
mainForm.append(longtitude);
mainForm.append(altitude);
mainForm.append(speed);
mainForm.append(course);
mainForm.append(locMethod);
mainForm.append(timestamp);
mainForm.append(status);
}

public void startApp() {


display = Display.getDisplay(this);
display.setCurrent(mainForm);
}

public void pauseApp() {


}

public void destroyApp(boolean unconditional) {


}

public void commandAction(Command c, Displayable d) {


if (c == locationCmd) {
Thread thread = new Thread(this);
thread.start();
}
if (c == exitCmd) {
destroyApp(true);
notifyDestroyed();
return;
}
}
public void run() {
try {

Pengembangan Perangkat Mobile 43


J.E.N.I.

Criteria cr = new Criteria();


// Men-set akurasi Horisontal ke 1 kilometer
cr.setHorizontalAccuracy(0);
cr.setVerticalAccuracy(0);
LocationProvider provider =
LocationProvider.getInstance(cr);

// Timeout setelah 30 detik


Location loc = provider.getLocation(30);

Coordinates coord = loc.getQualifiedCoordinates();


if (coord != null) {
if (loc.isValid()) {
latitude.setText(Coordinates.convert(coord.getLatit
ude(), Coordinates.DD_MM_SS));
longtitude.setText(Coordinates.convert(coord.getLon
gitude(), Coordinates.DD_MM_SS));
altitude.setText(Float.toString(coord.getAltitude()
));
timestamp.setText(Long.toString(loc.getTimestamp())
);
speed.setText(Float.toString(loc.getSpeed()));
locMethod.setText(Integer.toString(loc.getLocationM
ethod()));
course.setText(Float.toString(loc.getCourse()));

status.setText("Valid Location Information");


} else {
status.setText("Invalid Location Information");
}

}
} catch (LocationException e) {
status.setText("Exception:" + e.getMessage());
} catch (InterruptedException e) {
status.setText("Timeout: " + e.getMessage());
}
}
}

Pengembangan Perangkat Mobile 44


J.E.N.I.

Pengembangan Perangkat Mobile 45


J.E.N.I.

10.7 Latihan
10.7.1 Audio Player

Buatlah sebuah MIDlet yang dapat memainkan file audio sebagai sebuah indefinite loop. Audio
tersebut akan dibaca dari JAR file. Petunjuk: Anda harus menge-set properti dari player untuk
mengontrol looping.

10.7.2 SMS Auto-Responder

Buatlah sebuah MIDlet yang secara otomatis akan me-reply apabila ia menerima sebuah text
message. Petunjuk: Anda dapat memodifikasi SMSReceiverMidlet dan menggunakan koneksi
yang sama untuk me-reply pesan.

Pengembangan Perangkat Mobile 46


J.E.N.I.

Bab 11
Topik-topik Tambahan

11.1 Tujuan

Setelah menyelesaikan bab ini, siswa diharapkan mampu:


• mengatur jadwal tugas menggunakan Timers
• meregister koneksi yang datang pada Push Registry

11.2 Timers

Timer dan TimerTasks berfungsi agar Anda bisa melakukan penjadwalan tugas pada
suatu waktu. Tugas dapat juga dijadwalkan untuk diulang-ulang sampai interval
tertentu.

Anda dapat membuat tugas dengan menurunkan (extending) TimerTask dan


mengimplement method run(). Method run() akan dieksekusi berdasarkan jadwal yang
ada pada Timer.

class CounterTask extends TimerTask {


int counter = 0;
public void run() {
System.out.println("Counter: " + counter++);
}
}

Untuk menjadwalkan sebuah tugas, buat sebuah Timer dan gunakan method schedule()
yang ada pada Timer untuk menjadwalkan jalannya tugas. Setiap Timer berjalan pada
bagian yang terpisah. Method schedule() memiliki beberapa bentuk. Anda dapat
mengatur waktu tugas untuk mulai dengan memberikan delay dalam mililiseconds atau
dengan memberikan waktu absolut (java.util.Date). Parameter ketiga pada method
schedule() adalah periode pengulangan dari tugas. Jika nilai pengulangan diberikan,
tugas akan dieksekusi dalam periode waktu tertentu.

Timer timer = new Timer();


TimerTask task = new CounterTask();

Pengembangan Perangkat Mobile 1


J.E.N.I.

// task akan dimulai dalam 8 detik dan diulangi setiap 1 detik


timer.schedule(task, 8000, 1000);
Anda dapat menghentikan timer dengan menggunakan method close(). Method ini dapat
menghentikan timer dan mengabaikan tugas yang dijadwalkan. Perlu Anda catat, bahwa
ketika Timer dihentikan, maka tidak dapat diulangi (direstart) kembali.

void schedule(TimerTask task, Long delay)

Melakukan penjadwalan tugas untuk dieksekusi sesudah menentukan delay yang


diinginkan (dalam milliseconds)
void schedule(TimerTask task, Long delay , long period)

Melakukan penjadwalan tugas untuk dieksekusi berulang-ulang, dimulai


sesudah delay yang ditentukan (dalam milliseconds)
void schedule(TimerTask task, Date time)

Melakukan penjadwalan tugas agar dapat dieksekusi pada waktu yang


ditentukan.
void schedule(TimerTask task, Date time, long period)

Melakukan penjadwalan tugas untuk dieksekusi berulang-ulang, dimulai pada


waktu yang ditentukan.
void cancel()

Menghentikan timer, mengabaikan tugas yang dijadwalkan.

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

import java.io.*;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Date;

public class TimerMidlet extends MIDlet implements CommandListener{


private Command exitCommand;
private Form form;
private StringItem textField;
private Display display;

Pengembangan Perangkat Mobile 2


J.E.N.I.

public TimerMidlet() {
exitCommand = new Command("Exit", Command.EXIT, 1);
textField = new StringItem("Counter", "");

Timer timer = new Timer();


TimerTask task = new CounterTask(this);
timer.schedule(task, 2000, 1000);

form = new Form("Timer Test");


form.addCommand(exitCommand);
form.append(textField);
}

public void startApp() {


display = Display.getDisplay(this);
form.setCommandListener(this);
display.setCurrent(form);
}

public void pauseApp() {}


public void destroyApp(boolean unconditional) {
timer.cancel();
}

public void commAndaction(Command c, Displayable d) {


if (c == exitCommand) {
destroyApp(true);
notifyDestroyed();
}
}

public void setText(String text){


textField.setText(text);
}
}

class CounterTask extends TimerTask {

Pengembangan Perangkat Mobile 3


J.E.N.I.

int counter = 0;
TimerMidlet midlet;

public CounterTask(TimerMidlet midlet){


this.midlet = midlet;
}

public void run() {


counter++;
midlet.setText("" + counter);
System.out.println("Counter: " + counter);
}
}

11.3 Push Functionality

Push Registry berfungsi agar MIDlet bisa meregister koneksi yang masuk dengan
Application Management Software (AMS). Jika program tidak berjalan, AMS akan
mendengarkan koneksi pada alamat yang telah diregister oleh aplikasi. Hampir semua
tipe koneksi didukung, termasuk ServerSocket dan MessageConnection.

Anda dapat meregister koneksi yang masuk dengan Push Registry menggunakan dua
cara: cara statis dengan menggunakan file application descriptor (JAD) atau dinamis
selama proses runtime menggunakan PushRegistry API.

Pada bab ini kita akan meregister secara statis push application kita pada application
descriptor (JAD) kita. NetBeans Mobility Pack membantu kita untuk memodifikasi
Application Descriptor dengan mudah termasuk pada Push Registry.

Klik kanan pada Project name, selanjutnya klik Properties untuk membuka Properties
Page pada project.

Pengembangan Perangkat Mobile 4


J.E.N.I.

Pilih bagian Push Registry:

Klik "Add" untuk meregister koneksi yang masuk:

Pengembangan Perangkat Mobile 5


J.E.N.I.

Ulangi proses sebelumnya hingga semua koneksi yang masuk sudah teregister. Dalam
kasus ini, kita melakukan koneksi sms pada port 8888 dan koneksi socket (socket
connection) pada port 1234:

Pengembangan Perangkat Mobile 6


J.E.N.I.

Pilih bagian "API Permissions":

Pilih "Add" untuk menambah ijin (permission) untuk aplikasi MIDlet. Kita harus
menambahkan API javax.microedition.io.PushRegistry untuk menginstall aplikasi. Kita
juga harus menambahkan semua API yang digunakan oleh aplikasi:

Pengembangan Perangkat Mobile 7


J.E.N.I.

Hilangkan tAnda pada bagian required untuk semua API:

Pengembangan Perangkat Mobile 8


J.E.N.I.

Pilih bagian "Signing" dan beri tAnda "Sign Distribution" untuk mendaftarkan aplikasi
MIDlet:

Pengembangan Perangkat Mobile 9


J.E.N.I.

Pilih bagian "Running" dan pilih "Execute through OTA (Over the Air Provisioning)". Hal
ini merupakan proses instalasi dan eksekusi aplikasi pada device.

Pengembangan Perangkat Mobile 10


J.E.N.I.

Langkah selanjutnya adalah menjalankan aplikasi MIDlet. Pastikan build berjalan dan
tidak ada error ketika melakukan instalasi device (via OTA provisioning).

Pengembangan Perangkat Mobile 11


J.E.N.I.

Untuk menjalankan aplikasi MIDlet, gunakan WMA console (Tools -> Java Platform
Manager -> J2ME Wireless Toolkit 2.2 -> Open Utilities -> WMA: Open Console -> Send
SMS...). Pilih nomor device, tentukan nomor port yang sudah ada pada PushRegistry,
masukkan pesan dan klik "Send":

Pengembangan Perangkat Mobile 12


J.E.N.I.

AMS akan menerima koneksi yang datang dan menanyakan konfirmasi selanjutnya
kepada user:

Pengembangan Perangkat Mobile 13


J.E.N.I.

Ini adalah aplikasi MIDlet, dijalankan melalui Push Registry (melalui pesan SMS masuk):

Pengembangan Perangkat Mobile 14


J.E.N.I.

Ini adalah aplikasi kita yang dijalankan melalui Push Registry (socket pada port 1234).
Untuk menjalankan aplikasi MIDlet dengan cara ini, layar console dan ketik "telnet
localhost 1234".

Pengembangan Perangkat Mobile 15


J.E.N.I.

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

import java.io.*;
import java.util.Timer;
import java.util.TimerTask;
import javax.microedition.io.*;

public class PushMidlet extends MIDlet implements CommandListener{


private Command exitCommand;
private Form form;
private StringItem textField;
private Display display;

private String[] connections;

public PushMidlet() {
exitCommand = new Command("Exit", Command.EXIT, 1);
textField = new StringItem("Status", "");

form = new Form("Push via sms message");


form.addCommand(exitCommand);
form.append(textField);
}

public void startApp() {

connections = PushRegistry.listConnections(true);

if (connections != null && connections.length > 0){


textField.setText(
"Launched via Push Registry: " + connections[0]);
}

display = Display.getDisplay(this);
form.setCommandListener(this);

Pengembangan Perangkat Mobile 16


J.E.N.I.

display.setCurrent(form);
}

public void pauseApp() {}


public void destroyApp(boolean unconditional) {}

public void commAndaction(Command c, Displayable d) {


if (c == exitCommand) {
notifyDestroyed();
}
}

public void setText(String text){


textField.setText(text);
}
}

Pengembangan Perangkat Mobile 17


J.E.N.I.

11.4 Latihan
11.4.1 Time Midlet

Buatlah sebuah aplikasi MIDlet yang menampilkan tanggal dan waktu hari ini dan
terupdate setiap detik. Gunakan Timer untuk melakukan update dan StringItem untuk
menampilkan tanggal dan waktu.

Pengembangan Perangkat Mobile 18

Anda mungkin juga menyukai