Baik, langkah pertama yang di lakukan tentunya membuat proyeknya terlebih dahulu. Proyek dalam tutorial ini diberikan nama com.gwnbs.proyek8. Supaya nantinya tidak kewalahan, kita buat dulu 5 buah icon melalui vector asset maker. Anda bisa melihat postingan khusus mengenai cara membuat vector icon pada halaman All Post ini. Berikut screenshoot yang memperlihatkan struktur dan penamaan folder dan file pada proyek ini, serta screenshoot aplikasinya saat di jalankan di emulator.
Gambar 1 : Menunjukan struktur dan penamaan folder dan file |
Berikutnya kita ke activity_main.xml, disini kita hanya menambahkan 2 komponen yaitu sebuah Listview dan Button floating. Karena disini saya memakai floating action Button, maka diperlukan untuk menambahkan library material implementation 'com.google.android.material:material:1.1.0' ke build.gradle (Module : app) lalu lakukan sync gradle. Berikut isi dari activity_main.xml :
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<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">
<ListView
android:id="@+id/itemsList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginBottom="50dp"
android:divider="@null"
android:dividerHeight="0dp"
android:paddingLeft="6dp"
android:paddingRight="6dp"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:backgroundTint="@android:color/holo_blue_dark"
android:clickable="true"
android:focusable="true"
android:src="@drawable/ic_tambah"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
tools:ignore="UnusedAttribute" />
</RelativeLayout>
<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">
<ListView
android:id="@+id/itemsList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginBottom="50dp"
android:divider="@null"
android:dividerHeight="0dp"
android:paddingLeft="6dp"
android:paddingRight="6dp"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:backgroundTint="@android:color/holo_blue_dark"
android:clickable="true"
android:focusable="true"
android:src="@drawable/ic_tambah"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
tools:ignore="UnusedAttribute" />
</RelativeLayout>
Selanjutnya kita perlu membuat 2 layout resource baru, yang mana kedua layout ini di fungsikan sebagai custom Listview dan custom AlertDialog. Untuk layout custom Listview diberikan nama daftar_todo.xml dan custom AlertDialog diberi nama custom_dialog_todo.xml. Berikut isi dari masing-masing file layout tersebut :
daftar_todo.xml :
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:ignore="ContentDescription,
UselessParent,UseCompoundDrawables,HardcodedText">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp">
<ImageView
android:id="@+id/delete"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
android:background="@drawable/ic_hapus" />
<LinearLayout
android:id="@+id/titleRow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:background="@drawable/ic_judul"
android:tint="@android:color/holo_blue_dark" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:text="Judul"
android:textAllCaps="false"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/dateRow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/titleRow"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:background="@drawable/ic_tanggal" />
<TextView
android:id="@+id/dateTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="8dp"
android:text="Tanggal"
android:textAllCaps="true"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/dateRow"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:background="@drawable/ic_waktu"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/timeTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="16dp"
android:text="Waktu"
android:textAllCaps="true"
android:textSize="12sp" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
<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"
tools:ignore="ContentDescription,
UselessParent,UseCompoundDrawables,HardcodedText">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp">
<ImageView
android:id="@+id/delete"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
android:background="@drawable/ic_hapus" />
<LinearLayout
android:id="@+id/titleRow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:background="@drawable/ic_judul"
android:tint="@android:color/holo_blue_dark" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:text="Judul"
android:textAllCaps="false"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/dateRow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/titleRow"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:background="@drawable/ic_tanggal" />
<TextView
android:id="@+id/dateTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="8dp"
android:text="Tanggal"
android:textAllCaps="true"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/dateRow"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:background="@drawable/ic_waktu"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/timeTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="16dp"
android:text="Waktu"
android:textAllCaps="true"
android:textSize="12sp" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
custom_dialog_todo.xml :
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@null"
android:dividerPadding="0dp"
android:orientation="vertical"
android:padding="10dp"
app:layout_constraintCircleRadius="8dp"
tools:ignore="UseCompoundDrawables,
ContentDescription,HardcodedText">
<LinearLayout
android:id="@+id/titleLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/ic_judul" />
<EditText
android:id="@+id/edit_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:hint="Tugas"
android:inputType="text"
tools:ignore="Autofill" />
</LinearLayout>
<LinearLayout
android:id="@+id/dateLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/titleLayout"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="@drawable/ic_tanggal"/>
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Tanggal"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/dateLayout"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="@drawable/ic_waktu" />
<TextView
android:id="@+id/time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Waktu"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp" />
</LinearLayout>
</RelativeLayout>
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@null"
android:dividerPadding="0dp"
android:orientation="vertical"
android:padding="10dp"
app:layout_constraintCircleRadius="8dp"
tools:ignore="UseCompoundDrawables,
ContentDescription,HardcodedText">
<LinearLayout
android:id="@+id/titleLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/ic_judul" />
<EditText
android:id="@+id/edit_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:hint="Tugas"
android:inputType="text"
tools:ignore="Autofill" />
</LinearLayout>
<LinearLayout
android:id="@+id/dateLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/titleLayout"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="@drawable/ic_tanggal"/>
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Tanggal"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/dateLayout"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="@drawable/ic_waktu" />
<TextView
android:id="@+id/time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Waktu"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp" />
</LinearLayout>
</RelativeLayout>
Berikutnya membuat sebuah java class baru sebagai setter dan getter item-item nya, yaitu id, title, date dan time dari aplikasi "Pengingat Tugas" yang segera akan kita selesaikan ini. file ini di beri nama ModelData.java. Berikut isi lengkap dari file ini :
ModelData.java :
package com.gwnbs.proyek8; public class ModelData { int id; private String title; private String date; private String time; ModelData(int id, String title, String date, String time) { this.id = id; this.title = title; this.date = date; this.time = time; } int getId() { return id; } String getTitle() { return title; } String getDate() { return date; } String getTime() { return time; } }
Langkah berikutnya adalah membuat file java adaptor untuk SQL Database nya. Seperti terlihat pada gambar 1 di atas, file database ini di beri nama DatabaseHelper.java. Fungsinya tentu untuk Create, Read, Update dan Delete (CRUD) data.
DatabaseHelper.java :
package com.gwnbs.proyek8; import android.annotation.SuppressLint; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; import java.util.ArrayList; public class DatabaseHelper extends SQLiteOpenHelper { private static final String TAG = "DatabaseHelper"; private static final String TABLE_NAME = "ToDo_Table"; private static final String COL1 = "ID"; private static final String COL2 = "Name"; private static final String COL3 = "Date"; private static final String COL4 = "Time"; public DatabaseHelper(Context context) { super(context, TABLE_NAME, null, 1); } @Override public void onCreate(SQLiteDatabase db) { String createTable = "CREATE TABLE " + TABLE_NAME + "(" + COL1 + " integer primary key, " + COL2 + " TEXT, " + COL3 + " DATE, " + COL4 + " TIME" + ")"; Log.d(TAG, "Creating table " + createTable); db.execSQL(createTable); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } //Memasukkan data ke database public boolean insertData(String item, String date, String time) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues contentValues = new ContentValues(); contentValues.put(COL2, item); contentValues.put(COL3, date); contentValues.put(COL4, time); Log.d(TAG, "insertData: Inserting " + item + " to " + TABLE_NAME); long result = db.insert(TABLE_NAME, null, contentValues); db.close(); return result != -1; } //Menghapus data dari database void deleteData(int id) { SQLiteDatabase db = this.getWritableDatabase(); db.delete(TABLE_NAME, COL1 + "=" + id, null); } //Memuat semua data ke listview public ArrayList<ModelData> getAllData() { ArrayList<ModelData> arrayList = new ArrayList<>(); SQLiteDatabase db = this.getReadableDatabase(); String query = "SELECT * FROM " + TABLE_NAME; @SuppressLint("Recycle") Cursor cursor = db.rawQuery(query, null); while (cursor.moveToNext()) { int id = cursor.getInt(0); String title = cursor.getString(1); String date = cursor.getString(2); String time = cursor.getString(3); ModelData modelData = new ModelData(id, title, date, time); arrayList.add(modelData); } db.close(); return arrayList; } }
Jika ada kode yang di tandai atau di garis bawahi warna merah (error), abaikan dulu sementara sampai implementasi pembuatan aplikasi ini selesai. Tahap selanjutnya adalah membuat file java adaptor untuk listview. Implementasi penghapusan data dari database juga di lakukan di dalam adaptor ini. File ini diberikan nama ItemAdapter.java. Berikut isi keseluruhan dari file ini.
ItemAdapter.java :
package com.gwnbs.proyek8; import android.annotation.SuppressLint; import android.content.Context; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; public class ItemAdapter extends BaseAdapter { private Context context; private ArrayList<ModelData> arrayList; public ItemAdapter(Context context, ArrayList<ModelData> arrayList) { super(); this.context = context; this.arrayList = arrayList; } @Override public int getCount() { return this.arrayList.size(); } @Override public Object getItem(int position) { return arrayList.get(position); } @Override public long getItemId(int position) { return position; } @SuppressLint({"ViewHolder", "InflateParams"}) @Override public View getView(int position, View convertView, final ViewGroup parent) { LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); assert layoutInflater != null; convertView = layoutInflater.inflate(R.layout.daftar_todo, null); TextView titleTextView = convertView.findViewById(R.id.title); TextView dateTextView = convertView.findViewById(R.id.dateTitle); TextView timeTextView = convertView.findViewById(R.id.timeTitle); final ImageView delImageView = convertView.findViewById(R.id.delete); delImageView.setTag(position); //Menghapus tugas dari database saat icon hapus di klik delImageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final int pos = (int) v.getTag(); deleteItem(pos); } }); ModelData modelData = arrayList.get(position); titleTextView.setText(modelData.getTitle()); dateTextView.setText(modelData.getDate()); timeTextView.setText(modelData.getTime()); return convertView; } //Menghapus tugas dari listview private void deleteItem(int position) { deleteItemFromDb(arrayList.get(position).getId()); arrayList.remove(position); notifyDataSetChanged(); } //Menghapus tugas dari database private void deleteItemFromDb(int id) { DatabaseHelper databaseHelper = new DatabaseHelper(context); try { databaseHelper.deleteData(id); toastMsg("Tugas di hapus"); } catch (Exception e) { e.printStackTrace(); toastMsg("Oppss.. ada kesalahan saat menghapus"); } } //Metode pesan toast private void toastMsg(String msg) { Toast t = Toast.makeText(context, msg, Toast.LENGTH_SHORT); t.setGravity(Gravity.CENTER,0,0); t.show(); } }
Dan kelas java terakhir yang perlu dibuat adalah kelas Notifikasi.java. Kelas ini tentunya berfungsi untuk menghantarkan notifikasi ke smartphone pengguna setelah waktu pengingat di setel. Setelah kelas ini di buat, pada AndroidManifest.xml kita perlu melakukan pembaharuan, yaitu dengan menambahkan kelas ini sebagai receiver, juga kita perlu menambahkan beberapa izin yang di perlukan. Berikut isi lengkap dari masing-masing file ini :
Notifikasi.java :
package com.gwnbs.proyek8; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class Notifikasi extends BroadcastReceiver { public static String NOTIFICATION_ID = "notification-id"; public static String NOTIFICATION = "notification"; public void onReceive(Context context, Intent intent) { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); Notification notification = intent.getParcelableExtra(NOTIFICATION); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { int importance = NotificationManager.IMPORTANCE_HIGH; NotificationChannel notificationChannel = new NotificationChannel(MainActivity.NOTIFICATION_CHANNEL_ID, "Pengingat", importance); assert notificationManager != null; notificationManager.createNotificationChannel(notificationChannel); } int id = intent.getIntExtra(NOTIFICATION_ID, 0); if (notificationManager != null) { notificationManager.notify(id, notification); } } }
AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gwnbs.proyek8">
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<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:label="Daftar Tugas | gwnbs.com">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".Notifikasi" />
</application>
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gwnbs.proyek8">
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<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:label="Daftar Tugas | gwnbs.com">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".Notifikasi" />
</application>
</manifest>
Sekali lagi jika ada kode yang di warnai merah atau error, di abaikan dulu. Kecuali jika sudah selesai tutorial ini dan ada yang di tandai error barulah silahkan mencari dimana letak kesalahan nya.
Baik, tahap terakhir MainActivity.java. Cukup banyak koding yang di lakukan pada file ini, jika di jelaskan bisa panjang urusan nya. Pada setiap metode kodingan sudah saya buat sedikit-sedikit penjelasan nya. Jadi langsung saja berikut isi keseluruhan pada file activity ini :
MainActivity.java :
import android.annotation.SuppressLint; import android.app.AlarmManager; import android.app.DatePickerDialog; import android.app.Notification; import android.app.PendingIntent; import android.app.TimePickerDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.animation.AlphaAnimation; import android.widget.AbsListView; import android.widget.DatePicker; import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; import android.widget.TimePicker; import android.widget.Toast; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.NotificationCompat; import com.google.android.material.floatingactionbutton.FloatingActionButton; import java.text.DateFormatSymbols; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import static java.util.Calendar.MINUTE; public class MainActivity extends AppCompatActivity { public static final String NOTIFICATION_CHANNEL_ID = "10001"; private final static String default_notification_channel_id = "default"; private static final String TAG = "MainActivity"; private DatabaseHelper databaseHelper; private ListView itemsListView; private FloatingActionButton fab; private AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.3F); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); databaseHelper = new DatabaseHelper(this); fab = findViewById(R.id.fab); itemsListView = findViewById(R.id.itemsList); populateListView(); onFabClick(); hideFab(); } //Mengatur notifikasi private void scheduleNotification(Notification notification, long delay) { Intent notificationIntent = new Intent(this, Notifikasi.class); notificationIntent.putExtra(Notifikasi.NOTIFICATION_ID, 1); notificationIntent.putExtra(Notifikasi.NOTIFICATION, notification); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager alarmManager = (AlarmManager) getLayoutInflater().getContext().getSystemService(Context.ALARM_SERVICE); if (alarmManager != null) { alarmManager.set(AlarmManager.RTC_WAKEUP, delay, pendingIntent); } } private Notification getNotification(String content) { //Saat notifikasi di klik di arahkan ke MainActivity Intent intent = new Intent(this, MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0); NotificationCompat.Builder builder = new NotificationCompat.Builder(getLayoutInflater().getContext(), default_notification_channel_id); builder.setContentTitle("Pengingat"); builder.setContentText(content); builder.setContentIntent(pendingIntent); builder.setAutoCancel(true); builder.setSmallIcon(R.drawable.ic_judul); builder.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND); builder.setChannelId(NOTIFICATION_CHANNEL_ID); builder.setPriority(NotificationCompat.PRIORITY_HIGH); return builder.build(); } //Memasukkan data ke database private void insertDataToDb(String title, String date, String time) { boolean insertData = databaseHelper.insertData(title, date, time); if (insertData) { try { populateListView(); toastMsg("Tugas di tambahkan"); } catch (Exception e) { e.printStackTrace(); } } else toastMsg("Opps.. terjadi kesalahan saat menyimpan!"); } //Mengambil seluruh data dari database ke listview private void populateListView() { try { ArrayList<ModelData> items = databaseHelper.getAllData(); ItemAdapter itemsAdopter = new ItemAdapter(this, items); itemsListView.setAdapter(itemsAdopter); itemsAdopter.notifyDataSetChanged(); } catch (Exception e) { e.printStackTrace(); } } //Menyembunyikan tombol floating tambah saat listview di scroll private void hideFab() { itemsListView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == SCROLL_STATE_IDLE) { fab.show(); }else{ fab.hide(); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } }); } private void onFabClick() { try { fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { v.startAnimation(buttonClick); showAddDialog(); } }); } catch (Exception e) { e.printStackTrace(); } } //Implementasi klik dari tombol tambah @SuppressLint("SimpleDateFormat") private void showAddDialog() { AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getLayoutInflater().getContext()); LayoutInflater inflater = this.getLayoutInflater(); @SuppressLint("InflateParams") final View dialogView = inflater.inflate(R.layout.custom_dialog_todo, null); dialogBuilder.setView(dialogView); final EditText judul = dialogView.findViewById(R.id.edit_title); final TextView tanggal = dialogView.findViewById(R.id.date); final TextView waktu = dialogView.findViewById(R.id.time); final long date = System.currentTimeMillis(); SimpleDateFormat dateSdf = new SimpleDateFormat("d MMMM"); String dateString = dateSdf.format(date); tanggal.setText(dateString); SimpleDateFormat timeSdf = new SimpleDateFormat("hh : mm a"); String timeString = timeSdf.format(date); waktu.setText(timeString); final Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(System.currentTimeMillis()); //Set tanggal tanggal.setOnClickListener(new View.OnClickListener() { @RequiresApi(api = Build.VERSION_CODES.N) @Override public void onClick(View v) { final DatePickerDialog datePickerDialog = new DatePickerDialog(getLayoutInflater().getContext(), new DatePickerDialog.OnDateSetListener() { @SuppressLint("SetTextI18n") @Override public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { String newMonth = getMonth(monthOfYear + 1); tanggal.setText(dayOfMonth + " " + newMonth); cal.set(Calendar.YEAR, year); cal.set(Calendar.MONTH, monthOfYear); cal.set(Calendar.DAY_OF_MONTH, dayOfMonth); } }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)); datePickerDialog.show(); datePickerDialog.getDatePicker().setMinDate(date); } }); //Set waktu waktu.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { TimePickerDialog timePickerDialog = new TimePickerDialog(getLayoutInflater().getContext(), new TimePickerDialog.OnTimeSetListener() { @Override public void onTimeSet(TimePicker view, int hourOfDay, int minute) { String time; @SuppressLint("DefaultLocale") String minTime = String.format("%02d", minute); if (hourOfDay >= 0 && hourOfDay < 12) { time = hourOfDay + " : " + minTime + " AM"; } else { if (hourOfDay != 12) { hourOfDay = hourOfDay - 12; } time = hourOfDay + " : " + minTime + " PM"; } waktu.setText(time); cal.set(Calendar.HOUR, hourOfDay); cal.set(Calendar.MINUTE, minute); cal.set(Calendar.SECOND, 0); Log.d(TAG, "onTimeSet: Time has been set successfully"); } }, cal.get(Calendar.HOUR), cal.get(MINUTE), false); timePickerDialog.show(); } }); dialogBuilder.setTitle("Buat tugas baru"); dialogBuilder.setPositiveButton("Tambah", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { String title = judul.getText().toString(); String date = tanggal.getText().toString(); String time = waktu.getText().toString(); if (title.length() != 0) { try { insertDataToDb(title, date, time); scheduleNotification(getNotification(title), cal.getTimeInMillis()); } catch (Exception e) { e.printStackTrace(); } } else { toastMsg("Oops, Gak bisa kosong tugas nya."); } } }); dialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { dialog.cancel(); } }); AlertDialog b = dialogBuilder.create(); b.show(); } //Metode pesan toast private void toastMsg(String msg) { Toast t = Toast.makeText(this, msg, Toast.LENGTH_SHORT); t.setGravity(Gravity.CENTER, 0,0); t.show(); } //Mengkonversi bulan dari huruf menjadi angka private String getMonth(int month) { return new DateFormatSymbols().getMonths()[month - 1]; } }
Begitu saja, silahkan langsung di publish ke Google Play Store. Sekian dan terima kasih! Jika ada pertanyaan silahkan di pertanyakan di kolom komentar atau kontak form yang ada di bilah samping kiri.
UPDATE !
Berhubung adanya permintaan repositori github untuk tutorial ini, repositori nya pun sudah dibuat dan dapat di lihat di https://github.com/DaltrayNababan/pengingat.tugas
apakah ada file nya biar makin mudah dipelajari, soalnya saya masih awam
ReplyDeleteapakah ada file nya biar makin mudah dipelajari, soalnya saya masih awam
ReplyDeleteTidak ada. Saya tidak pernah menyimpan project baik di online seperti github, ataupun saat membuat contoh tutorial file nya langsung saya hapus.
ReplyDeleteNanti seiring waktu juga jadi master kok, yg penting minat dan gak frustasi.
Kok tidak keluar kak notifnya
ReplyDeleteKenapa bisa begitu, coba diperiksa lagi kelas java notifikasi dan androidmanifest nya apakah sama seperti contoh. Trims
DeleteCoba bagi dong ka file mentahannya. Please
Deletebagi file mentahan nya dong ka,, Pleasee
DeleteBaik, akan saya buat ulang dulu proyek tutorial ini, nanti saya posting di github, nanti saya kabari ya.
DeleteSilahkan di cek repositori nya di https://github.com/DaltrayNababan/pengingat.tugas
Deleteapa ini bisa offline ya?
ReplyDeleteini apa bisa offline ya?saya coba waktu aplikasinya keluar notifnya tidak keluar waktu offline tapi kalau aplikasinya tetap berjalan notifikasi baru bisa berjalan
ReplyDeleteBisa gan. Nanti saya coba buatkan dulu repositori github untuk tutorial ini. Nanti silahkan di cek apakah sudah sama apa belum file-file dan isinya.
DeleteSilahkan di cek repositori nya di https://github.com/DaltrayNababan/pengingat.tugas
Deletekak mau tanya dong ini kalau formatnya jadi 24 jam gimana ya, bingung saya
ReplyDeletekak kalo tambah update jadi gimana?
ReplyDeletekalau nambah fitur edit gimana a kak ? saya coba olah sama tutor yang Contoh Sederhana Menggunakan SQLite Database Android (Aplikasi Catatan) gabisa kak
ReplyDeletekak mau tanya kok notifnya tidak ada suaranya ya
ReplyDeletekak kok di saya tidak ada suara dari notifnya ya
ReplyDeletesaya mau bertnya kak,, saya mencoba memodifikasi programnya dengan menambahkan inputan baru berupa catatan tapi ketika saya tambhkan kolom didatabase malah nama kolomnya tidak dikenali.
ReplyDeleteerrornya seperti ini :
table ToDo_Table has no column named Note in "INSERT INTO ToDo_Table(Date,Name,Note,Time)
kakk mau tanya ini pakai metode apa ya kak namanya
ReplyDelete