Menghubungkan Laravel RESTful API Dengan Android Menggunakan Retrofit2 Part 1
Pada tahap ini kita akan membuat projek android dan akan kita hubungakan dengan RESTful API yang telah kita buat sebelumnya dengan menggunakan framework laravel. untuk itu kita perlu mempersiapkan tool yang dibutuhkan :
- android studio
pertama-tama saya akan menjelaskan tahap yang ada pada tulisan kali ini, kali ini akan dilakukan setup awal projek android dan hanya akan melakukan read data, untuk Create, Update dan Delete(CUD) akan ada pada part 2, langsung saja tahapan yang akan dilakukan :
1. Kita buat view pada projek android untuk menghandle data yang kita dapatkan dari rest server(jika anda sudah memiliki view untuk menghandle anda bisa melewati langkah ini)
2. buat class response yang digunakan untuk menangkap respon yang diberikan oleh rest server
3. buat class Model yang digunakan untuk menangani data yang dikirimkan oleh rest server
4. buat class yang digunakan untuk menangani hubungan kirim dan terima data dari client ke rest server
masuk pada tahap pertama kita akan membuat tampilan, saya akan membuat bottom navigation bar yang akan digunakan untuk berpindah pindah menu, tapi terserah kalian jika kalian tidak membutuhkan tampilan yang rapi hehehe 😊
Petama buat package dengan nama “menu” didalam direktori “res” kemudian didalam package “menu” tersebut buat menu resource file dengan nama terserah anda, kalau saya “bottom_nav”.
Didalam file resource tersebut masukkan kode berikut :
<item
android:id="@+id/dashboard"
android:icon="@drawable/ic_baseline_dashboard_24"
android:title="Dashboard"></item>
<item
android:id="@+id/tambah_Barang"
android:title="Tambah"
android:icon="@drawable/ic_baseline_playlist_add_24"></item>
<item
android:id="@+id/edit_Barang"
android:title="Update Barang"
android:icon="@drawable/ic_baseline_edit_24"></item>
kode diatas merupakan menu item yang akan tampil saat kita membuat bottom navigation bar.
buka layout activity_main, karena layout itu merupakan layout milik activity saat kita pertama kali membuat projek baru di android studio. Tambahkan kode berikut untuk membuat bottom navigation bar pada layout activity_main.xml. Oiya saya menggunakan constraint layout :
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/cardview_light_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/bottom_nav"
app:itemIconTint="@color/nav_color"
app:itemTextColor="@color/nav_color"
/>
Jika sudah kita buat frame layout diatas navigation bar tersebut. Copy kode berikut untuk membuat frame layout :
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/bottom_nav"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
sehingga menghasilkan tampilan seperti berikut :
Gan, buat apa sih frame layout itu?, kan Cuma kosong gimana kita handle datanya nanti?
Nah frame layout ini digunakan sebagai template frame dasar, android kan membuat halamannya dengan cara menumpuk halaman lain, jadi nanti kita akan membuat layout untuk diisi oleh data yang kita dapatkan dari rest server, kemudian saat halaman layout berisi data itu dipilih maka framelayout itu akan ditindih oleh layout yang berisi data tersebut. Konsepnya seperti ini sih :
Jadi kita anggap layout A merupakan frame layout dan Layout B merupakan layout yang berisi data, maka saat kita memilih menu layout data maka layout A akan ditumpuk oleh layout B begitu seterusnya.
Masih di class “MainActivity”, kita inisialisasi bottom navigation yang telah kita buat dan buat dan buat method listener untuk mengontrol clik pada bottom navigation. Keseluruhan kodenya dapat dilihat seperti berikut atau copy code berikut :
public class MainActivity extends AppCompatActivity {
BottomNavigationView bottom_nav;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottom_nav = (BottomNavigationView)findViewById(R.id.bottom_nav);
bottom_nav.setOnNavigationItemSelectedListener(navListener);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new DashBoardFragment()).commit();
}
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
Fragment selected = null;
switch (item.getItemId()){
case R.id.dashboard:
selected = new DashBoardFragment();
break;
case R.id.tambah_Barang:
selected = new AddBarangFragment();
break;
case R.id.edit_Barang:
selected = new UpdateBarangFragment();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
selected).commit();
return true;
}
};
}
Pada method function listener kita buat case case. Perhatikan kode case “R.id.dashboard”. kode tesebut berarti jika casenya Resource dengan id dashboard ditekan maka pindah ke Class dengan nama DashboardFragment();
Jika sudah seperti diatas kode pada tiap case pasti akan merah karena kita belum membuat class class yang ada pada tiap case tersebut. Kita buat saja ketigas class tersebut. Pertama ada class bernama DashBoardFragment, kedua AddBarangFragment dan terakhir UpdateBarangFragment.
Jika sudah membuat classnya kita buat juga layout yang mendasar tampilan dari class tersebut. Untuk membuat layout anda sekalian bisa membuka folder res->layout. Sampai di package layout klik kanan->new->layout resource file. Buatlah 3 layout sesuai dengan 3 class yang kita buat.
Selanjutnya buka 3 class tersebut dan kita tambahkan override method onViewCreated dan onCreateView. Khususnya pada bagian onCreateView returnnya kita ubah mengikuti kode berikut :
return inflater.inflate(R.layout.”nama layout yang kalian buat”, container, false). Jadi class DashBoardFragment ini meng-inflate layout fragment_dashboard. Lakukan hal ini pada 2 class dan 2 layout lainnya.
Sampai pada tahap ini kita lanjutkan dengan membuat recycler view untuk menghandle data yang masuk. Yang pertama kita lakukan untuk menggunakan recycler view kita perlu menambahkan dependency material design. Jadi kita buka Kembali build.gradle level module dan tambahakn kode berikut :
implementation 'com.google.android.material:material:1.3.0-alpha02'
jika sudah lakukan sinkronisasi, kemudian buka layout_dashboar dan tambahkan recycler view :
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView_daftarBarang"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Kemudian buka class DashBoardFragment dan deklarasi Recycler view yang kita buat dan instansiasi variable deklarasi tadi :
RecyclerView tabel_barang;
untuk instansiasi lakukan didalam override method onViewCreated seperti contoh berikut :
tabel_barang = (RecyclerView)view.findViewById(R.id.recyclerView_daftarBarang);
kesuluruhan kode dapat mengikuti gambar berikut :
Selanjutnya kita buat adapter untuk mengisi recycler view tadi. Buat class dengan nama AdapterDaftarBarang dan buat layout dengan nama layout_daftar_barang. Untuk layout_daftar_barang bisa langsung copy kode berikut :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/layout_daftar_barang">
<androidx.cardview.widget.CardView
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="90dp"
android:layout_margin="5dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/judul_kode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:textSize="18dp"
android:text="Kode Barang :"
android:textColor="@color/splashScreen"
app:layout_constraintStart_toStartOf="@+id/cardView"
app:layout_constraintTop_toTopOf="@+id/cardView" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="34dp"
android:layout_marginLeft="8dp"
android:text="Nama Barang :"
android:textSize="16dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="58dp"
android:layout_marginLeft="8dp"
android:text="Jumlah Barang :"
android:textSize="16dp" />
<TextView
android:id="@+id/textViewJumlahBarang"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="58dp"
android:layout_marginLeft="128dp"
android:text="000"
android:textSize="16dp" />
<TextView
android:id="@+id/textViewNamaBarang"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="34dp"
android:layout_marginLeft="128dp"
android:text="Teh Pucuk"
android:textSize="16dp" />
<TextView
android:id="@+id/textViewKodeBarang"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginLeft="128dp"
android:text="0001"
android:textColor="@color/splashScreen"
android:textSize="18dp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageButton
android:id="@+id/imgBtnDeleteBarang"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_baseline_delete_outline_24"
android:background="@null"
android:adjustViewBounds="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginTop="16dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="12dp"/>
<ImageButton
android:id="@+id/imgBtnEditBarang"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/imgBtnDeleteBarang"
android:layout_alignParentRight="true"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:adjustViewBounds="true"
android:background="@null"
android:src="@drawable/ic_baseline_edit_24" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Layout ini merupakan layout tempat kita akan menampilkan data dan recycler view merupakan view yang melakukan daur ulang terhadap layout ini. Bentuk dari layout ini seperti berikut :
Setelah itu masuk ke class AdapterDaftarBarang dan copy code berikut :
public class AdapterDaftarBarang extends RecyclerView.Adapter<AdapterDaftarBarang.ViewHolder> {
UpdateDataBarangFragement updateDataBarangFragement;
InterfaceConnection interfaceConnection;
ArrayList<Data_Model> daftarBarang;
Context mContext;
String id;
public AdapterDaftarBarang(Context context){
daftarBarang = new ArrayList<>();
mContext = context;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_daftar_barang, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.kodeBarang.setText(daftarBarang.get(position).getKode_barang());
holder.namaBarang.setText(daftarBarang.get(position).getNama_barang());
holder.jumlahBarang.setText(daftarBarang.get(position).getJumlah_barang());}@Override
public int getItemCount() {
return daftarBarang.size();
}
public void updatedatabarang(ArrayList<Data_Model> updatedatabarang){
daftarBarang.clear();
daftarBarang.addAll(updatedatabarang);
notifyDataSetChanged();
}public class ViewHolder extends RecyclerView.ViewHolder{
ConstraintLayout layout_daftar_barang;
TextView kodeBarang, namaBarang, jumlahBarang;
ImageButton btnDelete, btnEdit;
public ViewHolder(@NonNull View itemView) {
super(itemView);
layout_daftar_barang = (ConstraintLayout)itemView.findViewById(R.id.layout_daftar_barang);
kodeBarang = (TextView) itemView.findViewById(R.id.textViewKodeBarang);
namaBarang = (TextView)itemView.findViewById(R.id.textViewNamaBarang);
jumlahBarang = (TextView)itemView.findViewById(R.id.textViewJumlahBarang);
btnDelete = (ImageButton)itemView.findViewById(R.id.imgBtnDeleteBarang);
btnEdit = (ImageButton)itemView.findViewById(R.id.imgBtnEditBarang);
}
}
}
Untuk tahap view saya kira sudah cukup. Kemudian kita masuk ke tahap kedua yaitu membuat class untuk menghadle data yang dikirimkan dari rest server
pertama buat folder dengan nama model kemudian buat class didalam package model tersebut dengan nama Data_model seperti gambar berikut :
Didalam class Data_Model buat variable yang sesuai dengan data yang kalian buat pada rest server kalian, kalau saya hanya terdapat 3 variabel data, pertama ada kode barang, nama barang dan jumlah barang jangan lupa tambahkan kode @SerializedName sebelum variable. Jika variable sudah dibuat tambahkan setter dan getter pada tiap variable, seperti gambar berikut :
public class Data_Model {
@SerializedName("kode_barang")
private String kode_barang;
@SerializedName("nama_barang")
private String nama_barang;
@SerializedName("jumlah_barang")
private String jumlah_barang;
public String getKode_barang() {
return kode_barang;
}
public void setKode_barang(String kode_barang) {
this.kode_barang = kode_barang;
}
public String getNama_barang() {
return nama_barang;
}
public void setNama_barang(String nama_barang) {
this.nama_barang = nama_barang;
}
public String getJumlah_barang() {
return jumlah_barang;
}
public void setJumlah_barang(String jumlah_barang) {
this.jumlah_barang = jumlah_barang;
}
}
Selanjutnya kita masuk pada tahap 3 yaitu membuat class untuk menghandle response dari rest server. Buat package dengan nama response kemudian buat file dengan nama Data_Response didalamnya.
Didalam Class Data_Response buat variable status dengan tipe data Boolean dan message dengan tipe data String, variable status ini akan digunakan oleh retrofit dalam menangkap status response apakah true atau false, dan variable message digunakan untuk menangkap message yang dikirimkan oleh rest server dan 1 tambahan List yang diarahkan ke model yang kita buat, jadi data yang dikirim oleh rest server akan ditangkap oleh response kemudian response memberikan data ke model. Untuk keseluruhan kode dapat dilihat seperti berikut saya sertakan gambar dan kode programnya :
public class Data_Response {
private Boolean status;
private String message;
@SerializedName("data")
List<Data_Model> seluruh_barang;
public Boolean getStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<Data_Model> getSeluruh_barang() {
return seluruh_barang;
}
public void setSeluruh_barang(List<Data_Model> seluruh_barang) {
this.seluruh_barang = seluruh_barang;
}
}
Pembuatan model dan response sudah kita bisa lanjutkan dengan membuat koneksi antara client dan server.
Karena penggunaan rest ini membutuhkan koneksi internet, kita buat aplikasi kita dapat mengakses internet, buka file manifest dan tambahkan kode berikut :
<uses-permission android:name="android.permission.INTERNET" />
Berikut merupakan screenshot kesuluruhan manifest :
Selanjutnya buka buld.gradle level module dan tambahkan kode berikut pada android{} seperti gambar dibawah :
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
untuk penempatan kode diatas dapat diletakkan didalam tag android {}
Kode diatas diperlukan karena android sendiri mengharuskan kita menggunakan HTTPS dan rest yang kita buat hanya HTTP dan tidak secure(bukan HTTPS). Masih di build.gradle kita tambahkan dependency dari retrofit yang bisa dilihat disini atau dengan meng-copy kode berikut :
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
pada saat saya membuat projek ini retrofit2 sedang ada pada versi 2.9.0, pastikan anda mengecek versi terupdate dari retrofit2, berikut tampilannya :
Jika sudah tambahkan dua dependency lainnya
1. Retrofit2 converter json merupakan dependency tambahan yang dibutuhkan retrofit2 untuk melakukan konversi saat menghubungi rest server melalui URL. Versi terbaru dari dependency retrofit2 converter dapat dilihat disini.
2. Goggle gson merupakan library yang digunakan untuk merubah java object ke bentuk Json. Versi terbaru dapat dilihat disini.
Disaat saya membuat tulisan ini versi yang digunakan untuk retrofit2 converter adalah versi 2.9.0, dan untuk google gson di versi 2.8.6. dapat dituliskan seperti gambar dibawah ini :
Jika sudah ditambahkan seperti diatas, lakukan sinkronasi terlebih dahulu, dapat dengan mengklik pop up bar yang muncul Ketika kita selesai menambahkan dependency dan tunggu hingga sinkronasi selesai
Jika sudah buatlah package baru dengan nama “rest”, nantinya dalam package rest ini kita akan membuat class class yang digunakan untuk menghubungkan client ke rest server. Jika package sudah dibuat kita buat class baru didalam package rest tadi dengan nama ApiConnection dengan cara klik kanan pada package rest kemudian new->class dan beri nama ApiConnection. Buka class ApiConnection yang telah kita buat kemudian tambahkan kode berikut :
public static final String BASE_URL = http://IP computer yang kalian gunakan" /sistem_kasir/public/api/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
Jika pada saat kita melakukan pengetesan menggunakan postman kita memasukkan ip 127.0.0.1:800/sistem_kasir/public/api maka pada rest client yaitu projek android ini, kita wajib memasukkan ip computer atau laptop yang akan dijadikan sebagai server dan perlu diingat computer kalian harus terhubung dengan jaringan yang sama pada hp kalian saat program ini dijalankan. Kalian bisa menggunakan tattering dari smartphone atau terhubung di jaringan wifi yang sama. Pada bagian BASE_URL dengan IP 192.168.18.2 kalian ubah menjadi IP milik computer kali. Untuk mengecek IP computer kalian buka command prompt dan ketikkan ipconfig
IPv4 Address itulah ip dari computer kalian. Selanjutnya di package yang sama kita buat interface class dengan nama InterfaceConnection, interface ini digunakan sebagai sambungan url yang kita akan gunakan untuk menghubungi rest server kita. Untuk permulaan kita akan buat fungsi untuk mendapat seluruh data yang ada didalam database kita. Copy kode berikut kedalam interface class InterfaceConnection :
public class DashBoardFragment extends Fragment {
ArrayList<Data_Model> daftarseluruhBarang = new ArrayList<>();
RecyclerView tabel_barang;
InterfaceConnection interfaceConnection;
AdapterDaftarBarang adapterDaftarBarang;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
tabel_barang = (RecyclerView)view.findViewById(R.id.recyclerView_daftarBarang);
interfaceConnection = ApiConnection.getClient().create(InterfaceConnection.class);
loadDataBarang();
}
private void loadDataBarang() {
adapterDaftarBarang = new AdapterDaftarBarang(getContext());
Call<Data_Response> daftar_barang = interfaceConnection.daftar_barang();
daftar_barang.enqueue(new Callback<Data_Response>() {
@Override
public void onResponse(Call<Data_Response> call, Response<Data_Response> response) {
if (response.isSuccessful()){
List<Data_Model> seluruh_barang = response.body().getSeluruh_barang();
daftarseluruhBarang.addAll(seluruh_barang);
} else {
try {
JSONObject jObjError = new JSONObject(response.errorBody().string());
Toast.makeText(getActivity(), jObjError.getString("message"), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
adapterDaftarBarang.updatedatabarang(daftarseluruhBarang);
}
@Override
public void onFailure(Call<Data_Response> call, Throwable t) {
Log.d("Error Jaringan", "disini");
t.printStackTrace();
Log.d("here", "here", t);
Toast.makeText(getActivity(), "Terjadi kesalahan", Toast.LENGTH_SHORT).show();
}
});
startRecyclerView();
}
private void startRecyclerView() {
tabel_barang.setAdapter(adapterDaftarBarang);
tabel_barang.setLayoutManager(new LinearLayoutManager(getActivity()));
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_dashboard, container, false);
}
}
Yuk kita run aplikasi nya, pertama kita lihat data yang ada pada database kita
Dan berikut hasilnya pada android :
Sebelumnya di cara membuat rest yang saya buat ditulisan ini, kita akan melakukan perubahan sedikit mengenai status yang dikirimkan oleh rest jika sebelumnya saya menuliskan status tersebut seperti ini :
Kita rubah statusnya menjadi true, seperti gambar dibawah :
Untuk response salah bisa diganti saja statusnya menjadi false dan sisanya tetap sama 😊
Retrofit meminta status dengan tipe data Boolean untuk mengetahui request yang dilakukan menghasilkan nilai response true atau false, saya mencoba status dengan tipe data string di rest client android mendapatkan error bahwa status butuh Boolean data, atau sayanya aja yang kurang mencoba lagi(tolong jangan dihujat hehe). Tapi sampai disini koneksi restnya sudah mau, dan terima kasih 😊
berikut source code githubnya. semoga membantu 😊