Reputation: 61
I'm creating a birthday reminder application, where the app starts on the main activity, goes to a new activity using intent and there the person selects the birthday, and the selected birth day, month and year is returned back to the main activity. Then in the main activity I've created a new button which retrieves all the information sent by the bday picker activity and tries to display it in a list activity every time I press a button.
The problem I'm facing is if once I run the app, the birthday gets recorded and is shown in the listview, but if I add another Birthday and try to display it in the listview,the previous record is removed and I'm left with only the present record.
What I exactly want to know is how can I add items in my listView so that all my previous birthdays are shown as well.
The code File Provided is as Follows: activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
android:weightSum="10"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
android:background="#97B252D5">
<TextView
android:id="@+id/editText"
android:layout_width="213dp"
android:layout_height="52dp"
android:ems="10"
android:fontFamily="sans-serif-black"
android:text="Remindro"
android:textAllCaps="true"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textSize="36sp"
android:textStyle="bold|italic"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.067"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/newEntry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#C1E6E60F"
android:fontFamily="sans-serif-black"
android:onClick="addNewEntry"
android:text="+ADD"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.88"
app:layout_constraintStart_toEndOf="@+id/editText"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.48" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="9"
android:background="#A071D4ED">
<ListView
android:id="@+id/list"
android:layout_width="410dp"
android:layout_height="596dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/viewRecord"
app:layout_constraintVertical_bias="0.0" />
<Button
android:id="@+id/viewRecord"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="#9650EC31"
android:onClick="viewRecord"
android:text="View Record"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/_dynamic"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
Code file for : MainActivity.java
package com.example.remindro;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.Calendar;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "";
ArrayList<String> listItems = new ArrayList<String>();
ArrayAdapter<String> adapter;
Calendar calendar = Calendar.getInstance();
int thisYear = calendar.get(Calendar.YEAR);
int thisMonth = calendar.get(Calendar.MONTH) + 1;
int thisDay = calendar.get(Calendar.DAY_OF_MONTH);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter=new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
listItems);
ListView records = (ListView) findViewById(R.id.list);
records.setAdapter(adapter);
}
public void addNewEntry(View v)
{
Intent adding = new Intent();
adding.setClass(this,addinglist.class);
startActivity(adding);
finish();
}
public void viewRecord(View v)
{
Intent receiver = getIntent();
int day = receiver.getIntExtra("day",0);
int month = receiver.getIntExtra("month",0);
int year = receiver.getIntExtra("year",0);
String name = receiver.getStringExtra("nameofperson");
String choice = receiver.getStringExtra("radio");
String mss = name + " has his " + choice + " on " + day + "/" + month + "/" + year;
//Toast.makeText(getApplicationContext(),mss,Toast.LENGTH_LONG).show();
int age = thisYear - year;
calendar.set(thisYear,thisMonth,thisDay);
Calendar calendar1 = Calendar.getInstance();
calendar1.set(thisYear,month,day);
long milliseconds1 = calendar.getTimeInMillis();
long milliseconds2 = calendar1.getTimeInMillis();
long diff = milliseconds2 - milliseconds1;
int noOfDays = (int) (diff / (24 * 60 * 60 * 1000));
String msg2 = "Turning " + age + " in " + noOfDays + "days!!";
// Toast.makeText(getApplicationContext(),msg2,Toast.LENGTH_LONG).show();
String finalMsg = mss + " " + msg2;
listItems.add(finalMsg);
adapter.notifyDataSetChanged();
}
}
activity_addinglist.xml
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#8AEC9F18"
tools:context=".addinglist">
<NumberPicker
android:id="@+id/day"
android:layout_width="97dp"
android:layout_height="131dp"
android:background="#B5EA1241"
android:scaleX="1.3"
android:scaleY="1.3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.298">
</NumberPicker>
<NumberPicker
android:id="@+id/month"
android:layout_width="97dp"
android:layout_height="131dp"
android:layout_marginStart="60dp"
android:layout_marginLeft="60dp"
android:background="#B5EA1241"
android:scaleX="1.3"
android:scaleY="1.3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/day"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.298">
</NumberPicker>
<NumberPicker
android:id="@+id/year"
android:layout_width="97dp"
android:layout_height="131dp"
android:layout_marginStart="56dp"
android:layout_marginLeft="56dp"
android:background="#B5EA1241"
android:scaleX="1.3"
android:scaleY="1.3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/month"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.298">
</NumberPicker>
<Button
android:id="@+id/submit"
android:layout_width="121dp"
android:layout_height="59dp"
android:layout_marginBottom="156dp"
android:background="#9A7CEF46"
android:onClick="addingEvent"
android:text="ADD Event"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<RadioGroup
android:id="@+id/typer"
android:layout_width="384dp"
android:layout_height="88dp"
app:layout_constraintBottom_toTopOf="@+id/submit"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.407"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/month"
app:layout_constraintVertical_bias="0.666">
<RadioButton
android:id="@+id/birthday"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Birthday"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<RadioButton
android:id="@+id/anniversary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Anniversary"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
</RadioGroup>
<EditText
android:id="@+id/name"
android:layout_width="413dp"
android:layout_height="53dp"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:hint="Enter the Name of the Person"
app:layout_constraintBottom_toTopOf="@+id/month"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.045"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.475" />
<EditText
android:id="@+id/resultshower"
android:layout_width="412dp"
android:layout_height="95dp"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.045"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/submit"
app:layout_constraintVertical_bias="0.518" />
</androidx.constraintlayout.widget.ConstraintLayout>
and addinglist.java
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.NumberPicker;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Switch;
public class addinglist extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_addinglist);
NumberPicker day = (NumberPicker) findViewById(R.id.day);
NumberPicker month = (NumberPicker) findViewById((R.id.month));
NumberPicker year = (NumberPicker) findViewById(R.id.year);
day.setMinValue(1);
day.setMaxValue(31);
month.setMinValue(1);
month.setMaxValue(12);
year.setMinValue(1950);
year.setMaxValue(2020);
}
public void addingEvent(View v)
{
String name;
EditText nameEntered = (EditText) findViewById(R.id.name);
name = nameEntered.getText().toString();
NumberPicker day = (NumberPicker) findViewById(R.id.day);
NumberPicker month = (NumberPicker) findViewById((R.id.month));
NumberPicker year = (NumberPicker) findViewById(R.id.year);
int day1 = day.getValue();
int month1 = month.getValue();
int year1 = year.getValue();
RadioGroup typer = (RadioGroup) findViewById(R.id.typer);
int selectedId = typer.getCheckedRadioButtonId();
RadioButton checked = (RadioButton) findViewById(selectedId);
String typee = checked.getText().toString();
EditText resultbox = (EditText) findViewById(R.id.resultshower);
String Finalmsg = name + " has his " + typee + " on " + day1 + "/" + month1 + "/" + year1;
resultbox.setText(Finalmsg);
Intent newintent = new Intent();
newintent.putExtra("nameofperson",name);
newintent.putExtra("day",day1);
newintent.putExtra("month",month1);
newintent.putExtra("year",year1);
newintent.putExtra("radio",typee);
newintent.setClass(this,MainActivity.class);
startActivity(newintent);
}
}
Thanks in advance for taking out time to solve this query.
Upvotes: 1
Views: 385
Reputation: 950
To get a result from an activity you should use startActivityForResult()
and onActivityResult()
APIs instead of startActivity()
.
You can learn it from this simple example given by tutorialspoint : https://www.tutorialspoint.com/how-to-manage-startactivityforresult-on-android
But latest Android developer documentation recommends us to use new Activity Result APIs for this.
To learn, you can refer to the Google's documentation : https://developer.android.com/training/basics/intents/result
And this write up by Wajahat Karim : https://wajahatkarim.com/2020/05/activity-results-api-onactivityresult/
I'm trying to give you an answer using this new Activity Result API.
First, you must add AndroidX Activity
and Fragment
libraries as dependencies.
app/build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.lakindu.birthdayreminder"
minSdkVersion 14
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
// Reference 1 : https://developer.android.com/training/basics/intents/result
// Reference 2 : https://wajahatkarim.com/2020/05/activity-results-api-onactivityresult/
implementation 'androidx.activity:activity:1.2.0-alpha04'
implementation 'androidx.fragment:fragment:1.3.0-alpha04'
}
I'm going to send a Parcelable
object from the addinglist activity to the MainActivity as the result.
This is the implementation of that Parcelable Event
class.
Event.java
import android.os.Parcel;
import android.os.Parcelable;
public class Event implements Parcelable {
// Name of the person
private String nameOfPerson;
// Day of month
// byte (8 bit) as the type, because day can only have a value from 1 to 31
private byte day;
// Month of year
// byte (8 bit) as the type, because month can only have a value from 1 to 12
private byte month;
// Year
// Short (16 bit) as the type, because year can only have a realistic A.D. year
private short year;
// Type of event
private String eventType;
// Constructor (auto-generated using Android Studio)
public Event(String nameOfPerson, byte day, byte month, short year, String eventType) {
this.nameOfPerson = nameOfPerson;
this.day = day;
this.month = month;
this.year = year;
this.eventType = eventType;
}
// Getters for each private member field (auto-generated using Android Studio)
public String getNameOfPerson() {
return nameOfPerson;
}
public byte getDay() {
return day;
}
public byte getMonth() {
return month;
}
public short getYear() {
return year;
}
public String getEventType() {
return eventType;
}
// Parcelable implementation (auto-generated using Android Studio)
protected Event(Parcel in) {
nameOfPerson = in.readString();
day = in.readByte();
month = in.readByte();
year = (short) in.readInt();
eventType = in.readString();
}
public static final Creator<Event> CREATOR = new Creator<Event>() {
@Override
public Event createFromParcel(Parcel in) {
return new Event(in);
}
@Override
public Event[] newArray(int size) {
return new Event[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(nameOfPerson);
dest.writeByte(day);
dest.writeByte(month);
dest.writeInt((int) year);
dest.writeString(eventType);
}
}
Then we have to create a class to encapsulate inputs given to addinglist activity from MainActivity (in this example there's none), and outputs returned from addinglist activity to MainActivity (Event Parcelable object).
This class is an ActivityResultContract, which is like a contract we give to the Android system to open a specific Activity, and get a result from it for us.
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import androidx.activity.result.contract.ActivityResultContract;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class GetEvent extends ActivityResultContract<Void, Event> {
@NonNull
@Override
public Intent createIntent(@NonNull Context context, Void input) {
// Create Intent that should be used to start addinglist activity for result
Intent intent = new Intent(context, addinglist.class);
// If you need to send any inputs to addinglist activity,
// you can put them in intent as extras.
// Eg: intent.putExtra("input", input)
// But for now we don't have to send any inputs to addinglist activity.
return intent;
}
@Override
public Event parseResult(int resultCode, @Nullable Intent intent) {
// Action is cancelled? Return null
if(Activity.RESULT_OK != resultCode) return null;
// No intent to get output? Return null
if(null == intent) return null;
// Successfully got result from addinglist activity
return intent.getExtras().getParcelable("output");
}
}
Here is how we launch the addinglist activity from MainActivity and get the result.
MainActivity.java
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import androidx.activity.ComponentActivity;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import java.util.ArrayList;
import java.util.Calendar;
public class MainActivity extends ComponentActivity {
private static final String TAG = "";
ArrayList<String> listItems = new ArrayList<String>();
ArrayAdapter<String> adapter;
Calendar calendar = Calendar.getInstance();
int thisYear = calendar.get(Calendar.YEAR);
int thisMonth = calendar.get(Calendar.MONTH) + 1;
int thisDay = calendar.get(Calendar.DAY_OF_MONTH);
// Holds the latest event received from addinglist activity
private Event mLatestEvent = null;
// Register a callback to be called on an event received from addinglist activity
private ActivityResultLauncher<Void> mGetEvent = registerForActivityResult(
// Instance that encapsulates input and output when starting addinglist activity for result
new GetEvent(),
// Callback to be called when event is received
new ActivityResultCallback<Event>() {
@Override
public void onActivityResult(Event result) {
// Save as latest event received
mLatestEvent = result;
}
}
);
private static final Void NO_INPUT = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter=new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
listItems);
ListView records = (ListView) findViewById(R.id.list);
records.setAdapter(adapter);
}
public void addNewEntry(View v)
{
// Launch addinglist activity to get an event
mGetEvent.launch(NO_INPUT);
}
public void viewRecord(View v)
{
// No latest event? Then nothing to add to list, just return.
if(null == mLatestEvent) return;
// Prepare string that is being added to the list.
// Using a StringBuilder as there are multiple number of immutable strings to be appended.
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(mLatestEvent.getNameOfPerson())
.append(" has his ")
.append(mLatestEvent.getEventType())
.append(" on ")
.append(mLatestEvent.getDay())
.append("/")
.append(mLatestEvent.getMonth())
.append("/")
.append(mLatestEvent.getYear());
String mss = stringBuilder.toString();
//Toast.makeText(getApplicationContext(),mss,Toast.LENGTH_LONG).show();
int age = thisYear - mLatestEvent.getYear();
calendar.set(thisYear,thisMonth,thisDay);
Calendar calendar1 = Calendar.getInstance();
calendar1.set(thisYear, mLatestEvent.getMonth(), mLatestEvent.getDay());
long milliseconds1 = calendar.getTimeInMillis();
long milliseconds2 = calendar1.getTimeInMillis();
long diff = milliseconds2 - milliseconds1;
int noOfDays = (int) (diff / (24 * 60 * 60 * 1000));
String msg2 = "Turning " + age + " in " + noOfDays + "days!!";
// Toast.makeText(getApplicationContext(),msg2,Toast.LENGTH_LONG).show();
String finalMsg = mss + " " + msg2;
listItems.add(finalMsg);
adapter.notifyDataSetChanged();
}
}
Note that MainActivity is a ComponentActivity
now. Not a AppCompatActivity.
Here is how to send the result from addinglist activity to MainActivity.
addinglist.java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.NumberPicker;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import androidx.appcompat.app.AppCompatActivity;
public class addinglist extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_addinglist);
NumberPicker day = (NumberPicker) findViewById(R.id.day);
NumberPicker month = (NumberPicker) findViewById((R.id.month));
NumberPicker year = (NumberPicker) findViewById(R.id.year);
day.setMinValue(1);
day.setMaxValue(31);
month.setMinValue(1);
month.setMaxValue(12);
year.setMinValue(1950);
year.setMaxValue(2020);
}
public void addingEvent(View v)
{
String name;
EditText nameEntered = (EditText) findViewById(R.id.name);
name = nameEntered.getText().toString();
NumberPicker day = (NumberPicker) findViewById(R.id.day);
NumberPicker month = (NumberPicker) findViewById((R.id.month));
NumberPicker year = (NumberPicker) findViewById(R.id.year);
byte day1 = (byte) day.getValue();
byte month1 = (byte) month.getValue();
short year1 = (short) year.getValue();
RadioGroup typer = (RadioGroup) findViewById(R.id.typer);
int selectedId = typer.getCheckedRadioButtonId();
RadioButton checked = (RadioButton) findViewById(selectedId);
String typee = checked.getText().toString();
EditText resultbox = (EditText) findViewById(R.id.resultshower);
String Finalmsg = name + " has his " + typee + " on " + day1 + "/" + month1 + "/" + year1;
resultbox.setText(Finalmsg);
// Prepare the result to output
Intent newintent = new Intent();
newintent.putExtra(
"output",
new Event(name, day1, month1, year1, typee)
);
// Set the result
setResult(Activity.RESULT_OK, newintent);
// Finish the addinglist activity.
// Then result will be sent to the MainActivity.
finish();
}
}
Here is the working app.
Upvotes: 1