
Membuat Aplikasi Android Pencarian Kode POS
Tutorial membuat aplikasi android untuk mencari kode POS indonesia. Dulu saya sempat membuat aplikasi android tapi menggunakan javascript Framework7 + Cordova, nah sekarang saya akan share versi java dibuat di android studio.
Ok langsung saja berikut database kodeposnya yang sudah saya simpan di firebase secara publik jadi biasa digunakan oleh siapa saja. Endpoint:
- Daftar propinsi
https://kodepos-2d475.firebaseio.com/list_propinsi.json?print=pretty
- Daftar kota/kabupaten
https://kodepos-2d475.firebaseio.com/list_kotakab/{key propinsi}.json?print=pretty
- Daftar kecamatan, kelurahan & kodepos
https://kodepos-2d475.firebaseio.com/kota_kab/{key kota}.json?print=pretty
Pertama-tama kita buka android studionya trus create new project, lalu buat file2, class2 seperti digambar:
dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="margin_16dp">16dp</dimen>
</resources>activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
tools:context=".MainActivity">
<ListView
android:id="@+id/list_pos"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.constraint.ConstraintLayout>activity_propinsi.xml
masih sama dengan activity_main.xml
tools:context=".PropinsiActivity">
list_daerah.xml
untuk menampilkan daftar propinsi dan kota.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:padding="@dimen/margin_16dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/name"
android:freezesText="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="@style/TextAppearance.AppCompat.Subhead" />
</LinearLayout>activity_kota.xml
EditText untuk filter.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
tools:context="com.bachors.kodepos.KotaActivity">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<EditText android:id="@+id/filter"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="@dimen/margin_16dp"
android:hint="Filter" />
<ListView
android:id="@+id/list_pos"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>list_pos.xml
untuk menampilkan data kecamatan, kelurahan dan kodepos
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:padding="@dimen/margin_16dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/kecamatan"
android:freezesText="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/TextAppearance.AppCompat.Subhead" />
<TextView
android:id="@+id/kodepos"
android:freezesText="true"
style="@style/TextAppearance.AppCompat.Subhead"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/colorPrimary"
android:gravity="end" />
</LinearLayout>
<TextView
android:id="@+id/kelurahan"
android:freezesText="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>- Karena data jsonnya cukup sederhana dan berbentuk flat, keynya juga bersifat dinamis
{ "p1" : "Bali", "p10" : "Jawa Tengah", "p11" : "Jawa Timur", "p12" : "Kalimantan Barat", "p13" : "Kalimantan Selatan", "p14" : "Kalimantan Tengah", "p15" : "Kalimantan Timur", "p16" : "Kalimantan Utara", "p17" : "Kepulauan Riau", ... }
jadi saya menggunakan cara ini yang saya temukan di tutorial http://www.androidhive.info/2012/01/android-json-parsing-tutorial/, tidak menggunakan librari seperti retrofit, volley atau yg lainnya.HttpHandler.java
:
public class HttpHandler {
private static final String TAG = HttpHandler.class.getSimpleName();
public HttpHandler() {
}
public String makeServiceCall(String reqUrl) {
String response = null;
try {
URL url = new URL(reqUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
// read the response
InputStream in = new BufferedInputStream(conn.getInputStream());
response = convertStreamToString(in);
} catch (MalformedURLException e) {
Log.e(TAG, "MalformedURLException: " + e.getMessage());
} catch (ProtocolException e) {
Log.e(TAG, "ProtocolException: " + e.getMessage());
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.getMessage());
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
return response;
}
private String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
try {
while ((line = reader.readLine()) != null) {
sb.append(line).append('\n');
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
} MainActivity.java
mengambil data json daftar propinsi lalu menampilkannya di listview list_daerah.xml menggunakan SimpleAdapter.public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
private String TAG = MainActivity.class.getSimpleName();
private ProgressDialog pDialog;
private ListView lv;
// URL to get propinsi list JSON
final static String url = "https://kodepos-2d475.firebaseio.com/list_propinsi.json";
ArrayList<HashMap<String, String>> posList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// menampung data propinsi
posList = new ArrayList<>();
// listview untuk menampilkan daftar propinsi
lv = (ListView) findViewById(R.id.list_pos);
lv.setOnItemClickListener(this);
// Get JSON data
new GetPost().execute();
}
// Async task class to get json by making HTTP call
private class GetPost extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
@Override
protected Void doInBackground(Void... arg0) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url);
Log.e(TAG, "Response from url: " + jsonStr);
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Parser flat object
Iterator<String> iter = jsonObj.keys();
while (iter.hasNext()) {
String key = iter.next();
try {
Object value = jsonObj.get(key);
String nama = value.toString();
// tmp hash map for single GetPost
HashMap<String, String> pos = new HashMap<>();
// adding each child node to HashMap key => value
pos.put("name", nama);
pos.put("idp", key);
// adding pos to pos list
posList.add(pos);
} catch (JSONException e) {
// Something went wrong!
}
}
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),
"Data tidak ada.",
Toast.LENGTH_LONG)
.show();
}
});
}
} else {
Log.e(TAG, "Couldn't get json from server.");
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),
"Terjadi kesalahan coba lain waktu.",
Toast.LENGTH_LONG)
.show();
}
});
}
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
// Sorting a-z
Collections.sort(posList, new Comparator<HashMap< String,String >>() {
@Override
public int compare(HashMap<String, String> lhs,
HashMap<String, String> rhs) {
return lhs.get("name").compareTo(rhs.get("name"));
}
});
// Updating parsed JSON data into ListView
ListAdapter adapter = new SimpleAdapter(
MainActivity.this, posList,
R.layout.list_daerah, new String[]{"name"}, new int[]{R.id.name});
lv.setAdapter(adapter);
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// mengambil idp & name dari list yang kita click
String idp = posList.get(position).get("idp");
String name = posList.get(position).get("name");
// mengirim parameter idp & name ke PropinsiActivity
Intent intent = new Intent(MainActivity.this, PropinsiActivity.class);
intent.putExtra("idp", posList.get(position).get("idp"));
intent.putExtra("name", posList.get(position).get("name"));
startActivity(intent);
}
}PropinsiActivity.java
sama seperti MainActivity.java tinggal merubah url dan activitynya....
private static String url;
...
protected void onCreate(Bundle savedInstanceState) {
...
Bundle b = getIntent().getExtras();
// get id propinsi
url = "https://kodepos-2d475.firebaseio.com/list_kotakab/" + b.getString("idp") + ".json";
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ActionBar actionBar = getSupportActionBar();
// set toolbar title
actionBar.setTitle(b.getString("name"));
...
}
...
@Override
public void onBackPressed() {
super.onBackPressed();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}KotaActivity.java
berbeda dengan MainActivity.java dan PropinsiActivity.java data jsonnya berbentuk array dan ditampilkan di list_kota.xml dan ada proses untuk memfilter listview berdasarkan nama kecamatan atau kelurahan karena datanya banyak.public class KotaActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
...
// array untuk menampung data filter
ArrayList<HashMap<String, String>> tmpList;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
...
Bundle b = getIntent().getExtras();
// get id propinsi
url = "https://kodepos-2d475.firebaseio.com/kota_kab/" + b.getString("idp") + ".json";
...
// menampung data kota
posList = new ArrayList<>();
...
// filter berdasarkan nama kecamatan atau kelurahan
final EditText filter = (EditText) findViewById(R.id.filter);
filter.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String title = filter.getText().toString().trim().toLowerCase();
if(!TextUtils.isEmpty(title)) {
// clear tmpList
tmpList = new ArrayList<>();
for (int i = 0; i < posList.size(); i++) {
String kecamatan = posList.get(i).get("kecamatan").toLowerCase();
String kelurahan = posList.get(i).get("kelurahan").toLowerCase();
if (kecamatan.contains(title) || kelurahan.contains(title)) {
tmpList.add(posList.get(i));
}
}
// menampilkan hasil filter
ListAdapter adapter = new SimpleAdapter(
KotaActivity.this, tmpList,
R.layout.list_pos, new String[]{"kecamatan", "kelurahan", "kodepos"}, new int[]{R.id.kecamatan, R.id.kelurahan, R.id.kodepos});
lv.setAdapter(adapter);
} else {
// menampilkan original data
ListAdapter adapter = new SimpleAdapter(
KotaActivity.this, posList,
R.layout.list_pos, new String[]{"kecamatan", "kelurahan", "kodepos"}, new int[]{R.id.kecamatan, R.id.kelurahan, R.id.kodepos});
lv.setAdapter(adapter);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
}
// Async task class to get json by making HTTP call
private class GetPost extends AsyncTask<Void, Void, Void> {
...
@Override
protected Void doInBackground(Void... arg0) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url);
Log.e(TAG, "Response from url: " + jsonStr);
if (jsonStr != null) {
try {
JSONArray data = new JSONArray(jsonStr);
// Parser object array
for (int i = 0; i < data.length(); i++) {
JSONObject c = data.getJSONObject(i);
String kecamatan = c.getString("kecamatan");
String kelurahan = c.getString("kelurahan");
String kodepos = c.getString("kodepos");
HashMap<String, String> pos = new HashMap<>();
// adding each child node to HashMap key => value
pos.put("kecamatan", kecamatan);
pos.put("kelurahan", kelurahan);
pos.put("kodepos", kodepos);
// adding contact to contact list
posList.add(pos);
}
} catch (final JSONException e) {
...
}
} else {
...
}
return null;
}
@Override
protected void onPostExecute(Void result) {
...
// Updating parsed JSON data into ListView
ListAdapter adapter = new SimpleAdapter(
KotaActivity.this, posList,
R.layout.list_pos, new String[]{"kecamatan", "kelurahan", "kodepos"}, new int[]{R.id.kecamatan, R.id.kelurahan, R.id.kodepos});
lv.setAdapter(adapter);
}
}
...
}- dan terakhir
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.bachors.kodepos">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".PropinsiActivity"
android:configChanges="orientation|keyboardHidden|screenSize" />
<activity
android:name=".KotaActivity"
android:configChanges="orientation|keyboardHidden|screenSize" />
</application>
</manifest>
Atau sobat bisa mendownload source codenya disini. Selamat mencoba..