Pengembangan Perangkat
Mobile
Versi 1.1
April 2007
Sumber : JEDI
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:
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.
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
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
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
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
11 Topik-topik Tambahan
11.1 Tujuan
11.2 Timers
11.3 Push Functionality
11.4 Latihan
11.4.1 Time MIDlet
Bab 1
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 :
J2EE – Java 2 Platform, Enterprise Edition Aplikasi enterprise dengan fokus pada
pengembangan sisi webserver, termasuk
servlet,JSP,EJB, dan XML
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
Applications
Optional OEM
Profile
Packages APIs
Libraries
Configuration {
Java Virtual Machine
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:
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:
● Library dasar(java.lang.*,java.util.*)
● Input/Output(java.io.*)
● Kemanan
● Jaringan
● Internationalization
● Asynchronous exceptions
● Reflection
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.
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.*).
File.java
Install
File.class
preverify interpret
File.class
Connection
StreamConnectionNotifier DatagramConnection
InputConnection OutputConnection
StreamConnection
ContentConnection
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.
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.
MIDlets
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.
• 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
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.
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.
new
destroyApp()
startApp() Paused
Destroyed
Active pauseApp()
destroyApp()
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
● Faktor kesenangan
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.
2.2 Pengenalan
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.
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.
/*
* HelloMidlet.java
*
* Created on July 8, 2000, 9:00 AM
*/
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
/**
*
* @author JEDI Apprentice
* @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);
}
display.setCurrent(helloAlert);
}
}
}
Selanjutnya kita akan mempelajari MIDlet pertama kita, difokuskan pada line yang
penting dari code diatas:
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.
commandAction() diatas hanya menghandle request untuk perintah "Exit". Method diatas
akan menghentikan program menggunakan notifyDestroyed() jika perintah "Exit"
dijalankan atau ditekan.
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-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.
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.
− File JAR
− File Java Application Descriptor (JAD)
− 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)
− MicroEdition-Profile
− MicroEdition-Configuration
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.
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.
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.
Sekarang kita menggunakan Sun Wireless Toolkit untuk mengcompile dan memaketkan
aplikasi MIDlet / MIDlet suite (mengandung satu MIDlet)
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.
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":
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 9
Gambar 2: Membuat MIDlet secara otomatis membuat method MIDlet yang diperlukan
Langkah 10: Mengganti code yang dibuat secara otomatis dengan code program
kita.
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.
Gunakan Sun Wireless Toolkit untuk menambahkan MIDlet baru pada aplikasi MIDlet
anda.
Bab 3
High Level User Interface
3.1 Tujuan
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.
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).
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.
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).
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
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 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
Command.OK, Command.BACK,
Command.CANCEL, Command.EXIT,
Command.HELP, Command.ITEM,
Command.SCREEN, Command.STOP
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
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().
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.
3.2.8 Item
Items merupakan komponen yang dapat diletakan kedalam container, seperti Form atau
Alert. Sebuah item dapat memiliki property seperti dibawah ini:
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 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.
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.*;
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),
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);
// Menge-Set alert
alerts[5].setTimeout(Alert.FOREVER);
}
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.
Jika List bertipe IMPLICIT dan user mengeksekusi tombol “select”, commandAction() dari
list commandListener akan dipanggil. Default perintahnya adalah
List.SELECT_COMMAND.
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
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);
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().
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.
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.
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”.
DateField dateonly =
new DateField("Birthday (DATE)", DateField.DATE);
DateField timeonly =
new DateField("Set Alarm (TIME)", DateField.TIME);
DateField datetime =
new DateField("Departure (DATE_TIME)", DateField.DATE_TIME);
dateForm.append(dateonly);
dateForm.append(timeonly);
dateForm.append(datetime);
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.append(plain);
stringForm.append(hyperlink);
stringForm.append(button);
Gambar: StringItem
ImageItem menerima item layout sebagai parameter (Lihat pada bagian Item):
public ImageItem(
String label,
Image img,
int layout,
String altText)
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”.
Gambar: ImageItem
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
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().
textForm.append(ANY);
textForm.append(EMAILADDR);
textForm.append(NUMERIC);
textForm.append(PHONENUMBER);
textForm.append(URL);
textForm.append(DECIMAL);
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.
Bab 4
Low Level User Interface
4.1 Tujuan
Setelah mempelajari bab ini, Pelajar diharapkan mampu untuk :
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.
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.
Class Canvas menggambarkan sebuah metode abstrak yang disebut paint(). Aplikasi
menggunakan class Canvas harus menyediakan sebuah implementasi untuk metode
paint().
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.
(0,0)
increasing x value
increasing y value
(getwidth()-1,getHeight()-1)
4.3.2 ”Hello,World!”
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
HelloCanvas canvas;
if (display == null){
display = Display.getDisplay(this);
display.setCurrent(canvas);
destroyApp(true);
notifyDestroyed();
this.midlet = midlet;
this.text = text;
addCommand(exitCommand);
setCommandListener(this);
g.setColor(0, 0, 0);
g.drawString(text,
getWidth()/2, getHeight()/2,
Graphics.TOP | Graphics.HCENTER);
if (c == exitCommand){
midlet.Quit();
Dengan midlet “Hello,World!”, kita membuat sebuah class yang ber-extend Canvas
Kemudian kita menambahkan perintah (“Exit”) dan mengatur command listener nya.
addCommand(exitCommand);
setCommandListener(this);
...
...
Inti dari program ini adalah metode paint(). Set pertama dari pemanggilan metode
adalah membersihkan layar.
g.setColor(0, 0, 0);
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 :
addCommand(exitCommand);
setCommandListener(this);
...
if (c == exitCommand){
// do something
Subclass dari Canvas dapat merespon sebuah event tombol dengan metode-metode
sebagai berikut :
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).
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.
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.
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.
Untuk mengatur warna yang digunakan untuk metode grafik berikutnya, gunakan
metode setColor(). SetColor() memiliki dua bentuk:
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:
...
warna terbaru
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.
FONT_INPUT_TEXT
atau
FONT_STATIC_TEXT
STYLE_BOLD | STYLE_ITALIC
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.
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.
TOP | HCENTER
BOTTOM | HCENTER
BASELINE | HCENTER
Berikut adalah beberapa metode dari Font yang berguna dalam menggambar 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
g.drawString("JEDI",
getWidth()/2, getHeight()/2,
Graphics.TOP | Graphics.HCENTER);
getWidth()/2, getHeight()/2+font.getHeight(),
Graphics.TOP | Graphics.HCENTER);
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).
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
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);
Gambar 6: hasil dari penggunaan parameter yang sama untuk drawRect dan
fillRect
g.setColor(0, 0, 0);
g.drawRect(4,8,88,44);
g.drawRoundRect(108,8,88,44,18,18);
g.fillRect(4,58,88,44);
g.fillRoundRect(108,58,88,44,18,18);
g.setColor(255, 0, 0);
g.setColor(0, 0, 255);
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(|).
TOP | HCENTER
try {
Image image = Image.createImage("/jedi.png");
g.drawImage(image,
getWidth()/2, getHeight()/2,
Graphics.VCENTER | Graphics.HCENTER);
} catch (Exception e){}
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).
MyCanvas.java :
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
public MyCanvas() {
super(true);
screenWidth = getWidth();
screenHeight = getHeight();
currentX = screenWidth / 2;
currentY = screenHeight / 2;
delay = 20;
}
GameMidlet.java:
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
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.
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).
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
flushGraphics();
}
}
4.5.4 LayerManager
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.
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 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)
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.
Method-method dibawah ini digunakan untuk membuat dan membuka sebuah record
store:
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.
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).
Method addRecord akan membuat record yang baru didalam Record Store dan akan
mengembalikan record ID.
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.
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
Menghapus Record
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
membuat list dari keseluruhan record didalam record store. Anda harus
menggunakan Record Enumerator untuk mengetahui tiap record didalam sebuah list
store.
void closeRecordStore()
...
// Ini adalah String yang akan kita masukkan kedalam record
String newItem = "Record #" + recStore.getNextRecordID();
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.
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.
Contoh: 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.
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).
long getLastModified()
int getVersion()
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.
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.
Contoh – contoh selama ini membaca seluruh record dari sebuah store. Kita dapat
menggunakan sebuah filter untuk mendapatkan hanya record yang kita inginkan.
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.
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.
Bab 6
Jaringan
Pada bagian ini, kita akan belajar bagaimana menerapkan sebuah MIDlet yang
mempunyai kemampuan untuk koneksi kedalam jaringan.
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.
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.
<html>
<head>
<title>Test Page</title>
</head>
<body>
<h1 align="center">Test Page</h1>
</body>
</html>
<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
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.
import javax.microedition.io.*;
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;
}
...
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.
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");
...
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.
import javax.microedition.io.*;
try {
connection = (HttpsConnection) Connector.open("https://www.sun.com/");
int code = connection.getResponseCode();
...
} catch (CertificateException ce){
switch (ce.getReason()){
case CertificateException.EXPIRED:
...
}
}
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);
os.write("GET / HTTP/1.0\n\n".getBytes());
int c = 0;
while((c = is.read()) != -1) {
// memproses data yang diterima
...
}
iStream.close();
oStream.close();
conn.close();
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");
client.setSocketOption(DELAY, 0);
is.close();
os.close();
client.close();
server.close();
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()));
}
}
}
catch (IOException ioe) {}
catch (Exception e) {}
...
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.
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
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.
Sebelum kita memasuki bahasan dasar fungsi kriptografi, kita pelajari terlebih
dahulu beberapa security services penting yang digunakan dalam sebuah aplikasi :
Confidentiality – Jika kita mengirimkan data sensitive melalui sebuah jaringan, kita
ingin memastikan bahwa hanya penerima yang dituju yang dapat membacanya.
Integrity – Kita ingin memastikan bahwa data yang kita terima tidak mengalami
pengubahan, penambahan ataupun pemisahan.
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.
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.
Encrypted
Message ENCODE ENCODE Message
Message
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.
Encrypted
Message ENCODE ENCODE Message
Message
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?
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.
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.
Signature Generation
Signature Verification
Sender's
Message Create Digest
Private
Key
Message
Encrypt
Decrypted
Message Digest
Encrypted
Message Digest
Decrypt
Sender's
Public
Key
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.
Sebuah user permission memiliki salah satu dari 3 mode interaksi berikut :
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.
harus diberi hak akses terhadap protection domain. Jika hak akses tidak diberikan,
maka proses instalasi akan dibatalkan.
MIDlet-Permissions: javax.microedition.io.Connector.http
MIDlet-Permissions-Opt: javax.wireless.messaging.sms.receive,
javax.wireless.messaging.sms.send
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.
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” :
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 :
/*
* DigestMidlet.java
*
*/
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.security.*;
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;
}
}
Sun Java Wireless Toolkit 2.3 menyediakan dukungan JSR 177 (atau SATSA) :
2. Pilih “New Project” kemudian tentukan nama project dan class MIDlet :
3. Pilih “JWTI” sebagai Target Platform. Tandai pilihan “Security and Trust Services
APIs (JSR 177) dan kilik “OK”.
(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.
/*
* 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.*;
};
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 {
7.5 Latihan
Bab 8
Web Services
8.1 Tujuan
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">
<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.
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.
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.
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.
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
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.
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”
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 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.
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.
− 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.
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.
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.
Untuk mendapatkan instance dari SAX Parser, pertama-tama kita harus mendapatkan
instance dari SAXParserFactory:
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);
import java.util.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
if (TASK_ELEMENT.equals(qName)) {
// Dapatkan id attribute dari sebuah task
String id = attributes.getValue(ID_ATTRIBUTE);
qNameStack.push(qName);
}
qNameStack.pop();
}
}
Kita akan membuat secara sederhana aplikasi mobile dan kita akan menamakannya
“arithmeticClient”.
Kemudian, kita akan menggunakan stub generator (Tools->Java Platform Manager ->
Wireless Toolkit -> Tools and Extensions -> Open Utilities -> Stub Generator):
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.
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.*;
System.out.println("Invoking operation...");
WebServiceClient client = new WebServiceClient();
Thread thread = new Thread(client);
thread.start();
Bab 9
Optimisasi
9.1 Tujuan
Setelah menyelesaikan bab ini, pelajar diharapkan menguasai :
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.
String StringBuffer
String a, b, c; String a, b, c;
... ...
String StringBuffer
message.append(b);
message.append("\n");
message.append("c=");
message.append(c);
message.append("\n");
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;
...
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.
Ketika memanggil suatu method, penerjemah akan mendorong semua parameter ke atas
tumpukan eksekusi. Melewatkan banyak parameter akan mempengaruhi kecepatan eksekusi
dan pemakaian Heap Memory.
Memanggil method menghabiskan Heap Memory dan waktu eksekusi. Lihat subbab
sebelumnya.
Untuk mempercepat awal permulaan aplikasi, tunda semua inisialisasi yang sangat besar
sampai mereka dibutuhkan. Jangan meletakkan inisialisasi dalam konstruktor MIDlet atau
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
Hal tersebut lebih cepat mengakses variabel lokal daripada mengakses variabel instance.
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” :
Ada sepuluh tingkat obfuscation, dari tanpa obfuscation sampai ke obfuscation yang paling
agresif.
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.
Ini akan tampak berlawanan untuk prinsip berorientasi object, tapi apakah Anda mengetahui
bahwa suatu class kosong yang sederhana seperti ini :
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.
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.5 Jaringan
9.5.1 Gunakan thread yang terpisah
Gunakan thread yang terpisah untuk jaringan Anda yang berfungsi untuk menghindari screen
lockups.
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.
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.
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.
Bab ini akan membahas bagaimana memulai penggunaan Mobile Media API (MMAPI)
dan Wireless Messaging API (WMA).
Memainkan atau merekam sebuah media ditangani oleh dua object : DataSource dan
Player.
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
Key Deskripsi
Key Deskripsi
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import java.io.*;
form.addCommand(exitCommand);
form.append(volumeGauge);
form.append(durationGauge);
form.append(toneGauge);
}
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import java.io.*;
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");
form.addCommand(playCommand);
form.addCommand(exitCommand);
form.append(volumeGauge);
}
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));
}
}
}
}
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.*;
}
}
}
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
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import javax.wireless.messaging.*;
public SMSMidlet() {
sendCommand = new Command("Send", Command.OK, 1);
exitCommand = new Command("Exit", Command.EXIT, 1);
/**
* 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();
}
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:
Kita harus mendaftarkan aplikasi Kita untuk menjadi sebuah Message Listener
sehingga AMS akan memperhatikan MIDlet Kita dari pesan yang masuk.
conn.setMessageListener(this);
}
}
Dalam method run() Kita, Kita telah siap untuk mendapatkan sebuah pesan :
// 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;
}
public SMSReceiverMidlet() {
exitCommand = new Command("Exit", Command.EXIT, 1);
startReceiver();
display.setCurrent(form);
}
}
}
conn.setMessageListener(this);
statusField.setText(
"waiting for message at port " + port);
}
} catch (Exception ex){
statusField.setText("Cannot open connection on port "
+ port + ":" + ex.getMessage());
}
// 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;
}
}
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.
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.
Dalam rangka untuk pemeliharaan baterai, bluetooth memiliki tiga low modus
operasi yang hemat energi:
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.
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.
Application
OBEX
Service
RFCOMM
Discovery
L2CAP
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.
Aplikasi RFCOMM
localDevice = LocalDevice.getLocalDevice();
localDevice.setDiscoverable(DiscoveryAgent.GIAC);
notifier = (StreamConnectionNotifier) Connector.open(URL);
Client pertama kali akan mencari device yang tersedia untuk service tersebut:
discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);
InfoServer.java:
import javax.bluetooth.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;
public InfoServer() {
isRunning = false;
Thread thread = new Thread(this);
thread.start();
}
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) {
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.*;
public InfoClient() {
try {
discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);
} catch (Exception e) {
System.out.println(e);
}
}
} catch (Exception e) {
System.out.println("Exception: " + e);
}
}
System.out.println(BluetoothMidlet.read(conn));
break;
case SERVICE_SEARCH_ERROR:
System.out.println("SERVICE_SEARCH_ERROR\n");
break;
case SERVICE_SEARCH_TERMINATED:
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;
}
}
BluetoothMidlet.java:
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import javax.bluetooth.*;
import java.io.*;
Display display;
private InfoClient chatClient;
private InfoServer chatServer;
public BluetoothMidlet() {
menu.addCommand(exitCmd);
menu.addCommand(okCmd);
menu.setCommandListener(this);
}
switch (menu.getSelectedIndex()) {
case 0: chatServer = new InfoServer(); break;
case 1: chatClient = new InfoClient(); break;
default: break;
};
}
InputStream is = null;
byte[] dataBytes = null;
int len;
try {
is = conn.openInputStream();
len = is.read();
dataBytes = new byte[len];
len = 0;
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.
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:
Location Provider
Security
Tabel Loc01 terdiri dari nama-nama permission dan method yang dilindungi oleh
permission tersebut.
Landmarks
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.
Location Listener
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.
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.
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”.
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;
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);
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);
}
}
} catch (LocationException e) {
status.setText("Exception:" + e.getMessage());
} catch (InterruptedException e) {
status.setText("Timeout: " + e.getMessage());
}
}
}
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.
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.
Bab 11
Topik-topik Tambahan
11.1 Tujuan
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.
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.
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.io.*;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Date;
public TimerMidlet() {
exitCommand = new Command("Exit", Command.EXIT, 1);
textField = new StringItem("Counter", "");
int counter = 0;
TimerMidlet midlet;
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.
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:
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:
Pilih bagian "Signing" dan beri tAnda "Sign Distribution" untuk mendaftarkan aplikasi
MIDlet:
Pilih bagian "Running" dan pilih "Execute through OTA (Over the Air Provisioning)". Hal
ini merupakan proses instalasi dan eksekusi aplikasi pada device.
Langkah selanjutnya adalah menjalankan aplikasi MIDlet. Pastikan build berjalan dan
tidak ada error ketika melakukan instalasi device (via OTA provisioning).
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":
AMS akan menerima koneksi yang datang dan menanyakan konfirmasi selanjutnya
kepada user:
Ini adalah aplikasi MIDlet, dijalankan melalui Push Registry (melalui pesan SMS masuk):
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".
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.io.*;
import java.util.Timer;
import java.util.TimerTask;
import javax.microedition.io.*;
public PushMidlet() {
exitCommand = new Command("Exit", Command.EXIT, 1);
textField = new StringItem("Status", "");
connections = PushRegistry.listConnections(true);
display = Display.getDisplay(this);
form.setCommandListener(this);
display.setCurrent(form);
}
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.