Showing posts with label android. Show all posts
Showing posts with label android. Show all posts

Wednesday, 1 August 2012

Random thought July


Busy these days :(
  1. [Android] Apparently when you clean your Android project on Eclipse, it will generate new id on R.java. And there's this small probability it will make your app works on some OS and crash on the other. Fuck!
  2. Akhir-akhir ini sering kagum dengan beberapa pekerjaan where my code "just work. Dimana kode-nya kadang-kadang bekerja lebih bagus dari perkiraan. This is not exactly a good thing tapi kejutannya cukup menyenangkan :).
  3. Punya ide startup yang cukup solid. Moga-moga ada waktu untuk nyicil.
  4. Dapat ide aplikasi mobile. Sangat simple. Moga-moga tidak di-banned oleh Google Play nanti :(
  5. [Facebook] Hackathon di Facebook! Niatnya gak mau ikut lagi. Tapi gara-gara Hendri >.<

Sunday, 15 July 2012

Perbandingan Performa SharedPreferences dan SQLite

Yup bersama saya lagi bermain-main dengan Android! Kali ini saya ingin membahas tentang SharedPreferences dan SQLite sebagai pilihan untuk menyimpan data pada Android.

Pembuat aplikasi Android pasti suatu saat akan menemui suatu permasalahan tentang penyimpanan data. Bagaimana cara menyimpan data? Bagaimana data itu disimpan? Dimana harus disimpan? Jawaban dari pertanyaan itu dapat dijawab dengan membaca tutorial Android disini. Menurut saya tutorial itu sudah cukup memberikan pengantar yang cukup untuk memulai merambah dunia simpan-menyimpan di Android (sehubungan dengan simpan-menyimpan, saya jadi ingat dengan "simpanan" saya. Tapi itu untuk lain cerita).

Apabila si pembuat aplikasi ini sudah mulai advance, ia akan mulai bingung antara "apakah saya harus menggunakan SharedPreferences atau kah saya harus menggunakan SQLite?" dengan asumsi kita tidak memperdulikan penyimpanan di storage (internal maupun eksternal). Karena sudah dipastikan penyimpanan di storage itu lambat (akan disinggung sedikit nanti mengapa penyimpanan di storage itu lambat). Seperti kita ketahui, SharedPreferences hanya dapat menyimpan data dalam bentuk key-value pair sehingga mudah dimodifikasi. Sedangkan SQLite hanya dapat diubah dengan membuat query SQL.
Ini ngomongin apa sih? Saya maunya pake Hadoop saja >:)
Di sebuah post di StackOverflow sudah dibahas tipe penyimpanan mana yang harus anda gunakan pada suatu kondisi tertentu. Inti dari post itu adalah: Gunakan SharedPreferences bila data-nya kecil dan bermacam-macam. Gunakan SQLite bila data-nya besar, terstruktur dan sedikit macam-nya. Contoh data yang ingin anda simpan di SharedPreferences adalah: "opsi apakah user ingin mendapatkan notifikasi", "opsi apakah user hanya ingin mengunduh data dari internet ketika terhubung dengan wireless", "berapa kali notifikasi harus dilakukan tiap hari" dan berbagai macam data yang kecil yang lain. Contoh data yang ingin anda simpan di SQLite adalah: "daftar manga yang di bookmark oleh user", "contact list", "kumpulan teman-teman yang baru saja saya miss-call" dan berbagai macam data yang terstruktur yang lain.

Namun anda yang suka bermain Javascript atau fanatik dengan JSON akan berargumen: "Bitch please! Saya bisa mengubah data saya, misalnya Manga, menjadi sebuah JSON lalu saya simpan ke SharedPreferences. Manga saya nanti punya sebuah key, misal URL darimana Manga tersebut diambil, untuk mendapatkan Manga yang saya mau dari SharedPreferences dengan mudah. Solusi ini mudah dibuat dan sangat mudah dikembangkan! Semua-nya jadi rata ke SharedPreferences! Screw SQL!"
JSON can save the world! JSON can even kill and fight Freddy!
Baik saya sangat setuju bahwa dengan SharedPreferences pasti perlu digunakan (untuk setting, konstanta-konstanta kecil, menyimpan versi terakhir yang digunakan, menyimpan waktu update dari internet terakhir kali, dan lain sebagainya). Sedangkan seperti yang telah disebutkan diatas, SQLite tidak sepenuhnya dibutuhkan dengan alasan struktur yang kita butuhkan dapat dikompres dengan mudah kedalam JSON lalu kita simpan sebagai String biasa. Tapi bagaimana kalau kita tinjau dari segi performa?

Pertama SharedPreference akan makin lambat seiring dengan banyak-nya data yang disimpan dalam SharedPreference tersebut. Lambat disini hanya terjadi saat aplikasi mulai dijalankan. Misal anda menyimpan segala sesuatu di SharedPreference SPMangaMobile. Maka suatu saat apabila terlalu banyak Manga yang anda simpan di SPMangaMobile ini, untuk bisa me-load opsi-opsi trivial seperti "kapan terakhir kali aplikasi ini di-update" akan memakan waktu sangat lama. Samsung Galaxy Mini saya merasakan 5 detik startup hanya untuk memulai aplikasi karena saya menggunakan cara ini.

"Kalau begitu, pisahkan saja SharedPreference yang bersifat struktural, seperti Manga, ke SPManga. Sedangkan untuk yang lain, masukkan ke SPMangaMobile." In a way, solusi ini cukup benar sampai anda punya 1 MegaByte data. Me-load 300kB data saja membutuhkan waktu hingga hampir 1200 ms! Dan ini dilakukan di Android yang tidak sembarangan: Galaxy Tab 8.9" dengan processor Tegra 2 dual core 1 GHz! Bayangkan berapa lama waktu yang dibutuhkan di Galaxy Mini?


Tiap kali pengguna memulai aplikasi, pengguna harus menunggu selama 516 ms untuk  mempersiapkan SharedPreferences. Another 720 ms untuk mendapatkan data yang dibutuhkan.
Selebihnya program menghabiskan rata-rata 720ms untuk mengolah data hingga dapat digunakan.
Wow. Pengguna Android sekarang pasti akan mulai membanting HP-nya apabila HP-nya berhenti me-respon dalam waktu lebih dari 3 detik (ya, pengguna Android se-tidak-sabaran itu). "Nexus gw gak mungkin selambat itu! Yang lambat itu cuma BB!" Baik, coba tunjukkan waktu yang dibutuhkan bila menggunakan SQLite! Segera komandan!
3685 ms adalah waktu yang dibutuhkan untuk mem-backup database ke eksternal storage (karena itu saya bilang menyimpan di storage itu lambat). Hal ini hanya dilakukan sekali saja  setiap kali anda mengubah definisi database (misal menambah kolom pada suatu tabel). Jika anda pintar, database hanya perlu dibuat sekali saja :)
Loh tapi ternyata performa-nya tidak berkembang sama sekali! Penipuan ini namanya!
Ya, bisa anda lihat bahwa performa menggunakan SQLite tidak berbeda jauh dari menggunakan SharedPreference. Lalu apa gunanya donk kita menggunakan SQLite? Tunggu dulu! Mari kita simak lagi.

Berbeda dengan apabila kita menggunakan JSON terstruktur pada SharedPreferences, pada SQLite kita bisa mengambil data-data yang kita perlukan saja (dengan menspesifikasikan query yang tepat). Misalnya untuk kasus ini, saya hanya ingin mengambil judul, url, dan rating dari suatu Manga. Saya tidak peduli dengan deskripsi, genre, maupun data-data yang lain. Tentu hal ini bisa meningkatkan performa! Tapi sebesar apa? Mari kita lihat!
Karena sudah di-backup sebelumnya, kali ini kita hanya melihat waktu yang dihabiskan oleh aplikasi untuk menyiapkan data yang siap ditampilkan.
Yes! Akhirnya peningkatan performa! Kali ini aplikasi dapat me-load data dalam waktu hanya 231ms saja! Tiga kali lebih cepat dibandingkan sebelumnya!

Dari percobaan ini saya kembali ke kesimpulan yang sebelumnya telah dibuat oleh suatu post di  StackOverflow : Gunakan SharedPreferences bila data-nya kecil dan bermacam-macam. Gunakan SQLite bila data-nya besar, terstruktur dan sedikit macam-nya.


Sekian dari saya. Seperti biasa, komentar dan tanggapan sangat diterima :)

Monday, 19 March 2012

Expanding Your Market!

Hai hai, saya ingin nge-share tentang pengalamanku mengeksplorasi market di internet, especially Android.

Alkisah dua orang pria yang kurang kerjaan sebut saja Gogo dan Rhesa (bukan homo-an, masih jomblo, dan masih mencari cewek cantik) memutuskan untuk merealisasikan aplikasi yang awalnya digunakan untuk tugas kuliah. Aplikasi ini disebut Sound Scheduler. In a nut shell, aplikasi ini adalah sebuah aplikasi untuk mencocokkan volume HP dengan jadwal anda. Let's say anda sedang kuliah, tentunya sudah memiliki jadwal yang jelas. Bayangkan apabila anda ditengah kelas dimana dosen anda ada adalah seorang Avatime, Avatar of Time, The Time Bender, dimana dia bisa membuat 5 menit terasa seperti 2 tahun. Anda mungkin tergoda untuk main game ditengah kelas itu (mohon jangan dipraktekkan karena bahaya nilai E). Dan saat anda mulai main game, tiba-tiba BGM anda menyala dengan sangat keras. Tet Tot Tet Tot Tet Tot. That awkward moment when you play game in the class and you forgot to turn the volume off. Aplikasi ini bertujuan untuk mencegah awkward moment tersebut. Bagaimana caranya? Ya, dengan menjadwalkannnya terlebih dahulu.

Promotion banner. Tidak terlalu menarik akibat skill Photoshop saya yang pas-pasan

Jadwal! Hal yang paling penting dalam aplikasi ini. Perhatikan bahwa UI aplikasi ini mirip sekali dengan Alarm bawaan Android yang diproduksi oleh Samsung. 

Fitur. Sangat sederhana. Kalau dihitung-hitung aplikasi ini dibuat dalam 5 hari efektif dan 1 minggu testing.

Kami sudah mencoba me-research market di Android. Kita melihat aplikasi-aplikasi sejenis tidak memiliki UI yang memuaskan. Beberapa aplikasi tidak memiliki fitur ini dan beberapa aplikasi sudah kelewat kompleks. Aplikasi yang bagus harganya 2-5 USD (yang sudah kita coba dengan teknik pirating a'la Bang Google).

Dengan bekal sedikit market research dan UI dan fungsional yang straightforward, kami membuat dua model bisnis. Model pertama adalah free + ads + trial. Model ini saya anggap cukup annoying dimana anda diperbolehkan menggunakan aplikasi ini secara gratis apabila anda bersedia menerima ads yang annoying (by LeadBolt), atau anda bisa menggunakan aplikasi ini secara cuma-cuma selama 2 minggu tanpa ads. Model kedua adalah paid apps. Sebenarnya target dari dari pembuatan model ini adalah pembelajaran. Target saya adalah "Given enough customer, what's the best model to produce most income?" Bagaimana saya punya kepercayaan pada enough customer? Karena saya percaya dengan mengiklankan Sound Scheduler di Manga Mobile saya akan mendapatkan customer yang cukup. Tampaknya dugaan saya salah besar!

Hari pertama download count pada Manga Mobile berjumlah 55, dan dihari-hari selanjutnya bertambah dengan grafik yang lumayan bagus menurut saya. Download count pada Ace Core lebih mengerikan lagi, 500 pada hari pertama (Nokia memang memiliki user base yang fearsome). Namun untuk Sound Scheduler, grafik ini sangatlah tidak memuaskan. Satu download pada hari pertama, 4 download pada hari kedua dan tidak bertambah pada hari-hari selanjutnya. Terang saja hal ini sangat mengecewakan saya dan Rhesa.

Perkembangan download Manga Mobile dari masa ke masa

Saya melakukan research pribadi disela-sela waktu break ngoding dan tidur. Dulu, Android Market memiliki kategori Just In, dimana semua aplikasi yang baru di-publish di Android Market akan masuk kedalam kategori ini. Tentu saja keberadaan kategori ini mengunutngkan developer-developer cupu dan hina macam saya. Dan Manga Mobile dipublish saat kategori Just In ini masih ada. Namun kategori ini dihilangkan karena sering di-abuse oleh spammer yang memasukkan aplikasi sembarangan secara sembarangan.

Setelah mendapat fakta ini saya mulai mencari-cari: Bagaimana cara memasarkan aplikasi Android baru saya padahal saya tidak punya nama dan tidak punya uang? Apalagi saya adalah orang yang tergolong anti-sosial, not the marketing type banget lah (based on true story). Ilmu Googling dan Bing saya lakukan. Ada beberapa cara yang saya ingat:
  1. Ads: umum sekali, dengan iklan maka banyak chance dapat customer. Saya skip bagian ini karena perlu membayar.
  2. Masukkan ke review website: ada beberapa website seperti AppBrain dan AppTap yang sering dikunjungi oleh pengguna Android untuk mendapatkan aplikasi-aplikasi Android yang terbaik versi mereka. Saya menganalogikan hal ini dengan award pada dunia permusikan yang jumlahnya banyak (Grammy, MTV, dll, dsb). Bila kita di-review oleh website ini, maka kita dapat muncul di Home Page dari website mereka. Tentunya hal ini akan meningkatkan visibilitas kita terhadap customer. Saya mencoba cara ini dan sampai saat ini aplikasi saya belum mendapat review dari mereka.
  3. Post di forum: Forum-forum pengguna Android itu banyak jumlahnya. Banyak diantara pengguna forum itu juga adalah seorang developer. Mereka kadang memasarkan barang-barang mereka disana dengan membuka sebuah thread dan memberikan review singkat mengenai aplikasi mereka. Anggap sajalah kita berjualan aplikasi di Kaskus. Saya tidak menggunakan cara ini tanpa alasan khusus. Mungkin karena saya malas berkomunikai dengan manusia jadi saya tidak menggunakan cara ini.
  4. Masukkan ke banyak market: Cara ini adalah cara yang akan saya tekankan pada artikel ini. Ada banyak Android Market selain yang dimiliki oleh Google seperti Amazon Appstore, AppBrain, SlideMe, Motorola Shop4Apps, AppChina, Mobango dan lain sebagainya yang bertujuan untuk membuat market alternatif untuk developer yang mungkin merasa Android Market itu tidak memuaskan. Ada juga Android Market buatan Indonesia seperti Indosat iStore yang saya rasa belum cukup berkembang dan seolah dibuat setengah hati. Cara ini saya lakukan cukup intensif.
Sebenarnya saya sudah ditawari oleh beberapa website ini untuk memasarkan aplikasi saya di market mereka. Jadi saya memulai perjalanan saya dengan mengecek email-email terdahulu. Yang paling pertama dan paling menarik adalah AppChina.

AppChina adalah Android Market untuk China. Konon katanya Android Market milik Google tidak bisa dipasarkan di China sehingga perlu ada pihak ketiga yang memasarkan disana. Untuk memasarkan di website ini, saya tidak perlu berusaha. Ada seorang penggemar aplikasi Manga Mobile dan memutuskan untuk memasarkan aplikasi saya disana.



Apa yang menarik dari aplikasi ini. Pertama, bukan saya yang mengupload aplikasi ini di AppChina. Kedua, orang yang meng-upload aplikasi ini mentranslasikan deskripsi Manga Mobile dan menambahkan screenshot yang berbeda dari yang saya gunakan dari apa yang saya upload di Android Market. Deskripsi hasil translasi ini pun sedikit berbeda dengan apa yang saya gunakan di Android Market. Hal ini menurut saya sungguh mengejutkan, menarik dan exhilarating. Sayangnya saya tidak berhasil menghubungi AppChina untuk mencoba mengupload Sound Scheduler disana.

Kedua saya mencoba Motorola. Singkat saja, tempat ini cukup menyulitkan. Saya bahkan tidak pernah menemukan dimana itu Shop4Apps. Saya juga diwajibkan menggunakan advertisement yang disarankan Motorola dengan nama Amobee. Aplikasi yang saya berhasil upload pun tidak memiliki download satupun.

Lalu saya melirik market Android yang besar yang lain: Amazon AppStore. Disini hal yang menarik hati saya adalah fitur "New Free Apps of The Day." Dengan fitur ini developer bisa berharap untuk dapat mengupload aplikasinya dan dipromosikan oleh Amazon di home pagenya. Namun ternyata "bermain" di Amazon AppStore tidak semudah itu. Amazon AppStore memiliki sistem review yang lambat. Aplikasi Manga Mobile saya belum lulus review sampai saat ini. Sound Scheduler saya yang hanya terdiri dari dua form di-review selama satu minggu. Dan Sound Scheduler di Amazon AppStore sampai saat ini belum di-download.

Amazon AppStore dan fitur "New Apps of the Day"-nya


Kembali saya mengeksplorasi market-market yang ada. Kali ini saya tertarik dengan Mobango yang juga pernah menawari saya untuk mempromosikan aplikasi saya disana via email. Saya coba mendaftar disana dan cukup senang dengan hasilnya. Proses review aplikasi di Mobango hanya memakan waktu kurang dari 12 jam dan aplikasi anda bisa langsung live di Mobango. Mobango memiliki fitur yang memamerkan aplikasi yang baru saja dipublish disana, namun tidak eksplisit. Dan anehnya download count Manga Mobile dan Sound Scheduler bisa mencapai 9 masing-masing dalam waktu 3 hari. Saya yang sudah pesimis dengan segala macam market yang ada di internet kontan cukup senang dengan hasil ini.

Tampilan Mobango yang tidak terlalu menarik

Manga Mobile dan Sound Scheduler di Mobango

Terakhir ini, tepatnya kemarin, saya menguji satu market yang entah saya dapatkan dari mana. Nama market ini adalah SlideMe. Pada home page-nya SlideMe, aplikasi-aplikasi baru langsung dipamerkan disana. Hal ini sangat menggoda saya dan saya langsung mencoba meng-upload aplikasi saya disana. Sesuai dugaan, hasilnya memuaskan. Aplikasi saya di-review dalam 3 jam dan dalam 1 hari sudah mendapat download count sebanyak 30 untuk Sound Scheduler dan 60 untuk Manga Mobile. Hal ini sangat menarik dimana saya tidak pernah mendengar tentang SlideMe sebelumnya padahal SlideMe memfasilitasi pemasaran yang cukup bagus.

Tampilan SlideMe yang lumayan bagus

Hasil Manga Mobile dan Sound Scheduler di SlideMe

To sum it up, review saya untuk Android Market yang ada diinternet saat ini:
  1. Google Android Market: wajib! Pusat dari aplikasi Android adalah disini. Anggap saja kalau aplikasi anda belum masuk sini itu belum afdol. Market ini tidak memiliki sistem review jadi bisa dibilang adalah market termudah untuk mengupload aplikasi.
  2. AppChina: kalau bisa Bahasa Cina (cincau, bakpau, cepek, gopek, nopek, bakso) go for it. Download count dari market ini lumayan. Tapi berharap saja ada orang baik hati yang mau menguploadkan aplikasi anda kesini.
  3. Shop4Apps. definitely NO. Selain proses review yang cukup lama (sekitar 3 hari), anda harus mengupload dalam 2 format (Inggris dan Cina) yang cukup merepotkan. Hasilnya pun belum saya lihat hingga detik ini.
  4. Amazon AppStore. NO. Banyak review jelek tentang Amazon AppStore dan saya telah membuktikan bahwa hal itu ada benarnya. Saya mungkin akan mengganti opini saya apabila aplikasi saya masuk dalam  "New Free Apps of The Day" namun sampai saat ini opini saya adalah: NO.
  5. Mobango: bagus. Karena sedikitnya aplikasi yang diupload disini, maka kemungkinan aplikasi anda untuk eksis disini cukup tinggi. Walau tidak memiliki fitur new application namun Mobango membuktikan bahwa ia cukup digunakan.
  6. SlideMe: definitely. Dengan jumlah aplikasi yang sedikit, sedikit sistem review untuk mencegah spam (sotoy) dan memamerkan new application, SlideMe mendapat bintang 5 dalam hati saya.
So, what do you think? Ada saran bagaimana bisa mem-boost visibility kita dan aplikasi kita dimata pengguna Android? Mohon sarannya master :)

Sunday, 4 March 2012

Manga Mobile Coding Series : Membajak mangareader.net part 2

Asyik bisa nulis lagi. Sebelumnya kita telah membahas logika dibalik teknik pembajakan Mangareader. Kali ini saya akan membahas secara teknis bagaimana implementasinya di Android.

Kembali saya ingatkan: untuk bisa mengerti dengan sepenuhnya apa yang dibahas di artikel ini, anda perlu mengenal beberapa hal yang tidak dibahas di artikel ini:
  1. DOM (Document Object Model)
  2. Manga :)
Android dapat mengunduh isi halaman HTML dengan mudah. Tetapi hasil unduhan ini adalah sebuah string panjang. Lalu bagaimana kita bisa mengeksekusi logika "temukan anak pertama dari tag ul"? Ada beberapa cara seperti berikut:
  1. Lakukan manipulasi string. Kita membuat asumsi bahwa ul ini pasti punya anak. Sehingga kita dapat mencari karakter "<" pertama yang mengawali sebuah tag HTML dan menandai karakter tersebut menjadi karakter pertama dari anak yang kita cari. Lalu kita tinggal mencari ">" yang sesuai dan menandai karakter tersebut menjadi karakter terakhir dari anak yang kita cari. Dari sini kita dapat menyalin karakter-karakter diantara karakter yang telah kita tandai tersebut dan jadilah mereka sebagai string anak pertama yang kita cari. Ada permasalahan dari sini? Banyak: sangat rentan bug dan sangat tidak fleksibel.
  2. Gunakan XML Parser.
  3. Gunakan 3rd party library untuk membuat DOM.
Saya akan membahas cara terakhir (yang kebetulan saya gunakan). Dan perlu diketahui, sebenarnya membuat DOM tidak perlu menggunakan 3rd party library karena sepertinya Android sudah memilikinya. Namun saya terlanjur menggunakan 3rd party library dan malas untuk menggantinya (maaf).

Perkenalkan Jsoup (halo Jsoup, saya Gogo), library pembuat DOM yang saya gunakan. Fitur-fitur yang bisa dilakukan oleh library ini silakan dilihat di website nya. Yang penting, si Jsoup ini menyediakan beberapa hal yang berguna untuk saya:
  1. kemampuan untuk membuat DOM
  2. kemampuan untuk memanipulasi dan mencari elemen dalam DOM
  3. kemampuan untuk mencari elemen spesifik berdasarkan tag, class, id, name, dan href atribut lainnya.
  4. kemampuan untuk mencari bapak dan anak dari suatu elemen.
Sebenarnya fungsi 2 hingga 4 adalah fitur yang wajib ada untuk sebuah library yang mengaku bisa membuat DOM, jadi fungsi utama library ini sebenarnya hanya 1.

Jadi tanpa banyak cakap, inilah kodenya:


public ArrayList downloadMangaList() {
    ArrayList mangaList = new ArrayList();
    String url = Utilities.MANGAREADER_URL + "/alphabetical";

    boolean gagal = true;
    int attempt = 0;

    while (gagal && attempt < Utilities.DOWNLOAD_ATTEMPT) {
        try {
            Log.i("Manga", "trying to connect to " + url);
            Document soup = Jsoup.connect(url).get();
            gagal = false;

            // lewat sini means berhasil konek
            Elements links = soup.select("ul[class=series_alpha]");

            for (Element link : links){
                Elements mangaLinks = link.getElementsByTag("a");
                for (Element manga : mangaLinks){
                    mangaList.add(new Manga(manga.text(), Utilities.MANGAREADER_URL + manga.attr("href")));
                }
            }

        } catch (IOException ex){
            Log.i("Manga", "" + ex.getMessage());
            ++attempt;
        }
    }

    return mangaList;
}



Kode diatas adalah contoh bagaimana saya mendapatkan kumpulan manga yang ada di Manga Reader. Yang pertama saya lakukan adalah mengunduh page www.mangareader.net/alphabetical dimana pada page itu, semua manga yang ada di Manga Reader dituliskan. Saya mengunduhnya menggunakan Jsoup.connect(url).get()agar HTML yang diunduh ini sudah terformat dengan baik oleh JSoup. Hal ini saya lakukan berkali-kali in case pengguna menggunakan koneksi yang abal-abal sehingga page HTML-nya jadi tidak terunduh.

Langkah kedua adalah pattern matching. Ya, dengan sedikit pengamatan kita dapat melihat bahwa page HTML yang dibuat oleh Manga Reader ini cukup ber-pola. Tiap manga selalu dibungkus dalam alphabet yang mengawalinya (Naruto berarti N). Dan tiap alphabet itu dibungkus dalam satu elemen HTML yaitu 
<ul> , dan selalu memiliki class=series_alpha. Gambar berikut mungkin bisa lebih menjelaskan.

      HTML dari www.mangareader.net/alphabetical
Dari sini kita tinggal mengambil semua elemen yang memiliki class=series_alpha, lalu mencari semua URL yang ada didalamnya. Cara ini tidak foolproof, tapi cukup untuk mendapatkan apa yang kita butuhkan.

That's it! Semudah itu kita "membajak" Manga Reader. Tinggal melakukan hal yang sama pada page-page yang lain dan kita dapat membuat software untuk pengunduh manga dengan mudah. Cara ini juga dapat diaplikasikan pada manga source lain seperti GoodManga, MangaHere, AnimeA dan lain-lain. Namun beberapa manga source seperti MangaStream dan Batoto sering mengganti pola menampilkan halamannya dan membuat mereka susah di-scrapping.

What do you think? Ada yang mau membantu saya membuat manga downloader dengan membuat pola-pola seperti ini?

Tuesday, 28 February 2012

Random Thought February



Random thought
  1. Mineral water cannot quench my thirst anymore. Only sweet tea can. I wonder if vampires feel the same way about blood.
  2. Mungkin jurus terbaik yang diperlukan programmer dan desainer adalah Kage Bunshin no Jutsu. So many ideas and no time/manpower.
  3. "For engineers, our deadline is the deadline time. For market, the deadline is the opportunity." - Nico
  4. Saya curiga bahwa orang-orang jenius adalah orang dari masa depan yang menggunakan mesin waktu untuk kembali dan memperbaiki masa lalunya yang suram.
  5. [Android] Misalnya mau bikin Button programmatically (ga pake XML). Kalau misalnya kita punya drawable dalam bentuk resource (contoh R.drawable.image), lebih baik langsung button.setBackgroundResource(R.drawable.image). Jangan ubah R.drawable.image jadi obyek Drawable dulu (drawable = context.getResources().getDrawable(R.drawable.image); button.setBackgroundDrawable(drawable)). Hal ini buruk kalau R.drawable.image mengandung animasi (contoh kalau bikin selector pake XML). Nanti animasinya ga jalan.
  6. [Android] Just realized that beside Log.v(verbose), Log.d(debug), Log.i(info), Log.w(warning) and Log.e(error), there's Log.wtf(What a Terrible Failure)
  7. [Game Dev] Tips bikin gerakan Seeking Missile. Pertama cari vektor antara misilnya dengan targetnya. Terus cari vektor satuannya. Habis itu kalikan vektor satuan dengan kecepatan maksimal misil.
  8. [Manga Mobile] Just finished multiple manga source for Manga Mobile. And there're so many bug reports. Emailed on top of that. So sorry everyone >.<
  9. [Manga Mobile] Comment by user: Jan 28, 2012 11:02:34 AM on version 1.952 "fucked up"
  10. Don't go too far ahead, or be ready to be alone there.
  11. When I hate something, I just feel like making the game of it. Setelah kuliah Agama Islam, I feel like making a game about God (like Black and White?). Setelah naik angkot yang ngetem 1 jam, I feel like making a game about Angkot (like Dinner Dash?). And I had countless idea for game about programming.
  12. Keraguan adalah puncak dari keyakinan - Imam Al-Ghazali.
  13. Rioux SVN for free and private SVN :)
  14. Hello World in GWT and App Engine! So excited! Tutorial  in Indonesian coming up :). Ini tutorial Inggris-nya yang lumayan bagus (dibandingkan yang Google punya)
Damn GWT, how am I supposed to learn from ur f****d up sample?


Sunday, 17 April 2011

Manga Mobile Coding Series : Membuat Main Menu

Yup, untuk sebagian besar aplikasi, pasti memerlukan Main Menu untuk melakukan navigasi mula-mula. Bisa dibilang Main Menu adalah bagian terpenting dari sebuah aplikasi. Karena itu, pada kesempatan kali ini kita akan membahas :
  1. Bagaimana memulai activity baru dari activity sebelumnya.
  2. Bagaimana membuat layout Main Menu
  3. Bagaimana membuat event listener. Pada kasus ini event listener pada button.
Melanjutkan dari pembuatan Splash Screen di sini, pertama kita buat dahulu layout Main Menu yang kita kehendaki. Berikut kode XML layout sederhana Main Menu yang saya beri nama main_menu.xml :

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

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dip"
    android:gravity="center"
    android:id="@+id/main_layout" 
    android:background="@drawable/main_menu">
    <LinearLayout 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/main_linear"    
        android:orientation="vertical"
        android:gravity="center_horizontal"
    >
        <Button 
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@+id/read_button"
            android:text="Read"    
            android:background="@drawable/bg_button"
            android:layout_margin="10dip"
            android:textColor="#ffffff"
        />
        <Button 
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@+id/favorite_button"
            android:text="My Favorites"    
            android:background="@drawable/bg_button"
            android:layout_margin="10dip"
            android:textColor="#ffffff"
        />
        <Button 
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@+id/setting_button"
            android:text="Setting"    
            android:background="@drawable/bg_button"
            android:layout_margin="10dip"
            android:textColor="#ffffff"
        />
    </LinearLayout>
        
</RelativeLayout>

Ada banyak cara membuat .xml baru, salah satunya adalah meng-copy .xml yang sudah ada, lalu me-rename dan mengganti kode didalamnya.

Disini ada beberapa atribut baru yang cukup baru. Pertama adalah android:gravity="center_horizontal". Atribut ini bertujuan untuk menengahkan tombol-tombol yang ada didalam LinearLayout. Sedangkan android:orientation="vertical" berguna untuk menjaga agar tombol yang satu dan yang lain disusun secara vertikal. Setelah itu, didalam LinearLayout kita buat beberapa tombol. Pada kode diatas saya mendefinisikan isi text (android:text), warna text (android:textColor), ID dari tiap button (android:id), background button (android:background) dan jarak antar satu button dengan button lain (android:layout_margin).

Sebagai referensi, saya menggunakan 2 gambar ini untuk background Main Menu dan background button.

main_menu.png

bg_button.png


Lalu kita buat sebuah Activity baru bernama MainMenuAct. Cara membuat Activity sama dengan saat kita membuat SplashScreenAct hanya saja ada beberapa perubahan kode :

package gogo.mobile.mm;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainMenuAct extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_menu);
        
        mRead = (Button)findViewById(R.id.read_button);
        mRead.setOnClickListener(new View.OnClickListener() {
            
            public void onClick(View v) {
                //startActivity(new Intent(MainMenuAct.this, SelectMangaAct.class));
            }
        });
        
    }
    
    private Button mRead;
}

Perhatikan bahwa pada kode diatas kita mendapatkan definisi button Read dan Favorite dari main_menu.xml yang telah kita definisikan sebelumnya (dan ini menjadi penyebab mengapa saya lebih suka memainkan layout lewat kode daripada menggunakan IDE). Pada kode diatas, kita juga telah membuat sebuah event listener untuk button Read yang nanti akan kita isi untuk melakukan navigasi.

Lalu kita harus membenarkan SplashScreenAct kita. Cukup ubah kode ini :

SplashScreenAct.this.finish();

menjadi :

SplashScreenAct.this.finish();
startActivity(new Intent(SplashScreenAct.this.getApplicationContext(), MainMenuAct.class));

Sampai tahap ini, kita telah berhasil membuat MainMenuAct yang akan dijalankan setelah Splash Screen selesai. Namun kode ini masih belum bisa berjalan dengan sempurna. Kita harus memberitahu Android bahwa MainMenuAct adalah bagian dari activity kita. Tambahkan pada AndroidManifest.xml

<activity android:name=".MainMenuAct" />

dimanapun dalam tag <application> setara dengan tag <activity> milik SplashScreenAct.

Jalankan aplikasi. Bila lancar, maka akan muncul seperti berikut :

Splash Screen

Dan 5 detik kemudian, muncullah MainMenuAct.

Sekarang mari kita buat Main Menu ini bisa melakukan navigasi. Buatlah sebuah Activity kosong bernama SelectMangaAct.

package gogo.mobile.mm;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class SelectMangaAct extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}

Lalu uncomment kode


//startActivity(new Intent(MainMenuAct.this, SelectMangaAct.class)


pada MainMenuAct. Tambahkan juga


<activity android:name=".SelectMangaAct" />


pada AndroidManifest.xml. Kira-kira isi tag <application> pada AndroidManifest.xml saat ini adalah :

<application android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar">
    <activity android:name=".SplashScreenAct" android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".MainMenuAct"/>
<activity android:name=".SelectMangaAct" />
</application>

Jalankan aplikasi, dan bila sukses bin lancar muncullah seperti berikut :
Splash Screen

5 detik kemudian muncul MainMenuAct. Pencet button Read

Yap, kita berhasil melakukan navigasi ke Activity lain.

Sekian kombo pembahasan Splash Screen dan Main Menu. Nantikan pembahasan selanjutnya yang (semoga) lebih seru. Kritik dan saran tentunya masih saya terima.

Saturday, 16 April 2011

Manga Mobile Coding Series : Membuat Splash Screen

Yup, akhirnya punya cukup waktu luang untuk menuliskan artikel ini. Pada artikel ini saya akan memaparkan beberapa hal tentang bagaimana cara membuat Splash Screen.

Bagi anda mau memulai membuat project dan melakukan setting emulator, anda bisa melakukannya disini.
Pada project kali ini, saya menggunakan konfigurasi berikut

  1. Project Name = MangaMobile
  2. Build Target Android 2.1 yang memiliki API version 7
  3. Application Name = MangaMobile
  4. Package Name = gogo.mobile.mm
  5. Tidak membuat Activity (checkbox Create Activity tidak dicentang)
  6. Min SDK Version = 7
Kurang lebih akan muncul tampilan seperti berikut di Project Explorer anda (bila anda tidak bisa menemukan Project Explorer, klik Window > Show View > Project Explorer) :


Pada tahap ini, anda telah berhasil membuat sebuah project yang tidak bisa dijalankan (karena tidak ada Activity yang bisa dijalankan). Sekarang buka src, dan pada package gogo.mobile.mm, klik kanan > New > Class. Akan muncul tampilan seperti berikut

Yang paling penting untuk dilakukan adalah mengisi nama kelas di Name dan mengosongkan Superclass. Lalu langsung saja klik Finish. Kelas yang kita buat ini tidak akan langsung menjadi sebuah Splash Screen.

Sekarang kita memerlukan gambar untuk Splash Screen. Saya sarankan resolusi gambar tersebut adalah 320x480 seperti ini :
Simpan gambar ini di folder res > drawable-mdpi > splash.png (nama file gambarnya terserah, tapi pastikan hanya terdiri dari huruf kecil dan garis bawah). Kembali ke Eclipse, klik kanan pada project anda (pada kasus ini : MangaMobile) lalu pilih Refresh. Bila gambar anda berhasil dimasukkan, file tersebut akan muncul di folder res > drawable-mdpi pada project dan muncul juga di gen > gogo.mobile.mm > R.java > R > drawable > splash sebagai sebuah pointer ke resource gambar splash.png.

Setelah memiliki gambar untuk splash dan Android Project telah mendeteksi gambar kita, kita perlu membuat layout. Lihat pada Project Explorer, folder res > layout > main.xml. Akan muncul tampilan seperti layar HP. Saya tidak terlalu suka berkutat ditampilan ini karena tidak terlalu fleksibel. Pada bagian bawah, klik main.xml. Akan muncul tampilan XML. Ganti isi XML menjadi seperti berikut

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

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dip"
    android:gravity="center"
    android:id="@+id/main_layout" 
    android:background="@drawable/splash">    
</RelativeLayout>

Pada baris pertama <?xml version="1.0" encoding="utf-8"?> digunakan untuk mendefinisikan tipe XML yang digunakan. Pada Splash Screen kita menggunakan layout RelativeLayout (layout akan dibahas di post lain). Layout ini akan memenuhi seluruh layar (karena android:layout_width  dan android:layout_height bernilai fill_parent yang artinya ia akan memenuhi seluruh parent-nya dimana parent-nya adalah layar HP itu sendiri). Yang paling penting disini adalah properti ID dan Background. Disini ID nya saya set dengan main_layout sementara Background nya saya isi dengan splash (sesuai dengan nama file yang kita masukkan di res > drawable-mdpi).

Terakhir, kita tinggal memasukkan kode yang diperlukan di SplashScreenAct.java. Tambahkan kode sedemikian menjadi seperti berikut :

package gogo.mobile.mm;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

public class SplashScreenAct extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Thread timer = new Thread() {
            @Override
            public void run() {
                long startTime = System.currentTimeMillis();
                // lakukan sesuatu pada saat memulai game
                
                long now = System.currentTimeMillis();
                if (now - startTime < 5000){
                    try {
                        sleep(5000 - (now - startTime));
                    } catch (InterruptedException iEx){
                        
                    }
                }
                
                SplashScreenAct.this.finish();
                //kita belum akan membuat activity baru disini setelah splash screen selesai
                //startActivity(new Intent(SplashScreenAct.this.getApplicationContext(), MainMenuActivity.class));
            }
        };
        
        timer.start();
    }
}

Hal yang perlu diperhatikan adalah, kelas ini sekarang meng extend Activity. Saya sarankan untuk melakukan segala sesuatu dengan Ctrl + Space. Sebagai contoh tulis Activi lalu pencet Ctrl + Space, lalu pilih Activity pada intellisense. Hal ini akan membuat Eclipse secara otomatis mengimport segala hal yang diperlukan untuk membuat Activity.

Pada Activity, kita harus selalu mengimplementasikan onCreate(Bundle savedInstanceState)(cara paling mudah adalah dengan menulis onCreate, lalu pencet Ctrl + Space, lalu pilih onCreate yang sesuai pada intellisense). Jangan lupa untuk menambahkan super.onCreate(savedInstanceState) karena tanpa sebaris kode tersebut Activity tidak akan bisa di-start. Yap, pada tahap ini kita sudah membuat sebuah Activity yang bisa dijalankan. Tapi bila kita mencoba menjalankan project ini, tentu akan terdapat error.

Lalu untuk membuat Activity ini menggunakan layout yang telah kita buat, kita harus menambahkan setContentView(R.layout.main) dimana main disini adalah nama layout yang kita buat (main.xml).

Berikutnya kita membuat Thread yang akan melakukan sesuatu selama 5000 millisecond. Dan setelah 5000 millisecond, Thread ini akan menutup SplashScreenAct dan akan membuat Activity baru. Namun pada tutorial ini pembuatan Activity baru tidak akan dibahas. Yap, Splash Screen sudah selesai dibuat.

Apakah program ini akan berjalan? Belum! Kita perlu memberitahukan Android bahwa aplikasi kita memiliki Activity bernama SplashScreenAct dan aplikasi kita dimulai dari sana. Pada Project Explorer klik pada AndroidManifest.xml. Dan lagi-lagi pencet AndroidManifest.xml pada bagian bawah jendela. Pada tag <application>, edit kodenya sehingga menjadi seperti berikut

<application android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar">
    <activity android:name=".SplashScreenAct" android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        </activity>    
</application>

Hal ini membuat Android mengetahui bahwa aplikasi kita dimulai dari SplashScreenAct yang bisa distart dari launcher (icon yang kita klik untuk memulai aplikasi).

Yap sekarang Splash Screen kita telah selesai. Silakan dicoba :

memulai emulator

ketika kita buka menu utama Android, kita dapat melihat aplikasi kita

Yes, that's our Splash Screen

Bila anda mengikuti tutorial ini hingga seri kedepan, maka tampilan ini akan muncul

Sunday, 3 April 2011

Manga Mobile Coding Series : Membuat Widget

Maap kalau seri nya mungkin agak ngacak. Tapi kebetulan saya lagi penasaran mau membuat Widget untuk Manga Mobile atas saran dari teman saya (tag : dieend).

Jadi anggap saja kita sudah mempunya Android Project di Eclipse dan sudah men-develop-nya sedemikian rupa sehingga sudah bisa digunakan (detail pembuatan project di Eclipse dan development-nya akan saya tulis dikemudian hari). Lalu kita ingin membuat sebuah widget, misalnya untuk kasus aplikasi Manga Mobile saya, saya ingin memberikan update manga terbaru. Pada contoh ini, saya hanya akan membuat sebuah tombol di widget saya, yang bila dipencet, akan langsung membuka aplikasi Manga Mobile.

Untuk membuat widget, kita memerluka 3 hal :

  1. AppWidgetProviderInfo : yaitu widget itu sendiri. Disini kita akan mendefinisikan layout widget, frekuensi melakukan update dan provider yang akan mengupdate widget.
  2. AppWidgetProvider : yaitu class yang meng-update isi widget.
  3. Layout dari widget itu sendiri.

Pertama, mari kita definisikan AppWidgetProviderInfo dalam bentuk xml. Saya menyimpan file ini di /res/xml/widget.xml

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

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="294dp"
    android:minHeight="72dp"
    android:updatePeriodMillis="1000"
    android:initialLayout="@layout/widget_layout"
    >
</appwidget-provider>

Penjelasan singkat : kita membuat widget menggunakan XML. Widget ini ukurannya paling kecil 294 x 72 dp (Density-Independent-Pixel). Widget ini akan mengupdate dirinya sendiri (dengan memanggil suatu method di provider yang akan kita definisikan nanti) setiap 1000 milliseconds. Tampilan widget ini juga akan dikonfigurasi oleh @layout/widget_layout (yang juga akan kita definisikan setelah ini).

Lalu kita membutuhkan WidgetProvider, yaitu class yang akan meng-update isi dari widget ini. Saya menamai kode dibawah ini = MangaMobileWidget.java

package gogo.mobile.mm;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;

public class MangaMobileWidget extends AppWidgetProvider {
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        final int widgetSize = appWidgetIds.length;
        
        for (int i = 0; i < widgetSize; ++i){
            Intent intent = new Intent(context, SplashScreenActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

            // Get remote layout
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
            views.setOnClickPendingIntent(R.id.widget_button, pendingIntent);

            // update widget
            appWidgetManager.updateAppWidget(appWidgetIds[i], views);
        }
    }
}

Method pada kode diatas akan dipanggil setiap beberapa millisecond (pada kasus ini 1000 milliseconds). Disini saya membuat Intent yang akan memanggil SplashScreenActivity yang sudah saya buat di aplikasi saya. Intent ini dikirim apabila suatu button dipencet. Button yang dimaksud sudah saya definisikan di @layout/widget_layout.

Lalu sekarang saatnya kita mendefinisikan layout dari widget itu sendiri. Layout ini saya simpan di /res/layout/widget_layout.xml

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="200dp"
    android:layout_height="160dp"
    android:padding="10dip"
    android:gravity="center"
    android:id="@+id/widget_layout" 
    android:background="@drawable/bg_button">
     <Button 
         android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/widget_button"
        android:text="Widget Button Test"
     />
 </LinearLayout>

Saya tidak akan membahas dengan detail tentang pembuatan layout disini. Disini intinya saya membuat sebuah  LinearLayout yang memiliki sebuah button didalamnya. Button ini memiliki ID (R.id.widget_button), sehingga bisa diakses oleh WidgetProvider yang telah saya buat.

Lalu, belum selesai sampai sini, kita harus mendefinisikan widget kita ke AndroidManifest.xml. Kode berikut saya letakkan antara tag  dan 

<receiver android:name=".MangaMobileWidget" >
    <intent-filter>
    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget" />
</receiver>


Disini kita mendefinisikan widget, dan mengatakan bahwa widget tersebut dikontrol oleh MangaMobileWidget sebagai WidgetProvider. Resource disini adalah AppWidgetInfo yang telah kita definisikan diatas.

Lalu jalankan emulator :


Home-nya emulator


Klik Menu dulu baru klik Add.



Klik Widgets



Ups, saya melihat icon saya


Yup itu dia widget nya. Coba di klik ah


Yep, Manga Mobile is ready.

Sekian dari saya, semoga bermanfaat. Masukan sangat diterima untuk seri koding selanjutnya