Cara Membuat Project Di Android Studio, Aplikasi LaporIN (Anonim)
Daftar Isi
Hallo Sobat Programmer!!, Pada artikel kali ini saya akan menjalaskan sebuah Aplikasi LaporIN serta memberikan tutorial singkat cara membuat sebuah project di AndroidStudio. bagi sobat programmer yang belum paham cara menginstall AndroidStudio, bisa lihat di Cara Install AndroidStudio jangan lupa dibaca ya sob!!
Aplikasi LaporIN merupakan sebuah aplikasi pengaduan layanan masyarakat yang terdapat permasalahan pada saat sekarang yang dimana problemnya itu masyarakat takut dalam melaporkan tindak kejahatan seperti pemakaian narkoba, dan rata - rata takut data yang melaporkan tindak kejahatan tersebut di cari oleh oknum. Maka dari itu, saya mengangkat permasalahan ini dan saya jadikan sebuah solusi mengenai Aplikasi LaporIN (Anonim). Sediakan kopi!! langsung saja simak artikel sampai habis ya sob!!
Persiapan Pembuatan Aplikasi
Sebelum sobat masuk dalam pembuatan project di android studio, sobat harus mempersiapkan beberapa tahap untuk mengembangkan aplikasi diandroidstudio. Emang penting? Ya penting dong sob!! karena jika sobat tidak melakukan persiapannya maka sobat akan kebingungan dan apa yang harus dilakukan!! berikut ini merupakan tahapan dalam pembuatan aplikasi android di AndroidStudio:
1. Identifikasi Kebutuhan
Pada tahap awal ini, sobat harus mengidentifikasikan telebih dahulu apa saja kebutuhan aplikasi yang sobat inginkan, apa masalah yang ingin diselesaikan, target pengguna, fitur utama, platformnya apa. Nah, jika sudah di definisikan semuanya, maka bisa masuk ketahap 2.
2. Design
Pada tahap kedua ini, sobat harus mengedesign tampilan yang dibutuhkan, dan sobat jadikan design tersebut ke prototipe, sobat bisa membuat designnya menggunakan figma, atau tools lainnya. Berikut dibawah ini merupakan design dari aplikasi LaporIN, dan ini link design figmanya.
Nah, persiapan diatas merupakan persiapan sederhana, dan pastikan tahap ke 2 itu sangat penting, agar sobat tidak bingung dalam pembuatan tampilan di androidStudio.
Cara Membuat Project Di AndroidStudio
Berikut ini merupakan cara membuat sebuah project di androidstudio, tutorial ini hanya disarankan untuk para pemula yang ingin terjun ke dunia mobile programming.
Langkah 1: Buka AndroidStudionya
Langkah 2: Ketika sudah sobat buka, maka silahkan klik new project. jika sudah mengkliknya maka akan menampilkan sebuah dialog halaman template seperti gambar dibawah ini:
Langkah 4: Kemudian, jika klik tombol next, maka akan muncul tampilan pengaturan target android versionnya seperti gambar dibawah ini. dan sobat bisa menyesuaikannya, pada pengaturan ini, saya menggunakan bahasa java, dan untuk api androidnya api version 24. Klik tombol finish jika sudah menyesuaikan peraturannya.
Langkah 5: Setelah selesai, akan ada window yang dimana window tersebut merupakan workspace project androidstudio tadi yang telah sobat buat! dan tampilannya seperti gambar dibawah ini:
Nah, cukup mudah bukan untuk membuat sebuah project dasar aplikasi di androidstudio!!, jangan bosan dulu ya sobat, karena terdapat penjelasan aplikasi LaporIN! Sediakan kopi.
Aplikasi LaporIN
Terdapat beberapa libray yang digunakan untuk membuat aplikasi LaporIN, berikut ini merupakan tools atau librarynya:
implementation("androidx.cardview:cardview:1.0.0")
implementation("com.google.android.gms:play-services-location:18.0.0")
implementation("org.osmdroid:osmdroid-android:6.1.10")
implementation("com.github.mkergall:osmbonuspack:6.9.0")
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")
implementation("com.karumi:dexter:6.2.3")
implementation("com.android.volley:volley:1.2.1")
implementation("com.github.bumptech.glide:glide:4.15.1")
annotationProcessor("com.github.bumptech.glide:compiler:4.15.1")
Diatas merupakan library yang saya gunakan untuk membuat sebuah aplikasi LaporIN. Lalu, saya juga menggunakan openstreetmap digunakan untuk menampilkan maps, dikarena ini aplikasi sederhana, jadi saya menggunakan openstreetmap yang gratis. Setelah itu, berikut ini merupakan kode xml dibawah untuk list news berita pada home page.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="12dp"
android:background="@drawable/rounded_background"
android:elevation="4dp"
android:layout_marginBottom="16dp">
<!-- Kontainer untuk Konten Berita -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<!-- Kategori -->
<TextView
android:id="@+id/newsCategory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Kejahatan"
android:textColor="#007AFF"
android:textSize="12sp"
android:fontFamily="sans-serif-medium"
android:layout_marginBottom="4dp" />
<!-- Judul Berita -->
<TextView
android:id="@+id/newsTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="10 Tips Untuk Orang Jahat dapat membantu Anda tetap hidup sehat dan bahagia."
android:textSize="14sp"
android:fontFamily="sans-serif-medium"
android:lineSpacingExtra="2dp"
android:layout_marginBottom="8dp" />
<!-- Deskripsi Berita -->
<TextView
android:id="@+id/newsSummary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Deskripsi singkat berita"
android:textSize="12sp"
android:fontFamily="sans-serif"
android:textColor="#808080"
android:visibility="gone" />
</LinearLayout>
<!-- Gambar -->
<ImageView
android:id="@+id/newsImage"
android:layout_width="72dp"
android:layout_height="72dp"
android:scaleType="centerCrop"
/>
</LinearLayout>
Nah, kenapa saya pisah dari xml awalnya, karena list_news.xml pada kode diatas agar saya mudah menghandlenya, jadi nanti tinggal menampilkannya menggunakan java, berikut dibawah ini merupakan kode javanya. dibawah ini class Article untuk menyimpan data sementara.package com.mopro;
public class Article {
private int id;
private String category;
private String title;
private String content;
private String image;
public Article(int id, String category, String title, String content, String image) {
this.id = id;
this.category = category;
this.title = title;
this.content = content;
this.image = image;
}
public int getId() {
return id;
}
public String getCategory() {
return category;
}
public String getTitle() {
return title;
}
public String getContent() {
return content;
}
public String getImage() {
return image;
}
}
Dan kode dibawah ini merupakan kode utama untuk menampilkan artikel. Terdapat Metode fetchArticles digunakan untuk mengambil data artikel dari API menggunakan library Volley di Android. Metode ini mengirimkan permintaan GET ke URL API, memproses respons JSON, dan memperbarui data pada antarmuka. Jika respons berhasil, metode memeriksa status success dan membaca data artikel dari array data. Setiap artikel diolah menjadi objek Article yang ditambahkan ke dalam daftar dan diperbarui melalui adapter. Jika judul artikel terlalu panjang, akan dipotong dan ditambahkan elipsis. Jika permintaan gagal, error ditangani dengan mencatat log dan menampilkan pesan kepada pengguna menggunakan Toast. Semua permintaan dijalankan secara asynchronous melalui queue Volley.
package com.mopro;
import android.os.Bundle;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.widget.Button;
import android.content.Intent;
import android.view.View;
import android.widget.LinearLayout;
// Volley adalah library untuk melakukan HTTP request dengan lebih mudah
import com.android.volley.Request;
import com.android.volley.toolbox.JsonObjectRequest; // Digunakan untuk melakukan request JSON
import com.android.volley.toolbox.Volley; // Volley menyediakan queue untuk mengelola request
import com.android.volley.Response; // Digunakan untuk menangani response
import com.android.volley.VolleyError; // Digunakan untuk menangani error saat request
import org.json.JSONArray; // Untuk membaca array JSON dari response
import org.json.JSONException; // Untuk menangani kesalahan parsing JSON
import org.json.JSONObject; // Untuk memanipulasi objek JSON
import java.util.List;
import java.util.ArrayList;
import android.util.Log; // Untuk menambahkan log debug di Android
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView; // Komponen untuk menampilkan daftar data dalam format list atau grid
private NewsAdapter adapter; // Adapter bertugas untuk menghubungkan data dengan RecyclerView
private List<Article> articleList = new ArrayList<>(); // List untuk menyimpan data artikel
private LinearLayout addReport, search;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
// Inisialisasi tombol
addReport = findViewById(R.id.addReport);
search = findViewById(R.id.search);
// Set listener untuk tombol
addReport.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Arahkan ke ReportActivity
Intent intent = new Intent(MainActivity.this, ReportActivity.class);
startActivity(intent);
}
});
// Set listener untuk tombol
search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Arahkan ke ReportActivity
Intent intent = new Intent(MainActivity.this, ReportDetailActivity.class);
startActivity(intent);
}
});
// Inisialisasi RecyclerView
recyclerView = findViewById(R.id.newsRecyclerView); // Hubungkan RecyclerView dengan ID di layout XML
recyclerView.setLayoutManager(new LinearLayoutManager(this)); // Atur layout menjadi Linear (list)
// Inisialisasi adapter dan hubungkan dengan RecyclerView
adapter = new NewsAdapter(this, articleList);
recyclerView.setAdapter(adapter);
// Panggil fungsi untuk mengambil artikel dari server
fetchArticles();
}
private void fetchArticles() {
// URL API untuk mengambil data artikel
String url = "https://getkey.my.id/api/v1/getArticle"; // Ganti dengan URL API Anda
// Membuat request GET menggunakan JsonObjectRequest
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() { // Listener untuk response
@Override
public void onResponse(JSONObject response) {
try {
// Periksa apakah response berhasil (dengan field "success" == true)
if (response.getBoolean("success")) {
// Ambil array "data" dari response
JSONArray articles = response.getJSONArray("data");
for (int i = 0; i < articles.length(); i++) {
// Ambil setiap objek artikel dari array
JSONObject articleObj = articles.getJSONObject(i);
// Ambil dan potong judul jika terlalu panjang
String title = articleObj.getString("title");
int maxLength = 50; // Panjang maksimum judul
if (title.length() > maxLength) {
title = title.substring(0, maxLength) + "..."; // Tambahkan elipsis jika dipotong
}
// Buat objek Article dengan data yang diambil dari response
Article article = new Article(
articleObj.getInt("id"),
articleObj.getString("category"), // Kategori artikel
title, // Judul artikel (sudah dipotong jika panjang)
articleObj.getString("content"), // Isi artikel
articleObj.getString("image") // URL gambar artikel
);
// Tambahkan artikel ke dalam list
articleList.add(article);
}
// Beritahu adapter bahwa data telah berubah, agar RecyclerView di-update
adapter.notifyDataSetChanged();
} else {
// Jika response tidak mengandung "success", log pesan error
Log.e("API Response", "Failed to fetch data: " + response.getString("message"));
}
} catch (JSONException e) {
// Tangani kesalahan parsing JSON
Log.e("JSON Parsing Error", "Error parsing response: " + e.getMessage());
e.printStackTrace();
}
}
},
new Response.ErrorListener() { // Listener untuk menangani error pada request
@Override
public void onErrorResponse(VolleyError error) {
// Tampilkan log error jika request gagal
Log.e("API Request Error", "Error fetching data: " + error.getMessage());
// Tampilkan pesan kesalahan kepada pengguna
Toast.makeText(MainActivity.this, "Error fetching data", Toast.LENGTH_SHORT).show();
}
});
// Tambahkan request ke queue Volley untuk dieksekusi
Volley.newRequestQueue(this).add(request);
}
}
diatas merupakan penjelasan kode dari home page, dibawah ini merupakan kode dari form create laporan xml dan java. Berikut dibawah ini merupakan kodenya;
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="match_parent"
android:background="@color/white">
<!-- Toolbar -->
<RelativeLayout
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:padding="16dp">
<ImageButton
android:id="@+id/btn_back"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_centerVertical="true"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_arrow_back"
android:contentDescription="Back button" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Buat Laporan"
android:textColor="@color/black"
android:textSize="20sp"
android:textStyle="bold" />
</RelativeLayout>
<!-- Main Content -->
<ScrollView
android:id="@+id/main_scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/btn_submit"
android:layout_below="@id/toolbar"
android:fillViewport="true">
<LinearLayout
android:id="@+id/form_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/label_form_instructions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lengkapi data laporan kamu!"
android:textColor="@color/black"
android:textSize="16sp"
android:layout_marginBottom="24dp"/>
<TextView
android:id="@+id/label_basic_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Informasi dasar"
android:textColor="@color/black"
android:textSize="24sp"
android:textStyle="bold"
android:layout_marginBottom="32dp"/>
<!-- Judul Laporan -->
<TextView
android:id="@+id/label_judul"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Judul Laporan"
android:textColor="@color/black"
android:textSize="16sp"
android:layout_marginBottom="8dp"/>
<EditText
android:id="@+id/edt_judul"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/edit_text_background"
android:textColorHint="@color/grey"
android:textColor="@color/grey"
android:hint="Judul Laporan"
android:padding="16dp"
android:textSize="16sp"
android:layout_marginBottom="24dp"/>
<!-- Penjelasan Laporan -->
<TextView
android:id="@+id/label_penjelasan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Penjelasan Laporan"
android:textColor="@color/black"
android:textSize="16sp"
android:layout_marginBottom="8dp"/>
<EditText
android:id="@+id/edt_penjelasan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorHint="@color/grey"
android:textColor="@color/grey"
android:background="@drawable/edit_text_background"
android:hint="Contoh: Terdapat 2 orang pria menggunakan narkoba, dll"
android:padding="16dp"
android:minHeight="120dp"
android:gravity="top"
android:textSize="16sp"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/label_penjelasan_limit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Maks 100 Karakter"
android:textColor="@color/grey"
android:textSize="12sp"
android:layout_gravity="end"
android:layout_marginBottom="24dp"/>
<!-- File Pendukung -->
<TextView
android:id="@+id/label_file_pendukung"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="File Pendukung"
android:textColor="@color/black"
android:textSize="16sp"
android:layout_marginBottom="8dp"/>
<LinearLayout
android:id="@+id/file_upload_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/edit_text_background"
android:padding="16dp"
android:gravity="center_vertical">
<TextView
android:id="@+id/label_upload"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Unggah"
android:textColor="@color/grey"
android:textSize="16sp"/>
<ImageButton
android:id="@+id/btn_upload"
android:layout_width="24dp"
android:layout_height="24dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/camera"
android:contentDescription="Upload button"/>
</LinearLayout>
<TextView
android:id="@+id/label_file_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Gambar"
android:textColor="@color/grey"
android:textSize="12sp"
android:layout_gravity="end"
android:layout_marginBottom="24dp"/>
<!-- Alamat -->
<TextView
android:id="@+id/label_alamat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Alamat"
android:textColor="@color/black"
android:textSize="16sp"
android:layout_marginBottom="8dp"/>
<EditText
android:id="@+id/edt_alamat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/edit_text_background"
android:hint="Alamat kejahatan/kejadian"
android:padding="16dp"
android:minHeight="120dp"
android:textColorHint="@color/grey"
android:textColor="@color/grey"
android:gravity="top"
android:textSize="16sp"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/label_alamat_limit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Maks 100 Karakter"
android:textColor="@color/grey"
android:textSize="12sp"
android:layout_gravity="end"/>
</LinearLayout>
</ScrollView>
<!-- Button Submit -->
<Button
android:id="@+id/btn_submit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_margin="16dp"
android:background="@drawable/button_background"
android:text="Lanjut"
android:textColor="@color/white"
android:textSize="16sp"/>
</RelativeLayout>
Kode di bawah adalah kode untuk mengirim laporan dengan file (gambar) menggunakan Retrofit. Pengguna mengisi judul, deskripsi, dan alamat, kemudian memilih file untuk diunggah. File dan data laporan dikirim melalui API menggunakan multipart request. Retrofit mengelola komunikasi HTTP, sedangkan file sementara disimpan di cache aplikasi untuk dikirimkan ke server. Setelah laporan berhasil dikirim, pengguna diarahkan ke layar lain, seperti peta, dengan ID laporan. Aplikasi juga menghapus file sementara saat aktivitas dihentikan untuk mencegah kebocoran memori pada hp pengguna.
package com.mopro;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitClient {
private static final String BASE_URL = "https://getkey.my.id/api/v1/";
private static Retrofit retrofit;
public static Retrofit getInstance() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
package com.mopro;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
public interface ApiService {
@Multipart
@POST("Report")
Call uploadReport(
@Part("title") RequestBody title,
@Part("description") RequestBody description,
@Part("address") RequestBody address,
@Part MultipartBody.Part file
);
}
package com.mopro;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.OpenableColumns;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class ReportActivity extends AppCompatActivity {
private static final String TAG = "ReportActivity";
private EditText edtJudul, edtPenjelasan, edtAlamat;
private ImageButton btnUpload;
private Button btnLanjut;
private TextView labelUpload;
private ImageView btn_back;
private Uri fileUri;
private File cachedFile; // File sementara untuk pengiriman
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_report);
btn_back = findViewById(R.id.btn_back);
btn_back.setOnClickListener(v -> finish());
// Inisialisasi elemen UI
edtJudul = findViewById(R.id.edt_judul);
edtPenjelasan = findViewById(R.id.edt_penjelasan);
edtAlamat = findViewById(R.id.edt_alamat);
btnUpload = findViewById(R.id.btn_upload);
btnLanjut = findViewById(R.id.btn_submit);
labelUpload = findViewById(R.id.label_upload);
// Pilih file untuk diunggah
btnUpload.setOnClickListener(v -> pilihFile());
// Tombol untuk mengirim laporan
btnLanjut.setOnClickListener(v -> kirimLaporan());
}
private void pilihFile() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, 1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == RESULT_OK && data != null && data.getData() != null) {
fileUri = data.getData();
labelUpload.setText(getFileName(fileUri));
Log.d(TAG, "File URI: " + fileUri.toString());
}
}
private void kirimLaporan() {
String judul = edtJudul.getText().toString().trim();
String penjelasan = edtPenjelasan.getText().toString().trim();
String alamat = edtAlamat.getText().toString().trim();
if (judul.isEmpty() || penjelasan.isEmpty() || alamat.isEmpty()) {
Toast.makeText(this, "Harap isi semua data!", Toast.LENGTH_SHORT).show();
return;
}
if (fileUri == null) {
Toast.makeText(this, "Harap pilih file terlebih dahulu!", Toast.LENGTH_SHORT).show();
return;
}
try {
cachedFile = createCacheFile(fileUri);
MultipartBody.Part filePart = MultipartBody.Part.createFormData(
"file", cachedFile.getName(),
RequestBody.create(MediaType.parse(getContentResolver().getType(fileUri)), cachedFile)
);
RequestBody judulPart = RequestBody.create(MediaType.parse("text/plain"), judul);
RequestBody penjelasanPart = RequestBody.create(MediaType.parse("text/plain"), penjelasan);
RequestBody alamatPart = RequestBody.create(MediaType.parse("text/plain"), alamat);
ApiService apiService = RetrofitClient.getInstance().create(ApiService.class);
Call<ReportResponse> call = apiService.uploadReport(judulPart, penjelasanPart, alamatPart, filePart);
call.enqueue(new Callback<ReportResponse>() {
@Override
public void onResponse(Call<ReportResponse> call, Response<ReportResponse> response) {
if (response.isSuccessful() && response.body() != null) {
ReportResponse reportResponse = response.body();
if (reportResponse.isSuccess()) {
int idReport = reportResponse.getId(); // Ambil ID dari respons
// Beralih ke Maps.class dan kirimkan ID laporan
Intent intent = new Intent(ReportActivity.this, Maps.class);
intent.putExtra("id_report", idReport); // Kirim ID report ke Maps
startActivity(intent);
finish();
} else {
Toast.makeText(ReportActivity.this, reportResponse.getMessage(), Toast.LENGTH_SHORT).show();
}
} else {
Log.e(TAG, "Gagal mengirim laporan. Response code: " + response.code());
Toast.makeText(ReportActivity.this, "Gagal mengirim laporan: " + response.message(), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<ReportResponse> call, Throwable t) {
Log.e(TAG, "Terjadi kesalahan saat mengirim laporan.", t);
Toast.makeText(ReportActivity.this, "Kesalahan: " + t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
} catch (IOException e) {
Log.e(TAG, "Gagal membuat file sementara", e);
Toast.makeText(this, "Gagal memproses file!", Toast.LENGTH_SHORT).show();
}
}
private File createCacheFile(Uri uri) throws IOException {
// Ambil nama asli file
String fileName = getFileName(uri);
if (fileName == null) {
fileName = "file_" + System.currentTimeMillis(); // Nama default jika tidak ditemukan
}
// Buat file sementara di cache
File tempFile = new File(getCacheDir(), fileName);
try (InputStream inputStream = getContentResolver().openInputStream(uri);
FileOutputStream outputStream = new FileOutputStream(tempFile)) {
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
}
return tempFile;
}
private String getFileName(Uri uri) {
try (Cursor cursor = getContentResolver().query(uri, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
return cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
}
return null; // Jika tidak ditemukan
}
@Override
protected void onDestroy() {
super.onDestroy();
if (cachedFile != null && cachedFile.exists()) {
cachedFile.delete(); // Hapus file sementara jika aplikasi dihentikan
}
}
}
Setelah halaman pembuatan laporan, maka berikut ini halaman maps xml dan javanya:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Top Bar -->
<LinearLayout
android:id="@+id/top_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@color/white"
android:padding="16dp"
android:elevation="4dp">
<!-- Title -->
<TextView
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="Titik Posisi MAPS"
android:textSize="18sp"
android:textColor="@color/black"
android:gravity="center_vertical" />
</LinearLayout>
<!-- Search Bar -->
<EditText
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/top_bar"
android:textColorHint="@color/grey"
android:textColor="@color/grey"
android:hint="Cari Lokasi"
android:padding="12dp"
android:background="@android:color/white"
android:drawableLeft="@android:drawable/ic_menu_search"
android:drawablePadding="8dp"
android:imeOptions="actionSearch"
android:inputType="text"
android:elevation="2dp" />
<!-- Map View -->
<org.osmdroid.views.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/search_bar" />
<!-- Button Laporkan Sekarang -->
<Button
android:id="@+id/btn_report"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="Laporkan Sekarang"
android:padding="12dp"
android:textSize="18sp"
android:background="@color/lavender"
android:textColor="@android:color/white" />
</RelativeLayout>
diatas merupakan kode tampilan maps xmlnya, dan dibawah ini kode untuk mengimplementasikan aktivitas peta di Android menggunakan osmdroid, yang memungkinkan pengguna mencari lokasi, melihat posisi mereka, dan melaporkan lokasi. Aplikasi menggunakan
FusedLocationProviderClient
untuk mendapatkan lokasi perangkat dan menampilkan marker di peta. Pengguna dapat mencari lokasi melalui kolom pencarian, dan lokasi yang dipilih akan dikirim ke server dengan ID laporan melalui permintaan POST. Setelah laporan berhasil dikirim, aplikasi menampilkan kode laporan. Kode juga mengelola izin lokasi dan memberikan umpan balik kepada pengguna jika terjadi kesalahan.package com.mopro;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import org.json.JSONException;
import org.json.JSONObject;
import org.osmdroid.config.Configuration;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.Marker;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Locale;
public class Maps extends AppCompatActivity {
private static final String API_URL = "https://getkey.my.id/api/v1/Location";
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
private MapView mapView;
private EditText searchBar;
private Button btnReport;
private GeoPoint lastSearchedPoint;
private int idReport; // ID Report dari Intent
// Location client
private FusedLocationProviderClient fusedLocationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Konfigurasi osmdroid
Configuration.getInstance().setUserAgentValue(getPackageName());
setContentView(R.layout.activity_maps);
// Ambil ID report dari intent
idReport = getIntent().getIntExtra("id_report", -1);
if (idReport != -1) {
Log.d("MapsActivity", "ID Report diterima: " + idReport);
} else {
Log.e("MapsActivity", "ID Report tidak ditemukan!");
}
// Inisialisasi komponen berdasarkan ID di XML
mapView = findViewById(R.id.map);
searchBar = findViewById(R.id.search_bar);
btnReport = findViewById(R.id.btn_report);
// Konfigurasi MapView
mapView.setTileSource(TileSourceFactory.MAPNIK);
mapView.setBuiltInZoomControls(true);
mapView.setMultiTouchControls(true);
// Inisialisasi FusedLocationProviderClient
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
// Meminta permission lokasi jika belum diberikan
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION
}, LOCATION_PERMISSION_REQUEST_CODE);
} else {
getDeviceLocation();
}
setInitialLocation();
// Listener untuk pencarian lokasi
searchBar.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_DONE) {
String location = searchBar.getText().toString().trim();
if (!location.isEmpty()) {
searchLocation(location);
} else {
Toast.makeText(this, "Masukkan lokasi yang valid", Toast.LENGTH_SHORT).show();
}
return true;
}
return false;
});
// Listener untuk tombol "Laporkan Sekarang"
btnReport.setOnClickListener(v -> {
if (lastSearchedPoint != null) {
saveLocationToServer(lastSearchedPoint.getLatitude(), lastSearchedPoint.getLongitude(), "Lokasi yang dilaporkan");
} else {
Toast.makeText(this, "Tidak ada lokasi untuk dilaporkan", Toast.LENGTH_SHORT).show();
}
});
}
private void setInitialLocation() {
GeoPoint defaultLocation = new GeoPoint(3.595195, 98.672223);
mapView.getController().setCenter(defaultLocation);
mapView.getController().setZoom(15.0);
mapView.invalidate();
addMarker(defaultLocation, "Posisi Default", "Lokasi awal");
}
private void getDeviceLocation() {
try {
Task<android.location.Location> locationResult = fusedLocationClient.getLastLocation();
locationResult.addOnSuccessListener(this, location -> {
if (location != null) {
GeoPoint currentLocation = new GeoPoint(location.getLatitude(), location.getLongitude());
mapView.getController().setCenter(currentLocation);
mapView.getController().setZoom(15.0);
mapView.invalidate();
addMarker(currentLocation, "Lokasi Anda", "Lat: " + location.getLatitude() + ", Lon: " + location.getLongitude());
} else {
Toast.makeText(Maps.this, "Lokasi perangkat tidak tersedia", Toast.LENGTH_SHORT).show();
}
});
} catch (SecurityException e) {
Log.e("Maps", "Security exception: " + e.getMessage());
}
}
private void searchLocation(String location) {
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
try {
List<Address> addresses = geocoder.getFromLocationName(location, 1);
if (addresses != null && !addresses.isEmpty()) {
Address address = addresses.get(0);
GeoPoint point = new GeoPoint(address.getLatitude(), address.getLongitude());
lastSearchedPoint = point;
mapView.getOverlays().clear();
addMarker(point, location, address.getAddressLine(0));
mapView.getController().setCenter(point);
mapView.getController().setZoom(15.0);
mapView.invalidate();
Toast.makeText(this, "Lokasi ditemukan: " + location, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Lokasi tidak ditemukan", Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "Terjadi kesalahan: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
private void addMarker(GeoPoint point, String title, String snippet) {
Marker marker = new Marker(mapView);
marker.setPosition(point);
marker.setTitle(title);
marker.setSnippet(snippet);
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
mapView.getOverlays().add(marker);
}
private void saveLocationToServer(double latitude, double longitude, String description) {
new SaveLocationTask().execute(idReport, latitude, longitude, description);
}
private class SaveLocationTask extends AsyncTask<Object, Void, JSONObject> {
@Override
protected JSONObject doInBackground(Object... params) {
int idReport = (int) params[0];
double latitude = (double) params[1];
double longitude = (double) params[2];
String description = (String) params[3];
try {
URL url = new URL(API_URL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
String data = "id_report=" + idReport + "&latitude=" + latitude + "&longitude=" + longitude + "&description=" + description;
OutputStream os = connection.getOutputStream();
os.write(data.getBytes());
os.flush();
os.close();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
return new JSONObject(response.toString());
} catch (Exception e) {
Log.e("Maps", "Error: " + e.getMessage());
return null;
}
}
@Override
protected void onPostExecute(JSONObject result) {
if (result != null) {
try {
String status = result.getString("status");
if ("success".equals(status)) {
String kode = result.getString("kode");
Intent intent = new Intent(Maps.this, Kode.class);
intent.putExtra("kode", kode);
startActivity(intent);
finish();
} else {
String message = result.getString("message");
Toast.makeText(Maps.this, message, Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Toast.makeText(Maps.this, "Terjadi kesalahan.", Toast.LENGTH_SHORT).show();
}
}
}
}
Nah, pada kode diatas merupakan penjelasan singkat dan penting mengenai fitur utama dari aplikasi LaporIN, jika sobat programmer ingin mengotak atik kode lengkapnya bisa download disini Project Aplikasi LaporIN [Sudah include semua, dari database, api, dan skrip project] dan sobat programmer bisa memodifnya skrip laporIN sesuai dengan keinginan sobat. Berikut ini merupakan tampilan aplikasi LaporIN:
Posting Komentar