Library dan Modifikasi Aplikasi Mobile dengan Web
A. Library pada Aplikasi Mobile
Modul library berguna dalam membangun aplikasi yang ada dalam variasi APK versi gratis dan versi i berbayar, sehingga membutuhkan komponen inti yang sama dalam kedua versi. Di samping itu modul library juga berguna membangun beberapa aplikasi yang menggunakan beberapa komponen yang sama, misalnya aktivitas, layanan, atau layout Ul. Namun demikian, dapat memindah file yang ingin digunakan kembali ke dalam modul library kemudian menambahkan library sebagai dependensi untuk setiap modul aplikasi
1. Konsep Penggunaan Library dalam Aplikasi Perangkat Bergerak
Dengan menyediakan open development platform, Android menawarkan kepada para pengembang untuk membuat aplikasi-aplikasi yang inovatif, yang mana pe- ngembang memiliki akses penuh ke framework API yang digunakan oleh aplikasi inti. Selain itu juga bebas dalam mengoptimalkan penggunaan hardware, mengakses informasi lokasi, menjalankan layanan sendiri, mengatur alarm, dan berbagai fungsi- fungsi lainnya. Untuk libraries yang dapat digunakan oleh komponen-komponen dalam sistem, Android menyediakan satu set C/C++ libraries sebagai bagian dari Android application framework sebagai berikut.
a. RxJava dan RxAndroid
Jika ingin menerapkan reactive programming pada project aplikasi android, maka RxJava dan RxAndroid adalah pilihan yang tepat.
b. GSON
GSON adalah library dari Google untuk meng-convert JSON menjadi java object dan java object menjadi JSON.
c. Retrofit
Retrofit adalah library untuk meng-handle REST API dan termasuk salah satu library yang sangat populer di kalangan android developer. Beberapa faktor penyebab populernya retrofit di antaranya sebagai berikut.
1) Konsep annotation akan membuat codingan kita lebih rapih dan enak dipandang.
2) Retrofit merupakan library yang simpel untuk meng-organize API calls.
3) Retrofit men-support RxJava.
4) Retrofit bisa memakai OkHttp sebagai Http client-nya.
5) Retrofit men-support penggunaan GSON dan Jackson.
d. Realm
Realm adalah mobile database yang powerful. Realm merupakan object-oriented database sehingga tidak menggunakan query SQL layaknya SQLite, dan ini me- rupakan salah satu keunggulannya.
e. Glide
Salah satu kelebihan pada glide adalah pada disk caching-nya. Glide merupakan image loading library yang mendukung menampilkan video stills, image, dan animated gif.
f. LeakCanary
Sebagai developer mobile, seorang programmer harus memperhatikan pengguna- an memory, meskipun ada kalanya our messy code menyebabkan memory leak se- hingga mengakibatkan out of memory error. Guna mendeteksi memory leak yang terdapat pada aplikasi dan meminimalisirnya, kita dapat menggunakan LeakCanary.
g. ButterKnife
ButterKnife adalah salah satu library yang dikembangkan oleh Jake Wharton yang berguna untuk membantu proses pengembangan aplikasi android, terutama dalam hal mem-binding view dengan layout pada aplikasi. Biasanya menggunakan View pada resource id di layout, menggunakan findViewById(R.id.view). Namun dengan menggunakan library ButterKnife kita hanya perlu meng-inject view ter- sebut, sehingga fungsi library ButterKnife digunakan untuk mencegah terjadinya pengulangan baris code (boilerpate), dan baris code menjadi lebih sedikit serta mudah dibaca.
1) Cara Menambahkan dan Menggunakan Library ButterKnife Library Android bernama ButterKnife dapat membantu dan mempersingkat inisialisasi komponen yang ada di layout.xml. Selain mempermudah inisialisasi komponen, jika menggunakan library maka kodin pun akan lebih simpel dan mudah dibaca. Langkah-langkah dalam menambahkan library ButterKnife di- awali dengan membuka gradle app module project lalu tambahkan kode berikut.
compile 'com.jakewharton:butterknife:8.5.1'
annotation Processor 'com.jakewharton:butterknife-compiler:8.5.1'
Selanjutnya melakukan sync project hingga proses selesai dikerjakan.
2) Cara Menggunakan Library ButterKnife
Dua metode ButterKnife yang sering digunakan adalah @BindView dan @ OnClick. Misalnya pada layout MainActivity.xml terdapat komponen edittext dengan id etNama dan komponen button dengan id btnTmbSimpan. Maka penggunaan ButterKnife di MainActivity adalah sebagai berikut.
@BindView(R.id.etNama) EditText etNama;
@BindView(R.id.btnTmbSimpan) Button btnTmbSimpan;
Lalu di dalam method onCreate tambahkan kode Butterknife.bind(this); sedang- kan untuk listener onclick button bisa di dalam onCreate dengan methode btnTmbSimpan.setOnClickListener atau memanfaatkan anotasi yang sudah disediakan oleh Butterknife.
@OnClick(R.id.btnTmbSimpan)
void simpan(){
// lakukan sesuatu
}
2. Prosedur Penggunaan Library dalam Aplikasi Perangkat Bergerak
Kelebihan mobile application terletak pada kemudahan dan kepraktisan dalam penggunaannya. Di samping itu, aplikasi mobile tidak membutuhkan koneksi internet sesudah diunduh, sehingga hal tersebut sangat menguntungkan bagi user yang berada di daerah yang tidak terkoneksi dengan internet. Meskipun user berada di daerah yang terkoneksi dengan internet, belum tentu koneksi internet berjalan dengan lancar. Kelebihan ini tentu menjadi nilai lebih yang besar untuk mobile application. Oleh sebab itu, terhubungnya aplikasi dengan banyak fitur membuat user lebih nyaman dalam menjalankan aplikasi mobile. User bisa langsung terhubung dengan fitur gadget seperti kamera, speaker, dan fitur lainnya.
Guna membuat aplikasi sederhana dengan menggunakan Google map me- merlukan Android Developer Tools (ADT) dan koneksi internet. Hal ini bisa diawali dengan membuat project melalui File → New Android Project atau menggunakan ikon New yang ada pada taskbar Eclipse dengan menggunakan setting default dari SDK. Pada saat project telah aktif, dilanjutkan dengan mem- buka file AndroidManifest.xml. Beberapa perubahan harus dilakukan pada bagian ini antara lain sebagai berikut.
a. Menambahkan Permission
Tujuan utamanya adalah memberikan aplikasi izin untuk mengakses beberapa fitur dari sistem Android. Beberapa hal yang berhubungan dengan permission adalah sebagai berikut.
1) android.permission.INTERNET yang digunakan untuk mengakses internet ketika melakukan download API Google Maps.
2)android.permission.ACCESS_NETWORK_STATE yang digunakan untuk melakukan check ketersediaan koneksi internet.
3)android.permission.WRITE_EXTERNAL_STORAGE yang digunakan untuk menyimpan cache pada memory.
4)android.permission.ACCESS_COARSE_LOCATION yang digunakan untuk melakukan akses lokasi melalui WIFI yang sedang digunakan.
5)android.permission.ACCESS_FINE_LOCATION yang digunakan untuk melakukan deteksi lokasi secara terperinci.
b. Melakukan Spesifikasi OpenGL.
Hal yang perlu dipahami adalah beberapa device tidak mampu menggunakan Google Play Service pada saat tidak compatible dengan OpenGL. Implementasinya dilakukan dengan menambahkan perintah sebagai berikut.
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
c. Menambahkan Meta Data
Meta data yang ditambahkan berasal dari Google Playstore dan Google maps dalam bentuk key. Dalam hal ini bisa menambahkan tag meta data dalam Application Tree. Diawali dengan menambahkan meta data Google play service dilanjutkan dengan meta data dari API Google Maps yang berisi API_KEY yang dapat melakukan generate. Langkah-langkah dalam mengubah AndroidManifest.xml adalah sebagai berikut.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.elfarqy.androidmaps"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission STORAGE" /> android:name="android.permission.WRITE_EXTERNAL_
<uses-permission android:name="android.permission.ACCESS_NETWORK_ STATE" />
<uses-permission LOCATION" /> android:name="android.permission.ACCESS_COARSE_
<uses-permission android:name="android.permission.ACCESS_FINE_ LOCATION" />
<uses-permission android:name="com.elfarqy.androidmaps.permission. MAPS_RECEIVE" />
<uses-permission android:name="com.Google.android.providers.gsf. permission.READ_GSERVICES" />
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.elfarqy.androidmaps.MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.Google.android.gms.version"
android:value="@integer/Google_play_services_version"/
<meta-data
android:name="com.Google.android.maps.v2.API_KEY"
android:value="AlzaSyCCOsnRs6BuQpHgKgDTlafvIwjopSuurto" />
</application>
</manifest>
d. Menambahkan Library Google Play Service
Untuk membuat aplikasi dengan API Google Maps akan membutuhkan Google Play Service sebagai library dalam project. Aplikasi ini bisa dibuka melalui Android SDK Manager lewat Eclipse ataupun pada directory tempat instalasinya. Arahkan pada pilihan menu EXTRAS, pilih Google Play Services. Jika melakukan upgrade ADT versi terbaru maka tampak 2 tipe Google play services, yaitu Google Play Service for Froyo dan Google Play Services. Google Play services For Froyo bisa di-install jika aplikasi yang dibangun ditujukan untuk froyo, sedang Google Play Service digunakan untuk Android versi Ginger Bread ke atas. Setelah itu dilanjutkan dengan menambah ke dalam project yang diawali dengan meng-import library Google Play services yang telah diinstall sebelumnya. Pilih pada menu File → Import → Existing Android Code Into Workspace, pilih direktori ADT → SDK → extras Google Google_play_services →libproject→ Google-play-services-lib. Klik kanan pada project yang telah dibuat sebelumnya dengan memilih properties → Android. Klik Add pada tab group library untuk menambahkan project tersebut sebagai Library.
e. Mendapatkan API KEY
API Key merupakan kode unik yang digunakan untuk mengakses aplikasi dari penyedia API. Untuk mendapatkan API terlebih dahulu harus memiliki akun Google. Langkah-langkah untuk mendapatkan API Google adalah sebagai berikut.
1) Akses Laman Google API Console Jika sudah memiliki project sebelumnya maka akan ditampilkan list beberapa project yang sudah dibuat sebelumnya atau dilanjutkan pada laman baru dengan cara klik menu APIs & auth > APIs sehingga akan ditampilkan pilihan API yang bisa digunakan. Misalnya menggunakan "Google Maps Android API v2", untuk mengaktifkan ub ubah status dari OFF menjadi ON.
2) Setelah selesai, akses menu Credentials yang berada di bawah menu APIs. Pada bagian ini akan membuat API key dengan cara klik pada Create New Key → Android Key. Kotak dialog akan dimunculkan untuk menempatkan fingerprints dari project yang dibuat.
Penggunaan fitur Eclipse (ADT) lebih memudahkan untuk mendapatkannya. Akses menu Window→ Preferences → Android Build. Selanjutnya lakukan copy paste SHA1 pada window ke dialog. Secara otomatis API key akan ditampilkan.
f. Menampilkan Peta
Guna menampilkan peta sederhana dalam aplikasi yang dibangun dengan membuat sebuah layout sederhana yang diletakkan pada folder res dalam project. Misalkan saja activity_main.xml, dengan mengubah xml layout menjadi sebagai berikut.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/ android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin"
android:padding Top="@dimen/activity_vertical_margin"
tools:context="com.elfarqy.androidmaps.MainActivity$PlaceholderFragment
">
<fragment
android:id="@+id/map"
android:name="com.Google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
Jika berhasil maka map akan berhasil ditampilkan pada aplikasi yang dibangun sebagai berikut.
B. Memodifikasi Aplikasi Mobile Menggunakan Library
Di masa sekarang, pengembangan aplikasi untuk perangkat komputasi sedang berkembang. Apalagi dengan kemajuan teknologi yang makin pesat, di antaranya perkembangan teknologi mobile dan perangkat smartphone. Karena perkembangan teknologi tersebut berpengaruh pada banyaknya developer yang mengembangkan aplikasi-aplikasi baru. Aplikasi-aplikasi itu tidak hanya ditujukan untuk perangkat desktop tetapi juga perangkat mobile. Pemrograman aplikasi bergerak tidak banyak berbeda dengan pemrograman konvensional pada PC. Dalam pemrograman aplikasi bergerak berbagai aspek teknis perangkat lebih menonjol karena memiliki banyak keterbatasan dibandingkan komputer konvensional atau PC. Aspek karakteristik dari perangkat bergerak sering memengaruhi arsitektur dan implementasi dari aplikasi tersebut. Beberapa alasan memodifikasi Android di antaranya untuk me- lakukan test, membuat aplikasi bisa berjalan lagi, dan untuk mencurangi game. Untuk pentesting, modifikasi yang sering perlu dilakukan adalah mematikan certificate pinning, mematikan root checking, dan menambahkan tracing untuk melihat logika aplikasi lebih jelas.
1. Konsep Konektivitas antara Aplikasi Web dengan Aplikasi Perangkat Bergerak
Aplikasi berbasis mobile ini sedikit berbeda dengan aplikasi web. Aplikasi berbasis mobile umumnya ditujukan untuk perangkat mobile seperti smartphone. Karena bentuk smartphone yang lebih kecil daripada desktop, otomatis tampilan pada aplikasi mobile disesuaikan dengan kebutuhan dengan user smartphone. Karena itu, pengembangan aplikasinya juga berbeda. Pada dasarnya jenis aplikasi perangkat bergerak dikategorikan menjadi empat, yaitu aplikasi yang 100% gratis, aplikasi gratis dengan tayangan iklan di dalamnya. Aplikasi gratis dengan pembelian fitur di dalamnya, dan aplikasi berbayar yang memang harus dibeli sebelum menggunakannya.
Aplikasi berbasis mobile sendiri terbagi menjadi aplikasi berbasis mobile web dan native apps.
a. Aplikasi Berbasis Mobile Web
Aplikasi berbasis mobile web umumnya adalah tampilan aplikasi web dalam bentuk mobile. Untuk menggunakan aplikasi ini, user dapat mengakses web browser di perangkat smartphone. Sebelum era mobile populer, banyak situs yang tampil di perangkat mobile akan tampil seperti halnya tampilan web di desktop. Di masa sekarang, sudah banyak aplikasi berbasis web yang bisa menyesuaikan sendiri tampilan web tergantung perangkat yang digunakan. Hal ini biasa disebut sebagai tampilan situs mobile friendly.
b. Native Apps
Native apps ini biasanya didistribusikan di toko aplikasi semacam Google Play untuk Android atau Apple Store untuk iOS. Native apps adalah istilah untuk aplikasi mobile yang fungsinya sedikit mirip dengan aplikasi desktop yaitu user perlu meng- instal terlebih dulu aplikasi tersebut sebelum menggunakannya, Guna menggunakan aplikasi ini, ada proses persetujuan penggunaan aplikasi. Misalnya memperbolehkan aplikasi untuk mengakses fungsi tertentu di smartphone. Bahkan ada aplikasi yang meminta izin untuk memperbolehkan akses membaca data kontak telepon dan identitas perangkat (device id). Saat ini, native apps memang sedang naik daun. Hal ini didasarkan karena penggunaan native apps lebih mudah dan aksesnya lebih cepat meskipun kadang-kadang membuat smartphone user penuh dengan banyak aplikasi. Ada juga yang beranggapan pengembangan aplikasi berbasis Android atau iOS lebih unggul dibandingkan aplikasi berbasis web.
XPosed adalah sebuah framework open
source yang memungkinkan kita membuat modul untuk memodifikasi sistem dan apli- kasi Android yang ditulis menggunakan Java. Dari sudut pandang programming, framework menarik karena menambahkan dan menginter- sepsi kode pada aplikasi closed source Android, sedikit mirip Aspect Oriented Programming. Prosedur pendekatan XPosed framework yang lebih dinamik adalah Frida dalam memanipu- lasi berbagai hal secara dinamis menggunakan JavaScript, termasuk juga mengganti beberapa kode native. Frida bisa dijalankan pada HP yang sudah di-root, dengan ini signature APK yang tidak berubah. Kelemahan Frida dibandingkan XPosed adalah perubahan yang dilakukannya tidak permanen. Jika ingin menyebarkan modi- fikasi tanpa menyertakan aplikasi asli karena masalah hak cipta maka XPosed bisa digunakan dengan baik, bahkan sangat cocok jika ingin membuat perubahan semi permanen. Ketika terdapat sistem operasi yang baru, biasanya XPosed dan Frida tidak langsung bisa dipakai jika ada perubahan mendasar di sistem operasi, sehingga tetap perlu tahu cara modifikasi manual. XPosed bekerja dengan memodifi- kasi runtime Android (Dalvik/Art) sehingga untuk memanggil kode custom di awal/ akhir sebuah method apa pun. Untuk memakai XPosed, yang harus dilakukan adalah meng-install recovery alternatif (CWM, TWRP, dan sebagainya) serta meng-install framework-nya. Di samping itu juga perlu meng-install XPosed installer yang akan me-manage modul mana saja yang aktif.
Supaya bisa mengintersepsi dengan mengembalikan agar is Valid License selalu menjadi TRUE dilakukan dengan cara memodifikasinya. Dalam method checkRoot, untuk melakukan pemeriksaan, device di-root oleh user dan cara memeriksanya meng gunakan XML berisi daftar command dan package yang harus diperiksa bisa mengganti parameter input XML menjadi XML kosong. Kode-kode yang digunakan untuk mem- patch agar isValidLicense selalu mengembalikan true adalah sebagai berikut.
import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_LoadPackage. LoadPackageParam;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; IXposedHookLoadPackage {
public class JoeHackXposed implements private void hackLicense(final LoadPackageParam Ipparam) {
findAndHookMethod("es.thoriq.examples.LicenseChecker", Ipparam. classLoader,
"isValidLicense",
String.class,
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable (
param.setResult(true);
}
});
}
public void handleLoadPackage(final LoadPackageParam Ipparam) throws Throwable { XposedBridge.log("Loaded app: " + Ipparam.packageName); if (lpparam.packageName.equals("es.thoriq.examples")) { hackLicense(Ipparam);
}
}
}
Jika ingin mengubah detail sebuah method dengan Xposed dengan cara menulis ulang method itu, dan di beforeHookedMethod memberitahu XPosed framework agar tidak
memanggil method aslinya. Kebanyakan modul di repository XPosed berguna mengatasi masalah spesifik yang dimiliki oleh user. Sebagai programmer, modifikasi ini bisa dilakukan meskipun tidak memiliki source code aplikasinya. Bagian tersulit adalah mencari tahu bagian yang perlu di-hook untuk mengimplementasikan fungsionalitas tertentu. Modifikasi dengan XPosed framework melengkapi hack android yang lain. Rooting aplikasi tidak cukup untuk mengubah internal program. Modifikasi dan compile ROM sendiri bisa mengubah hal-hal yang di luar kemampuan XPosed tetapi tidak bisa mengubah aplikasi. Modifikasi aplikasi dengan cara patching manual bisa dilakukan.
2. Prosedur Koneksi antara Aplikasi Web dengan Aplikasi Perangkat Bergerak
Konsep dasar koneksi HP android dengan PC/Laptop menggunakan aplikasi smartcam. Smartcam adalah aplikasi yang dapat membantu dalam memanfaatkan kamera ponsel pintar dengan desktop. Cara koneksinya hanya membutuhkan konek- si WIFI/konektivitas bluetooth pada desktop dan menggunakan aplikasi SmartCam. Pada langkah pertama yang dilakukan adalah meng-install Smartcam untuk android pada ponsel android dan kemudian Install Smartcam untuk PC/komputer. Setelah semua instalasi dengan benar, selanjutnya dihubungkan ponsel dengan PC melalui jaringan WIFI atau bluetooth.
Pengetahuan tentang API sangat dibutuhkan ketika developer aplikasi menemui hambatan dan problem yang menyebabkan aplikasi tidak berjalan sebagaimana mestinya. Mengembangkan sebuah aplikasi berbasis android membutuhkan dasar pengetahuan tentang API dan basic OOP (native Java). Di dalam project android yang dibuat menggunakan Eclipse terdapat sebuah file bernama AndroidManifest. xml. File memiliki fungsi layaknya gudang informasi bagi aplikasi android itu sendiri. Informasi di dalam Manifest tersebut memiliki beberapa kegunaan di antaranya memberi akses permission untuk fitur pada aplikasi, menginformasikan set SDK yang digunakan dalam aplikasi, merubah kode versi aplikasi saat melakukan update aplikasi, inisialisasi dukungan layar perangkat, menerjemahkan string atau label ke dalam aplikasi yang diperlukan seperti string icon launcher/app name, dan lain-lain. Pada intinya, konfigurasi AndroidManifest sangat dibutuhkan sebagai penggambaran dalam paket aplikasi Android.
a. Perubahan Kode Versi Aplikasi
Di dalam file AndroidManifest, terdapat beberapa baris string yang menunjukkan informasi versi dari kode aplikasi yang dibuat. Beberapa kode versi di dalam AndroidManifest adalah sebagai berikut.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.my.application"
android:versionCode="2"
android:versionName="2.0" >
String android:version Code menunjukkan kode versi aplikasi untuk mendefinisi- kan penggantian kode yang dilakukan oleh developer (pengembang). Dan android: versionName adalah string versi yang akan ditampilkan pada user aplikasi. Jadi per- bedaan mendasar dari kedua string tersebut terletak pada objek tujuan, di mana versionCode untuk pengembang dan versionName untuk ditampilkan kepada user. Hal yang perlu diperhatikan pada string di atas adalah merubah versionCode dan versionName dalam melakukan update aplikasi di Google Play. Jika tidak mengganti versi-versi tersebut, Google Play tidak akan menerima versi terbaru dari aplikasi yang akan diupload.
b. Set Versi SDK
Elemen/string ini merupakan representasi dari versi SDK yang dipakai untuk membuild aplikasi android. Contoh kode versi SDK yang terletak di dalam string <uses-sdk /> adalah sebagai berikut.
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="15" />
Eclipse akan membaca string manifest di atas bahwa aplikasi yang dibuat minimal memiliki target SDK versi 4 hingga versi 15 yang akan berguna pada saat developer ingin menambahkan sebuah fitur-fitur tertentu yang telah didukung versi SDK tersebut. Penggunaan minimal dan maksimal target memiliki keuntungan di sisi user yang masih menggunakan perangkat Android versi lama. SDK versi terkecil memungkinkan mendukung semua perangkat.
c. Set Permission
Jika aplikasi yang diinginkan dapat menyokong fitur native tertentu device Android, dapat dilakukan dengan men-setting pengaturan permission pada AndroidManifest secara benar. Bentuk string permission yang dapat di-setting adalah sebagai berikut.
<uses-permission android:name="android.permission. VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
Perintah <uses-permission /> bermanfaat saat aplikasi yang dikembangkan membutuhkan fitur asli perangkat Android. Misalnya dengan memasukkan per- mission untuk vibrasi perangkat, dukungan internet, dan recording audio. Permission tersebut mutlak dimasukkan dalam file AndroidManifest agar aplikasi berjalan sesuai perancangan.
d. Set Dukungan Layar
File AndroidManifest bisa juga melakukan pengaturan dukungan mode layar dan ukuran layar aplikasi. Bentuk setting untuk besar ukuran layar yang menggunakan elemen <supports-screens/> adalah sebagai berikut.
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:reSizeable="true"
android:anyDensity="true"
/>
Kode di atas memperbolehkan aplikasi berjalan pada perangkat android yang memililiki layar kecil (small) hingga besar (large). Sedangkan android:reSizeable bernilai "true" berfungsi agar aplikasi dapat menyesuaikan pada semua kondisi besar/kecilnya layar perangkat. Sedangkan string android:anyDensity memiliki fungsi yang bermanfaat pada saat aplikasi berjalan di berbagai layar dengan resolusi tinggi maupun rendah.
Codingan game tetris tahap ke -4 modifikasi:
<!doctype html>
<html>
<head>
<title>Basic Julia Tetris HTML Game</title>
<meta charset="UTF-8">
<style>
html, body {
height: 100%;
margin: 0;
}
body {
background: rgb(182, 7, 226);
display: flex;
align-items: center;
justify-content: center;
}
canvas {
border: 1px solid rgb(0, 0, 0);
}
</style>
</head>
<body>
<canvas width="320" height="635" id="game">
</canvas>
<script>
// https://tetris.fandom.com/wiki/Tetris_Guideline
// get a random integer between the range of [min,max]
// @see https://stackoverflow.com/a/1527820/2124254
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// generate a new tetromino sequence
// @see https://tetris.fandom.com/wiki/Random_Generator
function generateSequence() {
const sequence = ['I', 'J', 'L', 'O', 'C', 'T', 'U'];
while (sequence.length) {
const rand = getRandomInt(0, sequence.length - 1);
const name = sequence.splice(rand, 1)[0];
tetrominoSequence.push(name);
}
}
// get the next tetromino in the sequence
function getNextTetromino() {
if (tetrominoSequence.length === 0) {
generateSequence();
}
const name = tetrominoSequence.pop();
const matrix = tetrominos[name];
// I and O start centered, all others start in left-middle
const col = playfield[0].length / 2 - Math.ceil(matrix[0].length / 2);
// I starts on row 21 (-1), all others start on row 22 (-2)
const row = name === 'I' ? -1 : -2;
return {
name: name, // name of the piece (L, O, etc.)
matrix: matrix, // the current rotation matrix
row: row, // current row (starts offscreen)
col: col // current col
};
}
// rotate an NxN matrix 90deg
// @see https://codereview.stackexchange.com/a/186834
function rotate(matrix) {
const N = matrix.length - 1;
const result = matrix.map((row, i) =>
row.map((val, j) => matrix[N - j][i])
);
return result;
}
// check to see if the new matrix/row/col is valid
function isValidMove(matrix, cellRow, cellCol) {
for (let row = 0; row < matrix.length; row++) {
for (let col = 0; col < matrix[row].length; col++) {
if (matrix[row][col] && (
// outside the game bounds
cellCol + col < 0 ||
cellCol + col >= playfield[0].length ||
cellRow + row >= playfield.length ||
// collides with another piece
playfield[cellRow + row][cellCol + col])
) {
return false;
}
}
}
return true;
}
// place the tetromino on the playfield
function placeTetromino() {
for (let row = 0; row < tetromino.matrix.length; row++) {
for (let col = 0; col < tetromino.matrix[row].length; col++) {
if (tetromino.matrix[row][col]) {
// game over if piece has any part offscreen
if (tetromino.row + row < 0) {
return showGameOver();
}
playfield[tetromino.row + row][tetromino.col + col] = tetromino.name;
}
}
}
// check for line clears starting from the bottom and working our way up
for (let row = playfield.length - 1; row >= 0; ) {
if (playfield[row].every(cell => !!cell)) {
// drop every row above this one
for (let r = row; r >= 0; r--) {
for (let c = 0; c < playfield[r].length; c++) {
playfield[r][c] = playfield[r-1][c];
}
}
}
else {
row--;
}
}
tetromino = getNextTetromino();
}
// show the game over screen
function showGameover() {
cancelAnimationFrame(rAF);
gameOver = true;
context.fillStyle = 'black';
context.globalAlpha = 0.75;
context.fillRect(0, canvas.height / 2 - 30, canvas.width, 60);
context.globalAlpha = 1;
context.fillStyle = 'white';
context.font = '36px monospace';
context.textAlign = 'center';
context.textBaseline = 'middle';
context.fillText('GAME OVER!', canvas.width / 2, canvas.height / 2);
}
const canvas = document.getElementById('game');
const context = canvas.getContext('2d');
const grid = 32;
const tetrominoSequence = [];
// keep track of what is in every cell of the game using a 2d array
// tetris playfield is 10x20, with a few rows offscreen
const playfield = [];
// populate the empty state
for (let row = -2; row < 20; row++) {
playfield[row] = [];
for (let col = 0; col < 10; col++) {
playfield[row][col] = 0;
}
}
// how to draw each tetromino
// @see https://tetris.fandom.com/wiki/SRS
const tetrominos = {
'I': [
[0,0,0,0],
[1,1,1,1],
[0,0,0,0],
[0,0,0,0]
],
'J': [
[1,0,0],
[1,1,1],
[0,0,0],
],
'L': [
[0,0,1],
[1,1,1],
[0,0,0],
],
'O': [
[1,1],
[1,1],
],
's': [
[0,1,1],
[1,1,0],
[0,0,0],
],
'Z': [
[1,1,0],
[0,1,1],
[0,0,0],
],
'T': [
[0,1,0],
[1,1,1],
[0,0,0],
]
};
// color of each tetromino
const colors = {
'I': 'maroon',
'O': 'maroon',
'T': 'maroon',
'S': 'maroon',
'Z': 'maroon',
'J': 'maroon',
'L': 'maroon'
};
let count = 0;
let tetromino = getNextTetromino();
let rAF = null; // keep track of the animation frame so we can cancel it
let gameOver = false;
// game loop
function loop() {
rAF = requestAnimationFrame(loop);
context.clearRect(0,0,canvas.width,canvas.height);
// draw the playfield
for (let row = 0; row < 20; row++) {
for (let col = 0; col < 10; col++) {
if (playfield[row][col]) {
const name = playfield[row][col];
context.fillStyle = colors[name];
// drawing 1 px smaller than the grid creates a grid effect
context.fillRect(col * grid, row * grid, grid-1, grid-1);
}
}
}
// draw the active tetromino
if (tetromino) {
// tetromino falls every 35 frames
if (++count > 35) {
tetromino.row++;
count = 0;
// place piece if it runs into anything
if (!isValidMove(tetromino.matrix, tetromino.row, tetromino.col)) {
tetromino.row--;
placeTetromino();
}
}
context.fillStyle = colors[tetromino.name];
for (let row = 0; row < tetromino.matrix.length; row++) {
for (let col = 0; col < tetromino.matrix[row].length; col++) {
if (tetromino.matrix[row][col]) {
// drawing 1 px smaller than the grid creates a grid effect
context.fillRect((tetromino.col + col) * grid, (tetromino.row + row) * grid, grid-1, grid-1);
}
}
}
}
}
// listen to keyboard events to move the active tetromino
document.addEventListener('keydown', function(e) {
if (gameOver) return;
// left and right arrow keys (move)
if (e.which === 37 || e.which === 39) {
const col = e.which === 37
?tetromino.col - 1
: tetromino.col + 1;
if (isValidMove(tetromino.matrix, tetromino.row, col)) {
tetromino.col = col;
}
}
// up arrow key (rotate)
if (e.which === 38) {
const matrix = rotate(tetromino.matrix);
if (isValidMove(matrix, tetromino.row, tetromino.col)) {
tetromino.matrix = matrix;
}
}
// down arrow key (drop)
if(e.which === 40) {
const row = tetromino.row + 1;
if (!isValidMove(tetromino.matrix, row, tetromino.col)) {
tetromino.row = row - 1;
placeTetromino();
return;
}
tetromino.row = row;
}
});
// start the game
rAF = requestAnimationFrame(loop);
</script>
</body>
</html>
Tidak ada komentar:
Posting Komentar