I'm creating an alarm clock application, and I'd like the homepage to have multiple Alarm objects shown, like the default Android clock application. To do this, I've been trying a ListView to create a button for each Alarm in an ArrayList of Alarms.
Debugging the crashes this caused, I've found that it can't implement Serializable or Parcelable due to the Context object within it, and thus I have no way to pass it from one activity to another. The ListView works fine when I create the alarms from the MainActivity itself, but when I use the CreateAlarmActivity that takes input from the user, the ListView won't pass through and it crashes.
I haven't found this precise problem on StackOverflow. This problem is close (Implementing Parcelable Class That Requires Context) but involves a database, which seems overkill for my needs.
If a ListView is even the best way to go about this, how should I pass the ListView between activities? If there's a better way, what would be a better implementation?
I apologise for the large amount of code. I'm not sure exactly what may prove relevant, so I've erred on the side of too much information rather than too little.
Code:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
ListView alarmListView;
ArrayList<Alarm> alarmList = new ArrayList<Alarm>();
int[] testArray = {0, 0, 0, 0, 0, 0, 0};
Alarm testAlarm = new Alarm("testAlarm", 6, 1, true, testArray, 10);
Alarm testAlarm2 = new Alarm("testAlarm2", 6, 1, true, testArray, 10);
AlarmAdapter alarmAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
alarmListView = (ListView) findViewById(R.id.alarmListView);
alarmList.add(testAlarm);
alarmList.add(testAlarm2);
alarmAdapter = new AlarmAdapter(MainActivity.this, alarmList);
alarmListView.setAdapter(alarmAdapter);
alarmAdapter.notifyDataSetChanged();
}
// Create alarm when user presses FAB on activity_main.xml.
public void createNewAlarm(View view) {
Intent createAlarmIntent = new Intent(this, CreateAlarmActivity.class);
createAlarmIntent.putExtra("alarmList", alarmList);
createAlarmIntent.putExtra("alarmAdapter", alarmAdapter);
startActivity(createAlarmIntent);
}
public void testAlarmActivated(View view){
Intent activateAlarmIntent = new Intent(this, AlarmActivatedActivity.class);
startActivity(activateAlarmIntent);
}
}
AlarmAdapter.java:
public class AlarmAdapter extends BaseAdapter implements Parcelable {
private Context alarmContext;
private ArrayList<Alarm> alarmList;
public AlarmAdapter(Context context, ArrayList arrayList) {
super();
alarmContext = context;
alarmList = arrayList;
}
public int getCount() {
return alarmList.size();
}
// getView method is called for each item of ListView
public View getView(int position, View view, ViewGroup parent) {
// inflate the layout for each item of listView
LayoutInflater inflater = (LayoutInflater) alarmContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.alarm_row, parent, false);
// get the reference of textView and button
TextView alarmName = (TextView) view.findViewById(R.id.title);
// Button alarmButton = (Button) view.findViewById(R.id.alarmButton);
// Set the title and button name
Alarm tempAlarm = alarmList.get(position);
alarmName.setText(tempAlarm.name);
// btnAction.setText("Action " + position);
// Click listener of button
/*btnAction.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Logic goes here
}
});*/
return view;
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
protected AlarmAdapter(Parcel in) {
alarmContext = (Context) in.readValue(Context.class.getClassLoader());
if (in.readByte() == 0x01) {
alarmList = new ArrayList<Alarm>();
in.readList(alarmList, Alarm.class.getClassLoader());
} else {
alarmList = null;
}
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(alarmContext);
if (alarmList == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeList(alarmList);
}
}
@SuppressWarnings("unused")
public static final Parcelable.Creator<AlarmAdapter> CREATOR = new Parcelable.Creator<AlarmAdapter>() {
@Override
public AlarmAdapter createFromParcel(Parcel in) {
return new AlarmAdapter(in);
}
@Override
public AlarmAdapter[] newArray(int size) {
return new AlarmAdapter[size];
}
};
}
Alarm.java:
public class Alarm implements Serializable {
String name;
int hour;
int minute;
boolean isPm;
int[] daysActive;
int snoozeTimer;
public Alarm(String startName, int startHour, int startMinute,
Boolean startIsPm, int[] startDaysActive, int startSnoozeTimer){
name = startName;
hour = startHour;
minute = startMinute;
isPm = startIsPm;
daysActive = startDaysActive;
snoozeTimer = startSnoozeTimer;
}
}
CreateAlarmActivity.java:
public class CreateAlarmActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_alarm);
alarmList = (ArrayList<Alarm>)getIntent().getSerializableExtra("alarmList");
alarmAdapter = (AlarmAdapter)getIntent().getParcelableExtra("alarmAdapter)");
}
int alarmHour = 6;
int alarmMinute = 0;
boolean isPm = false;
int snoozeTimer = 10;
int [] daysActive = new int[] {0, 0, 0, 0, 0, 0, 0};
ArrayList<Alarm> alarmList = new ArrayList<Alarm>();
AlarmAdapter alarmAdapter;
// Add one to the hour of the alarm.
public void changeHour(View view) {
Button btn = findViewById(R.id.buttonHours);
if (alarmHour == 12){
alarmHour = 0;
}
else {
alarmHour++;
}
btn.setText(Integer.toString(alarmHour));
}
// Add one to the minute of the alarm.
public void changeMinute(View view) {
Button btn = findViewById(R.id.buttonMinutes);
if (alarmMinute == 59) {
alarmMinute = 0;
}
else {
alarmMinute++;
}
if (alarmMinute < 10) {
// Ensure minute 1 becomes 01, e.g, 6:01 am.
btn.setText("0" + Integer.toString(alarmMinute));
}
else {
btn.setText(Integer.toString(alarmMinute));
}
}
public void changeAmPm(View view) {
Button btn = findViewById(R.id.buttonAmPm);
if (isPm == true) {
isPm = false;
btn.setText("am");
}
else {
isPm = true;
btn.setText("pm");
}
}
public void changeSnoozeTimer(View view) {
Button btn = findViewById(R.id.buttonSnoozeTimer);
if (snoozeTimer == 15){
snoozeTimer = 1;
}
else {
snoozeTimer++;
}
btn.setText(Integer.toString(snoozeTimer));
}
public void finishAlarm(View view){
EditText alarmName = findViewById(R.id.alarmName);
String name = alarmName.getText().toString();
Alarm alarm = new Alarm(name, alarmHour, alarmMinute, isPm, daysActive, snoozeTimer);
alarmList.add(alarm);
alarmAdapter.notifyDataSetChanged();
Intent finishAlarmIntent = new Intent(this, MainActivity.class);
finishAlarmIntent.putExtra("alarmList", alarmList);
startActivity(finishAlarmIntent);
}
public void cancelAlarm(View view){
Intent cancelAlarmIntent = new Intent(this, MainActivity.class);
startActivity(cancelAlarmIntent);
}
public void changeSunday(View view) {
Button btn = findViewById(R.id.buttonSunday);
if (daysActive[0] == 0){
daysActive[0] = 1;
// Source: https://stackoverflow.com/questions/2173936/how-to-set-background-color-of-a-view
// Credit goes to EddieB for the below line.
btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
}
else {
daysActive[1] = 0;
// Source: https://stackoverflow.com/questions/14802354/how-to-reset-a-buttons-background-color-to-default
// Credit goes to Ivo for the below line.
btn.getBackground().clearColorFilter();
}
}
public void changeMonday(View view) {
Button btn = findViewById(R.id.buttonMonday);
if (daysActive[1] == 0){
daysActive[1] = 1;
btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
}
else {
daysActive[1] = 0;
btn.getBackground().clearColorFilter();
}
}
public void changeTuesday(View view) {
Button btn = findViewById(R.id.buttonTuesday);
if (daysActive[2] == 0){
daysActive[2] = 1;
btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
}
else {
daysActive[2] = 0;
btn.getBackground().clearColorFilter();
}
}
public void changeWednesday(View view) {
Button btn = findViewById(R.id.buttonWednesday);
if (daysActive[3] == 0){
daysActive[3] = 1;
btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
}
else {
daysActive[3] = 0;
btn.getBackground().clearColorFilter();
}
}
public void changeThursday(View view) {
Button btn = findViewById(R.id.buttonThursday);
if (daysActive[4] == 0){
daysActive[4] = 1;
btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
}
else {
daysActive[4] = 0;
btn.getBackground().clearColorFilter();
}
}
public void changeFriday(View view) {
Button btn = findViewById(R.id.buttonFriday);
if (daysActive[5] == 0){
daysActive[5] = 1;
btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
}
else {
daysActive[5] = 0;
btn.getBackground().clearColorFilter();
}
}
public void changeSaturday(View view) {
Button btn = findViewById(R.id.buttonSaturday);
if (daysActive[6] == 0){
daysActive[6] = 1;
btn.getBackground().setColorFilter(Color.parseColor("#00ff00"), PorterDuff.Mode.DARKEN);
}
else {
daysActive[6] = 0;
btn.getBackground().clearColorFilter();
}
}
}