Problem summary: I have a listView which stores a list of vocabulary in WordsToMemorize Class, a NotificationWorker Class and a NotificationReceiver Class for processing notifications. My aim is to tap an item (which for example is a word called "baseball") of the listView, and the item will fire a timePicker where I will set a specific time (say, 5 munites later) to fire a notification. The notification, when appearing, is supposed to show a title that goes:" Do you remeber this word: baseball ? ". The notification works properly when I fire only one notification, but if I fire a second notification immediately for another word like "apple", the title of first the second notification would both become " Do you remeber this word: apple? ". I mean by the time both notification comes up, the first one should be for "baseball" and the second one should be for "apple". The problem is that "baseball" has been replaced when I fired a second notification.
So is there a way to make notifications remember their specifics words?
Things I have tried: I tried to set a different notification id for each notification and that didn't work. I thought of generating a time tag fetching the current system time when "baseball" (or any other item in the listView) is tapped, and letting the notification manager to pair the time tag and "baseball", so that will be the identifier for "baseball" and hence the notification can remember the word. However this is much above my coding level and I didn't know how to achieve this in codes.
Below are my codes for reference:
WordsToMemorize Class
public class WordsToMemorize extends AppCompatActivity {
static String vocabularyToBeMemorized;
Calendar c;
WorkManager mWorkManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.words_to_memorize);
final ListView myVocabularyListview;
final ArrayAdapter myVocabularyArrayAdapter;
//findViewById
myVocabularyListview = findViewById(R.id.my_vocabulary_listview);
mWorkManager = WorkManager.getInstance();
//Initialize the adapter
myVocabularyArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, myVocabularyArrayList);
myVocabularyListview.setAdapter(myVocabularyArrayAdapter);
/**
* Let the user click on an item and set notification timings
*/
myVocabularyListview.setOnItemClickListener(new AdapterView.OnItemClickListener(){
public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
final String selectedMyVocabularyListviewItemValue=myVocabularyListview.getItemAtPosition(position).toString();
AlertDialog.Builder AlertDialog = new AlertDialog.Builder(WordsToMemorize.this);
AlertDialog .setTitle(getString(R.string.Choose_the_timing_to_recall_a_word));
AlertDialog .setCancelable(false);
AlertDialog .setView(R.layout.custom_alert_dialog_dictionary_providers);
//Time Picker Button
AlertDialog .setPositiveButton(getString(R.string.Customize_timing), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//I couldn't directly fetch the values of the myVocabularyListview items so I had to pass them to a dummy texView called "wordInputView" and then fetch them from there.
MainActivity.wordInputView.setText(selectedMyVocabularyListviewItemValue);
setCustomizedNotificationTiming();
}
});
//Cancel Button
AlertDialog .setNegativeButton(R.string.Cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog .create();
AlertDialog .show();
}
});
@Override
protected void onStart() {
super.onStart();
c = Calendar.getInstance();
}
// Helper Method
public void setCustomizedNotificationTiming() {
vocabularyToBeMemorized = MainActivity.wordInputView.getText().toString();
// on Time
new TimePickerDialog(this,
new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay,
int minute) {
c.set(Calendar.HOUR_OF_DAY, hourOfDay);
c.set(Calendar.MINUTE, minute);
long nowMillis = System.currentTimeMillis();
long millis = c.getTimeInMillis() - nowMillis;
if (c.before(Calendar.getInstance())) {
Toast.makeText(getApplicationContext(), getString(R.string.Hey_thats_too_early),Toast.LENGTH_LONG).show();
} else {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.TAIWAN);
Long scheduledDateInMilliSeconds=c.getTimeInMillis();
String FormattedScheduledDate = dateFormat.format(scheduledDateInMilliSeconds);
Toast.makeText(getApplicationContext(), getString(R.string.Will_send_the_notification_at) + FormattedScheduledDate + getString(R.string.blank_space),Toast.LENGTH_LONG).show();
OneTimeWorkRequest UserDefinedNotificationRequest = new OneTimeWorkRequest.Builder(NotificationWorker.class)
.addTag("UserDefinedNotificationTag" + " for " + vocabularyToBeMemorized)
.setInitialDelay(millis, TimeUnit.MILLISECONDS)
.build();
mWorkManager.enqueue(UserDefinedNotificationRequest);
}
}
},
c.get(Calendar.HOUR_OF_DAY),
c.get(Calendar.MINUTE),
false).show();
// on Date
new DatePickerDialog(this,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, monthOfYear);
c.set(Calendar.DAY_OF_MONTH, dayOfMonth);
}
},
c.get(Calendar.YEAR),
c.get(Calendar.MONTH),
c.get(Calendar.DAY_OF_MONTH)).show();
}
}
NotificationWorker Class
public class NotificationWorker extends Worker {
public NotificationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
showNotification("Hey I'm your worker", "Work is done");
return Result.success();
}
public int createID(){
Date now = new Date();
int id = Integer.parseInt(new SimpleDateFormat("ddHHmmssSS", Locale.TAIWAN).format(now));
return id;
}
private void showNotification(String task, String desc) {
RemoteViews collapsedNotificationView = new RemoteViews(getApplicationContext().getPackageName(),R.layout.custom_notification_normal_view);
collapsedNotificationView.setTextViewText(R.id.normal_notification_title,"Do you Remember this word:" + WordsToMemorize.vocabularyToBeMemorized + "?");
RemoteViews expandedNotificationView = new RemoteViews(getApplicationContext().getPackageName(),R.layout.custom_notification_expanded_view);
expandedNotificationView.setTextViewText(R.id.expanded_notification_title,"Do you Remember this word:" + WordsToMemorize.vocabularyToBeMemorized + "?");
Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(getApplicationContext());
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
Intent broadcastIntent = new Intent(getApplicationContext(), NotificationReceiver.class);
broadcastIntent.putExtra("vocabularyToBeMemorized", WordsToMemorize.vocabularyToBeMemorized);
PendingIntent actionIntent = PendingIntent.getBroadcast(getApplicationContext(),
0, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager manager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new
NotificationChannel("simplfiedcoding", "simplfiedcoding", NotificationManager.IMPORTANCE_DEFAULT);
manager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), "simplfiedcoding")
.setSmallIcon(R.mipmap.ic_launcher)
.setLights(Color.YELLOW , 1000 , 1000)
.setColor(Color.BLUE)
.setSound(Settings.System.DEFAULT_NOTIFICATION_URI)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true)
.setOnlyAlertOnce(true)
.setStyle(new NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(collapsedNotificationView)
.setCustomBigContentView(expandedNotificationView)
.setContentIntent(resultPendingIntent)
.addAction(R.mipmap.dictionary,"yes",actionIntent);
int id = createID();
manager.notify(id, builder.build());
}
}
NotificationReceiver Class
public class NotificationReceiver extends BroadcastReceiver{
@Override
public void onReceive(final Context context, Intent intent) {
final String vocabularyToBeMemorizedFromNotification = intent.getStringExtra("vocabularyToBeMemorized");
Intent launchMainActivityIntent = context.getPackageManager().getLaunchIntentForPackage("com.example.android.dictionaryalmighty2");
if (launchMainActivityIntent != null) {
context.startActivity(launchMainActivityIntent);//null pointer check in case package name was not found
}
// This is only for null pointer errors before the app is fully launched and loaded
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
Intent intent = new Intent(context.getApplicationContext(), ComboSearchActivity.class);
context.startActivity(intent);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
// Just plain methods to look up dictionaries
loadFirstDefaultDictionaries();
loadSecondDefaultDictionaries();
loadThirdDefaultDictionaries();
}
}, 1000);
}
}, 1000); //1 second delay
}