You are on page 1of 54

Bài tập TH LTDĐCB

Mục lục
Buổi 1: Lập trình OOP với JAVA 1
Buổi 2: Thiết kế giao diện 8
Buổi 3: Thiết kế giao diện và xử lý với RecyclerView 14
Buổi 4: Xây dựng ứng dụng quản lý danh bạ 21
Buổi 5,6: Xây dựng ứng dụng quản lý danh bạ với CSDL Sqlite 38
Buổi 7,8: Xây dựng ứng dụng với dữ liệu JSON 40
Buổi 9,10: Xây dựng ứng dụng nghe nhạc với Mediaplayer 46

1
Bài tập TH LTDĐCB

Buổi 1: Lập trình OOP với JAVA


Mục tiêu: Ôn tập kiến thức về lập trình hướng đối tượng (OOP) trong JAVA
Kiến thức: phát biểu được các kiến thức về OOP và triển khai với JAVA
Kỹ năng: làm quen các cấu trúc dạng tập hợp trong JAVA và xây dựng chương trình với
NetBean, Eclipse
Bài tập hướng dẫn giải:
Một đơn vị sản xuất gồm có các cán bộ là công nhân, kỹ sư, nhân viên. Mỗi cán bộ cần
quản lý các dữ liệu: Họ tên, tuổi, giới tính (nam, nữ, khác), địa chỉ.
● Cấp công nhân sẽ có thêm các thuộc tính riêng: Bậc (1 đến 10).
● Cấp kỹ sư có thuộc tính riêng: Nghành đào tạo.
● Các nhân viên có thuộc tính riêng: công việc.
Yêu cầu 1: Xây dựng các lớp CongNhan (Worker), KySu(Engineer), NhanVien(Staff) kế thừa
từ lớp CanBo (Officer).
Yêu cầu 2: Xây dựng lớp QLCB (quản lý cán bộ là một danh sách cán bộ) cài đặt các phương
thức thực hiện các chức năng sau:
● Thêm mới cán bộ.
● Tìm kiếm theo họ tên.
● Hiện thị thông tin về danh sách các cán bộ.
● Thoát khỏi chương trình.
Hướng dẫn chi tiết:
Lớp cán bộ. (Officer.java)
public class Officer {
protected String name;
protected int age;
protected String gender;
protected String address;

public Officer(String name, int age, String gender, String address) {


this.name = name;
this.age = age;
this.gender = gender;
this.address = address;
}

public String getName() {


return name;
}

public void setName(String name) {


this.name = name;
}

public int getAge() {


return age;
}

public void setAge(int age) {


this.age = age;
}

public String getGender() {


return gender;
}

public void setGender(String gender) {

Trang 1
Bài tập TH LTDĐCB

this.gender = gender;
}

public String getAddress() {


return address;
}

public void setAddress(String address) {


this.address = address;
}
}

Lớp nhân viên (Staff.java)


public class Staff extends Officer {
private String task;
public Staff(String name, int age, String gender, String address, String task) {
super(name, age, gender, address);
this.task = task;
}

public String getTask() {


return task;
}

public void setTask(String task) {


this.task = task;
}

@Override
public String toString() {
return "Staff{" +
"task='" + task + '\'' +
", name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", address='" + address + '\'' +
'}';
}
}

Lớp công nhân (Worker.java)


public class Worker extends Officer {
private int level;

public Worker(String name, int age, String gender, String address, int level) {
super(name, age, gender, address);
this.level = level;
}

public int getLevel() {


return level;
}

public void setLevel(int level) {


this.level = level;
}

@Override
public String toString() {
return "Worker{" +
"level=" + level +
", name='" + name + '\'' +

Trang 2
Bài tập TH LTDĐCB

", age=" + age +


", gender='" + gender + '\'' +
", address='" + address + '\'' +
'}';
}
}

Lớp kỹ sư (Engineer.java)
public class Engineer extends Officer {
private String branch;
public Engineer(String name, int age, String gender, String address, String branch) {
super(name, age, gender, address);
this.branch = branch;
}

public String getBranch() {


return branch;
}

public void setBranch(String branch) {


this.branch = branch;
}

@Override
public String toString() {
return "Engineer{" +
"branch='" + branch + '\'' +
", name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", address='" + address + '\'' +
'}';
}
}

Lớp quản lý cán bộ (ManagerOfficer.java)


public class ManagerOfficer {
private List<Officer> officers;

public ManagerOfficer() {
this.officers = new ArrayList<>();
}

public void addOfficer(Officer officer) {


this.officers.add(officer);
}

public List<Officer> searchOfficerByName(String name) {


return this.officers.stream().filter(o -> o.getName().contains(name)).collect(Collectors.toList());
}

public void showListInforOfficer() {


this.officers.forEach(o -> System.out.println(o.toString()));
}
}

Lớp Main
public class Main {

public static void main(String[] args) {

Trang 3
Bài tập TH LTDĐCB

Scanner scanner = new Scanner(System.in);


ManagerOfficer managerOfficer = new ManagerOfficer();
while (true) {
System.out.println("Application Manager Officer");
System.out.println("Enter 1: To insert officer");
System.out.println("Enter 2: To search officer by name: ");
System.out.println("Enter 3: To show information officers");
System.out.println("Enter 4: To exit:");
String line = scanner.nextLine();
switch (line) {
case "1": {
System.out.println("Enter a: to insert Enginner");
System.out.println("Enter b: to insert Worker");
System.out.println("Enter c: to insert Staff");
String type = scanner.nextLine();
switch (type) {
case "a": {
System.out.print("Enter name: ");
String name = scanner.nextLine();
System.out.print("Enter age:");
int age = scanner.nextInt();
System.out.print("Enter gender: ");
scanner.nextLine();
String gender = scanner.nextLine();
System.out.print("Enter address: ");
String address = scanner.nextLine();
System.out.print("Enter branch: ");
String branch = scanner.nextLine();
Officer engineer = new Engineer(name, age, gender, address, branch);
managerOfficer.addOfficer(engineer);
System.out.println(engineer.toString());
break;

}
case "b": {
System.out.print("Enter name: ");
String name = scanner.nextLine();
System.out.print("Enter age:");
int age = scanner.nextInt();
System.out.print("Enter gender: ");
scanner.nextLine();
String gender = scanner.nextLine();
System.out.print("Enter address: ");
String address = scanner.nextLine();
System.out.print("Enter level: ");
int level = scanner.nextInt();
Officer worker = new Worker(name, age, gender, address, level);
managerOfficer.addOfficer(worker);
System.out.println(worker.toString());
scanner.nextLine();
break;
}
case "c": {
System.out.print("Enter name: ");
String name = scanner.nextLine();
System.out.print("Enter age: ");
int age = scanner.nextInt();
System.out.print("Enter gender: ");
scanner.nextLine();
String gender = scanner.nextLine();
System.out.print("Enter address: ");
String address = scanner.nextLine();
System.out.print("Enter task: ");
String task = scanner.nextLine();

Trang 4
Bài tập TH LTDĐCB

Officer staff = new Staff(name, age, gender, address, task);


managerOfficer.addOfficer(staff);
System.out.println(staff.toString());
break;
}
default:
System.out.println("Invalid");
break;
}
break;
}
case "2": {
System.out.print("Enter name to search: ");
String name = scanner.nextLine();
managerOfficer.searchOfficerByName(name).forEach(officer -> {
System.out.println(officer.toString());
});
break;
}
case "3": {
managerOfficer.showListInforOfficer();
break;
}
case "4": {
return;
}
default:
System.out.println("Invalid");
continue;
}

}
}

Bài tập về nhà:


Bài 1
Một thư viện cần quản lý các tài liệu bao gồm Sách, Tạp chí, Báo. Mỗi tài liệu gồm có các
thuộc tính sau: Mã tài liệu (Mã tài liệu là duy nhất), Tên nhà xuất bản, số bản phát hành.
● Các loại sách cần quản lý thêm các thuộc tính: tên tác giả, số trang.
● Các tạp chí cần quản lý thêm: Số phát hành, tháng phát hành.
● Các báo cần quản lý thêm: Ngày phát hành.
Yêu cầu 1: Xây dựng các lớp để quản lý tài liệu cho thư viện một cách hiệu quả.
Yêu cầu 2: Xây dựng lớp QuanLySach có các chức năng sau
● Thêm mới tài liêu: Sách, tạp chí, báo.
● Xoá tài liệu theo mã tài liệu.
● Hiện thị thông tin về tài liệu.
● Tìm kiếm tài liệu theo loại: Sách, tạp chí, báo.
● Thoát khỏi chương trình.

Bài 2
Các thí sinh dự thi đại học bao gồm các thí sinh thi khối A, B, và khối C. Các thí sinh cần
quản lý các thông tin sau: Số báo danh, họ tên, địa chỉ, mức ưu tiên.
● Thí sinh thi khối A thi các môn: Toán, Lý, Hoá.

Trang 5
Bài tập TH LTDĐCB

● Thí sinh thi khối B thi các môn: Toán, Hoá, Sinh.
● Thí sinh thi khối C thi các môn: Văn, Sử, Địa.
Yêu cầu 1: Xây dựng các lớp để quản lý các thi sinh dự thi đại học.
Yêu cầu 2: Xây dựng lớp TuyenSinh có các chức năng:
● Thêm mới thí sinh.
● Hiện thị thông tin của thí sinh và khối thi của thí sinh.
● Tìm kiếm theo số báo danh.
● Thoát khỏi chương trình.

Trang 6
Bài tập TH LTDĐCB

Buổi 2: Thiết kế giao diện


Mục tiêu: Thiết kế giao diện cho ứng dụng Android với các layout và view cơ bản
Kiến thức: hiểu và xác định được các thuộc tính cơ bản của View và layout
Kỹ năng: vận dụng và triển khai thiết kế giao diện với Android Studio
Bài tập hướng dẫn:
Ứng dụng chia tiền Tip. Ứng dụng cho
phép bạn nhập vào số tiền của hoá đơn,
chọn tỉ lệ tiền Tip để lại cho nhà hàng đồng
thời chọn số người trong bàn ăn sau đó
ứng dụng sẽ dựa trên thông tin đã nhập sẽ
tiến hành chia tiền mà mỗi người cần phải
trả.
Yêu cầu:
● Thiết kế như hình bên.
● Thực hiện xử lý với yêu cầu chia
tiền.

Hướng dẫn chi tiết:

layout_activity.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"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"

Trang 7
Bài tập TH LTDĐCB

android:layout_height="match_parent"
tools:context=".MainActivity">

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:text="@string/wesplit"
android:textSize="32sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputLayout"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/textView"
app:layout_constraintTop_toBottomOf="@+id/textView">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etAmount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:hint="Amount" />
</com.google.android.material.textfield.TextInputLayout>

<RadioGroup
android:id="@+id/rgPercentage"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="@+id/textInputLayout"
app:layout_constraintStart_toStartOf="@+id/textView2"
app:layout_constraintTop_toBottomOf="@+id/textView2">

<RadioButton
android:id="@+id/rb10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="true"
android:buttonTint="@color/purple_700"
android:text="10%" />

<RadioButton
android:id="@+id/rb20"

Trang 8
Bài tập TH LTDĐCB

android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:buttonTint="@color/purple_700"
android:layout_weight="1"
android:text="20%" />

<RadioButton
android:id="@+id/rb30"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:buttonTint="@color/purple_700"

android:text="30%" />

<RadioButton
android:id="@+id/rb40"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:buttonTint="@color/purple_700"
android:layout_weight="1"
android:text="40%" />
</RadioGroup>

<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="HOW MUCH TIP DO YOU WANT TO LEAVE"
app:layout_constraintStart_toStartOf="@+id/textInputLayout"
app:layout_constraintTop_toBottomOf="@+id/textInputLayout" />

<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Number of people"
app:layout_constraintStart_toStartOf="@+id/rgPercentage"
app:layout_constraintTop_toBottomOf="@+id/rgPercentage" />

<Spinner
android:id="@+id/spPeople"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:entries="@array/data"
android:textAlignment="textEnd"
app:layout_constraintBottom_toBottomOf="@+id/textView3"
app:layout_constraintEnd_toEndOf="@+id/rgPercentage"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@+id/textView3"
app:layout_constraintTop_toTopOf="@+id/textView3" />

<com.google.android.material.textfield.TextInputLayout

Trang 9
Bài tập TH LTDĐCB

android:id="@+id/textInputLayout2"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="@+id/spPeople"
app:layout_constraintStart_toStartOf="@+id/textView3"
app:layout_constraintTop_toBottomOf="@+id/textView3">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etResult"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:textColor="@color/purple_700"
android:text="Result : 0.00 / person" />
</com.google.android.material.textfield.TextInputLayout>

<Button
android:id="@+id/btCalc"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:padding="22dp"
android:text="Calculator"
app:layout_constraintEnd_toEndOf="@+id/textInputLayout2"
app:layout_constraintStart_toStartOf="@+id/textInputLayout2"
app:layout_constraintTop_toBottomOf="@+id/textInputLayout2" />

</androidx.constraintlayout.widget.ConstraintLayout>

string.xml
<resources>
<string name="app_name">Ten_sinh_vien</string>
<string name="wesplit">Wesplit</string>
<string-array name="data">
<item>2 people</item>
<item>3 people</item>
<item>4 people</item>
<item>5 people</item>
<item>6 people</item>
</string-array>
</resources>
MainActivity.java
public class MainActivity extends AppCompatActivity {

Button btCalc;
TextInputEditText etAmount, etResult;
RadioGroup rgPercentage;
Spinner spPeople;

int numberPeople = 0;
double tipPercentage = 0.1;
double amount = 0.0;

Trang 10
Bài tập TH LTDĐCB

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

etAmount = findViewById(R.id.etAmount);
etAmount.requestFocus();
etResult = findViewById(R.id.etResult);
rgPercentage = findViewById(R.id.rgPercentage);
rgPercentage.setOnCheckedChangeListener(new
RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
tipPercentage = getTipPercentage(i);
}
});

spPeople = findViewById(R.id.spPeople);
spPeople.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
numberPeople = getNumberPeople(i);
}

@Override
public void onNothingSelected(AdapterView<?> adapterView) {

}
});

btCalc = findViewById(R.id.btCalc);
btCalc.setOnClickListener(view -> {
double result = getAmountForPerson();
NumberFormat defaultFormat = NumberFormat.getCurrencyInstance();
etResult.setText(" Result: " + defaultFormat.format(result) + "/ person" );
});
}

int getNumberPeople(int index){


String[] people = getResources().getStringArray(R.array.data);
return Integer.parseInt(people[index].split(" ")[0]);
}

double getTipPercentage(int id){


double tipPercent = 0.0;
switch (id){
case R.id.rb10:
tipPercent = 0.1;
break;
case R.id.rb20:
tipPercent = 0.2;
break;

Trang 11
Bài tập TH LTDĐCB

case R.id.rb30:
tipPercent = 0.3;
break;
case R.id.rb40:
tipPercent = 0.4;
break;
}
return tipPercent;
}

Bài tập về nhà:


Bài 1: Xây dựng lại giao diện trên với RelativeLayout, LinearLayout và xây dựng phương
thức tính Tip cho bài trên
Bài 2: Chỉ số khối cơ thể (BMI) là giá trị tính từ cân nặng và chiều cao của một người. Kết
quả đo chỉ số BMI có thể đưa ra gợi ý về tình trạng sức khoẻ của một người về sự phù hợp
của chiều cao và cân nặng của người đó.
Công thức tính BMI như sau:
BMI = W/ (h*h)
● BMI dưới 18.5 : Underweight ( nhẹ cân )
● BMI : 18.5 – 24.9 : Normal or Healthy Weigh (bình thường)
● BMI : 25.0 - 29.9 : Overweigh ( thừa cân)
● BMI : 30.0 & above: Obese ( béo phì)
Trong đó W là cân nặng tính bằng Kg và h là chiều cao tính bằng mét.
Yêu cầu :
● Xây dựng giao diện như hình 1
● Xây dựng hàm tính BMI và thiết kế giao diện thông báo như Hình 2

Hình 1 Hình 2

Trang 12
Bài tập TH LTDĐCB

Buổi 3: Thiết kế giao diện và xử lý với RecyclerView


Mục tiêu: Xây dựng được giao diện dạng danh sách(List), lưới (Grid), so le (StaggedGrid)
cũng như xử lý sự kiện với RecylerView
Kiến thức: hiểu và vận dụng các bước triển khai giao diện với RecyclerView
Kỹ năng: thành thạo các bước xây dựng giao diện phức tạp với Android Studio
Bài tập hướng dẫn:
Xây dựng ứng dụng hiển thị thông tin
về các quốc gia trên thế giới. Mỗi
quốc gia sẽ gồm các thông tin như
cờ của quốc gia, tên, thủ đô, dân số,
toạ độ và mô tả (các thông tin này
được cho trong file “Bai02.xlsx”. Yêu
cầu xây dựng giao diện như hình 1 và
xử lý sự kiện như hình 2

Hình 1 Hình 2
Hướng dẫn chi tiết
Country.java
public class Country {
int id;
String name;
int image;
long population;
String description;
double latitude;
double longitude;
String capital;
String independence;
String currency;

public Country(int id, String name, int image, long population, String description, double
latitude, double longitude, String capital, String independence, String currency) {
this.id = id;
this.name = name;
this.image = image;
this.population = population;
this.description = description;
this.latitude = latitude;
this.longitude = longitude;
this.capital = capital;
this.independence = independence;
this.currency = currency;

Trang 13
Bài tập TH LTDĐCB

public int getId() {


return id;
}

public void setId(int id) {


this.id = id;
}

public String getName() {


return name;
}

public void setName(String name) {


this.name = name;
}

public long getPopulation() {


return population;
}

public void setPopulation(long population) {


this.population = population;
}

public String getDescription() {


return description;
}

public void setDescription(String description) {


this.description = description;
}

public double getLatitude() {


return latitude;
}

public void setLatitude(double latitude) {


this.latitude = latitude;
}

public double getLongitude() {


return longitude;
}

public void setLongitude(double longitude) {


this.longitude = longitude;
}

public String getCapital() {


return capital;
}

public void setCapital(String capital) {

Trang 14
Bài tập TH LTDĐCB

this.capital = capital;
}

public int getImage() {


return image;
}

public void setImage(int image) {


this.image = image;
}

public String getIndependence() {


return independence;
}

public void setIndependence(String independence) {


this.independence = independence;
}

public String getCurrency() {


return currency;
}

public void setCurrency(String currency) {


this.currency = currency;
}
}

country_row.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="wrap_content">

<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/imgFlag"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:src="@drawable/estonia"
app:civ_border_color="#3F51B5"
app:civ_border_width="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/txName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:text="TextView"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="@+id/imgFlag"
app:layout_constraintTop_toTopOf="parent" />

Trang 15
Bài tập TH LTDĐCB

<TextView
android:id="@+id/txCapital"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:text="TextView"
android:textStyle="italic"
app:layout_constraintBottom_toTopOf="@+id/txPopulation"
app:layout_constraintStart_toEndOf="@+id/imgFlag"
app:layout_constraintTop_toBottomOf="@+id/txName" />

<TextView
android:id="@+id/txPopulation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginBottom="4dp"
android:text="TextView"
android:textStyle="italic"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/imgFlag" />

<TextView
android:id="@+id/txLatLong"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:text="TextView"
android:textStyle="italic"
app:layout_constraintBottom_toBottomOf="@+id/txPopulation"
app:layout_constraintEnd_toEndOf="parent" />

<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
app:layout_constraintBottom_toBottomOf="@+id/txLatLong"
app:layout_constraintEnd_toStartOf="@+id/txLatLong"
app:layout_constraintTop_toTopOf="@+id/txLatLong"
app:srcCompat="@drawable/ic_baseline_map_24" />
</androidx.constraintlayout.widget.ConstraintLayout>

CountryAdapter.java
public class CountryAdapter extends RecyclerView.Adapter<CountryAdapter.CountryVH> {
ArrayList<Country> countries;
Listener listener;
public CountryAdapter(Listener listener, ArrayList<Country> countries) {
this.listener = listener;
this.countries = countries;
}
@NonNull
@Override
public CountryVH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.country_row,
parent,false);
return new CountryVH(view);
}
@Override
public void onBindViewHolder(@NonNull CountryVH holder, int position) {
Country country = countries.get(position);
holder.imgFlag.setImageResource(country.getImage());
holder.txName.setText(country.getName());

Trang 16
Bài tập TH LTDĐCB

holder.txCapital.setText("Capital: ".concat(country.getCapital()));

NumberFormat numberFormatter = NumberFormat.getInstance(Locale.US);


numberFormatter.setMinimumFractionDigits(2);
holder.txPopulation.setText("Population:
".concat(numberFormatter.format(country.getPopulation())));
holder.txLatLong.setText("Lat:
".concat(numberFormatter.format(country.getLatitude())).concat(" \nLong:
".concat(numberFormatter.format(country.getLongitude()))));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listener.onItemListener(country);
}
});
}
@Override
public int getItemCount() {
return countries.size();
}
class CountryVH extends RecyclerView.ViewHolder{
CircleImageView imgFlag;
TextView txName, txCapital, txPopulation, txLatLong;

public CountryVH(@NonNull View itemView) {


super(itemView);
imgFlag = itemView.findViewById(R.id.imgFlag);
txName = itemView.findViewById(R.id.txName);
txCapital = itemView.findViewById(R.id.txCapital);
txPopulation = itemView.findViewById(R.id.txPopulation);
txLatLong = itemView.findViewById(R.id.txLatLong);

}
}
interface Listener{
void onItemListener(Country country);
}
}

activity_main.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"
tools:context=".MainActivity">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvCountries"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"

Trang 17
Bài tập TH LTDĐCB

app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="@layout/country_row" />
</androidx.constraintlayout.widget.ConstraintLayout>

Mainactivity.java
public class MainActivity extends AppCompatActivity implements CountryAdapter.Listener {

RecyclerView rvCountries;
ArrayList<Country> countries;
CountryAdapter countryAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

rvCountries = findViewById(R.id.rvCountries);
countries = App.initDataForCountry();
countryAdapter = new CountryAdapter(MainActivity.this, countries);
rvCountries.setAdapter(countryAdapter);

rvCountries.setLayoutManager(new LinearLayoutManager(MainActivity.this,
LinearLayoutManager.VERTICAL, false));
rvCountries.addItemDecoration(new DividerItemDecoration(MainActivity.this,
LinearLayoutManager.VERTICAL));
}

@Override
public void onItemListener(Country country) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle(country.getName());
builder.setIcon(getDrawable(country.getImage()));
builder.setMessage(country.getDescription());
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();

}
}

Bài tập về nhà


Bài 1: Xây dựng lại Ứng dụng trên với kiểu hiển thị dạng lưới (Grid) trong RecyclerVỉew
Bài 2: Xây dựng ứng dụng quản lý danh bạ với dữ liệu “Bai2_1.xlsx” và dữ liệu hình ảnh cho
sẵn với giao diện gợi ý như sau:

Trang 18
Bài tập TH LTDĐCB

Trang 19
Bài tập TH LTDĐCB

Buổi 4: Xây dựng ứng dụng quản lý danh bạ


Mục tiêu: Xây dựng ứng dụng với các chức năng như CRUD
Kiến thức: vận dụng được các kiến thức liên quan đến recyclerView, menu, listener
Kỹ năng: thành thạo các bước xây dựng giao diện phức tạp với Android Studio
Bài tập hướng dẫn
Xây dựng ứng dụng quản lý danh bạ với các chức năng như:
● C- create R-read U-update D-delete
● tìm kiếm
● sắp xếp.

Hinh 1 HÌnh 2 Hình 3 Hình 4

Hình 5 Hình 6

Trang 20
Bài tập TH LTDĐCB

Hình 7 Hình 8 Hình 9


Hướng dẫn chi tiết
Hình 1: Thực hiện chức năng hiển thị danh sách danh bạ - sử dụng lại bài tập số 2 của
buổi 3
Hình 2: Thực hiện chức năng xem thông tin chi tiết của danh bạ
Giao diện:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:id="@+id/bottomInfo"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto">

<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/purple_500"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<ImageButton
android:id="@+id/cancelBtn"
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_close_24"
android:tint="@android:color/white" />

<TextView
android:id="@+id/nameToolbar"
android:layout_width="0dp"
android:layout_height="wrap_content"

Trang 21
Bài tập TH LTDĐCB

android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:layout_weight="1"
android:text="Information"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textColor="@android:color/white" />

<ImageButton
android:id="@+id/editBtn"
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_create_24"
android:tint="@android:color/white" />

<ImageButton
android:id="@+id/deleteBtn"
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_delete_24"
android:tint="@android:color/white" />

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout">

<LinearLayout
android:id="@+id/profileLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">

<ImageView
android:id="@+id/userImage"
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:src="@drawable/valkema" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:orientation="vertical">

Trang 22
Bài tập TH LTDĐCB

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">

<TextView
android:id="@+id/fullName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Name"

android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Full name"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
/>

</LinearLayout>

</LinearLayout>

</LinearLayout>
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginStart="60dp"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#e6e6e6" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

Trang 23
Bài tập TH LTDĐCB

android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:orientation="horizontal">

<ImageButton
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_phone_android_24" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">

<TextView
android:id="@+id/txPhone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(000) 000-000"

android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />

<TextView
android:id="@+id/typeOfNumber1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Mobile"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
/>

</LinearLayout>

</LinearLayout>

</LinearLayout>

Trang 24
Bài tập TH LTDĐCB

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginStart="60dp"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#e6e6e6" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

<ImageButton
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_email_24"
/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:orientation="vertical">

<TextView
android:id="@+id/txEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="email@email.com"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
/>

<TextView
android:id="@+id/emailType1"
android:layout_width="match_parent"

Trang 25
Bài tập TH LTDĐCB

android:layout_height="wrap_content"
android:text="Personal"
android:textAppearance="@style/TextAppearance.AppCompat.Small" />

</LinearLayout>

</LinearLayout>

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginStart="60dp"
android:layout_marginBottom="10dp"
android:orientation="horizontal">

<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#e6e6e6" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

<ImageButton
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_cake_24"
/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_marginStart="10dp"
android:orientation="vertical">

<TextView
android:id="@+id/txBirthday"

Trang 26
Bài tập TH LTDĐCB

android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ABC Street Sector 1/2"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Birthday"
android:textAppearance="@style/TextAppearance.AppCompat.Small" />

</LinearLayout>

</LinearLayout>

</LinearLayout>

</LinearLayout>

</LinearLayout>

Xử lý:
public class InfoDialogBottomSheet extends BottomSheetDialog {
TextView txFullName, txPhone, txEmail,txBirthday;
ImageView imImage;
ImageButton btnClose, btnEdit, btnDelete;
Contact contact;
ActivityResultLauncher mLauncher;
ContactAdapter contactAdapter;
public InfoDialogBottomSheet(@NonNull Context context, Contact contact,
ActivityResultLauncher mLauncher, ContactAdapter contactAdapter) {
super(context);
this.contact = contact;
this.mLauncher = mLauncher;
this.contactAdapter = contactAdapter;
}

public void findView(){


View view = getLayoutInflater().inflate(R.layout.activity_info, null);

txFullName = view.findViewById(R.id.fullName);
txPhone = view.findViewById(R.id.txPhone);
txEmail = view.findViewById(R.id.txEmail);
txBirthday = view.findViewById(R.id.txBirthday);
imImage = view.findViewById(R.id.userImage);
btnClose = view.findViewById(R.id.cancelBtn);
btnClose.setOnClickListener( v -> {

Trang 27
Bài tập TH LTDĐCB

this.dismiss();
});
btnEdit = view.findViewById(R.id.editBtn);
btnEdit.setOnClickListener( v -> {
Intent intent = new Intent(getContext(), AddEditActivity.class);
intent.putExtra("contact", contact);
intent.putExtra("flag", 2);
mLauncher.launch(intent);
dismiss();
});

btnDelete = view.findViewById(R.id.deleteBtn);
btnDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("Contacts");
builder.setMessage("Delete ".concat(contact.getFullName()).concat(" ?"));
builder.setNegativeButton("No", (dialogInterface, i) -> {
dialogInterface.cancel();

});
builder.setPositiveButton("Yes", (dialogInterface, i) -> {
contactAdapter.deleteContact(contact);
dialogInterface.dismiss();
dismiss();
});
AlertDialog alertDialog = builder.create();
alertDialog.show();

}
});

txFullName.setText(contact.getFullName());
txEmail.setText(contact.getEmail());
txPhone.setText(contact.getPhone());
txBirthday.setText(contact.getBirthday());
imImage.setImageResource(contact.getImage());

setContentView(view);
}

Hình 3: Thực hiện chức năng tìm kiếm danh ba


ContactAdapter.java
public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactVH>
implements Filterable {

Context context;
ArrayList<Contact> contacts;
ArrayList<Contact> contactsFilter;
Listener listener;

Trang 28
Bài tập TH LTDĐCB

public ContactAdapter(Listener listener, ArrayList<Contact> contacts) {


this.listener = listener;
this.contacts = contacts;
this.contactsFilter = contacts;
}

@NonNull
@Override
public ContactVH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_contact,
parent,false);
return new ContactVH(view);
}

@Override
public void onBindViewHolder(@NonNull ContactVH holder, int position) {
Contact contact = contactsFilter.get(position);
holder.txName.setText(contact.getfName().concat(" ").concat(contact.lName));
holder.txPhone.setText(contact.getPhone());
holder.txEmail.setText(contact.getEmail());
if(contact.getImage() == 0){
holder.imgProfile.setImageResource(R.drawable.ic_baseline_circle_24);
}else {
holder.imgProfile.setImageResource(contact.getImage());
}

holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listener.OnItemListener(position,contact);
}
});

@Override
public int getItemCount() {
return contactsFilter.size();
}

@Override
public Filter getFilter() {
return new ContactFilter();
}

class ContactVH extends RecyclerView.ViewHolder{


TextView txName, txPhone, txEmail;
ImageView imgProfile;

public ContactVH(@NonNull View itemView) {


super(itemView);
txName = itemView.findViewById(R.id.txName);
txPhone = itemView.findViewById(R.id.txPhone);
txEmail = itemView.findViewById(R.id.txEmail);

Trang 29
Bài tập TH LTDĐCB

imgProfile = itemView.findViewById(R.id.imgProfile);
}
}

class ContactFilter extends Filter{

@Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
contactsFilter = contacts;
} else {
List<Contact> filteredList = new ArrayList<>();
for (Contact row : contacts) {
if (row.getfName().toLowerCase().contains(charString.toLowerCase()) ||
row.getPhone().contains(charSequence) || row.getlName().contains(charSequence)) {
filteredList.add(row);
}
}

contactsFilter = (ArrayList<Contact>) filteredList;


}

FilterResults filterResults = new FilterResults();


filterResults.values = contactsFilter;
return filterResults;
}

@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults)
{
contactsFilter= (ArrayList<Contact>) filterResults.values;
notifyDataSetChanged();
}
}

public void addContact(Contact contact){


contactsFilter.add(contact);
notifyDataSetChanged();
}

public void editContact(Contact contact, int pos){


contactsFilter.set(pos, contact);
notifyDataSetChanged();
}

public void deleteContact(int pos){


contactsFilter.remove(pos);
notifyDataSetChanged();
}

public void deleteContact(Contact contact){


contactsFilter.remove(contact);
notifyDataSetChanged();
}

Trang 30
Bài tập TH LTDĐCB

interface Listener{
void OnItemListener(int pos, Contact contact);
}
}

MainActvitity.java
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.main_mnu, menu);

SearchView searchView = (SearchView) menu.findItem(R.id.mnuSearch).getActionView();


searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
contactAdapter.getFilter().filter(query);
return false;
}

@Override
public boolean onQueryTextChange(String newText) {
contactAdapter.getFilter().filter(newText);

if(newText.isEmpty()){
fabAddContact.setVisibility(View.VISIBLE);
}else {
fabAddContact.setVisibility(View.INVISIBLE);
}
return false;
}
});

return true;
}

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if(item.getItemId() == R.id.mnuSort){
Collections.sort(contacts);
contactAdapter.notifyDataSetChanged();
}
if(item.getItemId() == R.id.mnuSearch){
Intent intent = new Intent(MainActivity.this, SearchActivity.class);
startActivity(intent);
}
return super.onOptionsItemSelected(item);
}

Hình 4: Thực hiện chức năng xoá danh bạ


Xử lý
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("Contacts");
builder.setMessage("Delete ".concat(contact.getFullName()).concat(" ?"));

Trang 31
Bài tập TH LTDĐCB

builder.setNegativeButton("No", (dialogInterface, i) -> {


dialogInterface.cancel();

});
builder.setPositiveButton("Yes", (dialogInterface, i) -> {
contactAdapter.deleteContact(contact);
dialogInterface.dismiss();
dismiss();
});
AlertDialog alertDialog = builder.create();
alertDialog.show();

HÌnh 5,6: Thực hiện chức năng Thêm / Cập nhật danh bạ
Giao diện
<?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"
tools:context=".AddEditActivity">

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilFname"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:hint="First name"

app:startIconDrawable="@drawable/ic_baseline_info_24"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edFirstName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Tom"
android:inputType="textPersonName" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilLname"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
app:startIconDrawable="@drawable/ic_baseline_info_24"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="Last name"

Trang 32
Bài tập TH LTDĐCB

app:layout_constraintEnd_toEndOf="@+id/tilFname"
app:layout_constraintStart_toStartOf="@+id/tilFname"
app:layout_constraintTop_toBottomOf="@+id/tilFname">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edLastName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Vu"
android:inputType="textPersonName" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilEmail"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
app:startIconDrawable="@drawable/ic_baseline_email_24"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="Email"

app:layout_constraintEnd_toEndOf="@+id/tilLname"
app:layout_constraintStart_toStartOf="@+id/tilLname"
app:layout_constraintTop_toBottomOf="@+id/tilLname">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"
android:text="vutom@gmail.com"
/>
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilPhone"
app:startIconDrawable="@drawable/ic_baseline_phone_android_24"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="Phone"
app:layout_constraintEnd_toEndOf="@+id/tilEmail"
app:layout_constraintStart_toStartOf="@+id/tilEmail"
app:layout_constraintTop_toBottomOf="@+id/tilEmail">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edPhone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:text="0972277977"/>
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout

Trang 33
Bài tập TH LTDĐCB

android:id="@+id/tilBirthday"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
app:startIconDrawable="@drawable/ic_baseline_cake_24"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
app:layout_constraintEnd_toEndOf="@+id/tilPhone"
app:layout_constraintStart_toStartOf="@+id/tilPhone"
app:layout_constraintTop_toBottomOf="@+id/tilPhone"
android:hint="Birthday">

<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="false"
android:id="@+id/edBirthday"
android:text="01/01/1980"/>
</com.google.android.material.textfield.TextInputLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

Xử lý
public class AddEditActivity extends AppCompatActivity {
TextInputLayout tifName, tilName, tiEmail, tiPhone, tiBirthday;
TextInputEditText edfName, edlName, edEmail, edPhone, edBirthday;
int mYear, mMonth, mDay;
int flag;
Contact contactEdit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_edit);

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

tifName = findViewById(R.id.tilFname);
tilName = findViewById(R.id.tilLname);
tiEmail = findViewById(R.id.tilEmail);
tiPhone = findViewById(R.id.tilPhone);
tiBirthday = findViewById(R.id.tilBirthday);

edfName = findViewById(R.id.edFirstName);
edlName = findViewById(R.id.edLastName);
edEmail = findViewById(R.id.edEmail);
edPhone = findViewById(R.id.edPhone);
edBirthday = findViewById(R.id.edBirthday);

Intent intent = getIntent();


flag = intent.getIntExtra("flag", 0);
if(flag == 1){
getSupportActionBar().setTitle(R.string.add);

Trang 34
Bài tập TH LTDĐCB

}else {
getSupportActionBar().setTitle(R.string.edit);
contactEdit = (Contact) intent.getSerializableExtra("contact");
edfName.setText(contactEdit.getfName());
edlName.setText(contactEdit.getlName());
edEmail.setText(contactEdit.getEmail());
edPhone.setText(contactEdit.getPhone());
edBirthday.setText(contactEdit.getBirthday());
}

edBirthday.setOnClickListener(view -> {
if (view == edBirthday) {
final Calendar calendar = Calendar.getInstance ();
mYear = calendar.get ( Calendar.YEAR );
mMonth = calendar.get ( Calendar.MONTH );
mDay = calendar.get ( Calendar.DAY_OF_MONTH );

//show dialog
DatePickerDialog datePickerDialog = new DatePickerDialog ( AddEditActivity.this,
new DatePickerDialog.OnDateSetListener () {
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {

edBirthday.setText ( dayOfMonth + "/" + String.format("%02d",month+1) + "/"


+ year );
}
}, mYear, mMonth, mDay );
datePickerDialog.show ();
}
});
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.save_mnu, menu);
return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if(item.getItemId() == R.id.mnuSave){
if(edfName.getText().toString().isEmpty()
||edlName.getText().toString().isEmpty()
||edEmail.getText().toString().isEmpty()
||edPhone.getText().toString().isEmpty()
||edBirthday.getText().toString().isEmpty()){
tifName.setError("Not null");
tilName.setError("Not null");
tiEmail.setError("Not null");
tiPhone.setError("Not null");
tiBirthday.setError("Not null");
return false;
}else {

Trang 35
Bài tập TH LTDĐCB

if(flag == 1){
Contact contact = new Contact(new Random().nextInt(9999),
edfName.getText().toString(),
edlName.getText().toString(),
0,
edPhone.getText().toString(),
edEmail.getText().toString(),
edBirthday.getText().toString());

Intent intent = new Intent();


intent.putExtra("contact", contact);
intent.putExtra("flag", 1);
setResult(RESULT_OK, intent);
finish();
}else {
Contact contact = new Contact(contactEdit.getId(),
edfName.getText().toString(),
edlName.getText().toString(),
contactEdit.getImage(),
edPhone.getText().toString(),
edEmail.getText().toString(),
edBirthday.getText().toString());

Intent intent = new Intent();


intent.putExtra("contact", contact);
intent.putExtra("flag", 2);
setResult(RESULT_OK, intent);
finish();
}
}
}
return super.onOptionsItemSelected(item);
}

@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return super.onSupportNavigateUp();
}
}

Buổi 5,6: Xây dựng ứng dụng quản lý danh bạ với CSDL Sqlite
Mục tiêu: Thiết kế và xây dựng ứng dụng với SQLITE
Kiến thức: hiểu và triển khai ứng dụng với SQLITEDATABASE
Kỹ năng: vận dụng và triển khai với Android Studio
Bài tập hướng dẫn
Xây dựng ứng dụng quản lý ghi chú với SQLITE. Trong dó mỗi ghi chú được quản lý với các
thông tin như title (tiêu đề), content (nội dung), createDate (Ngày tạo), ứng dụng bao gồm
các chức năng như :
● C- create R-read U-update D-delete
● tìm kiếm
● sắp xếp.

Trang 36
Bài tập TH LTDĐCB

Hướng dẫn chi tiết


Triển khai lại giao diện của buổi 6 với phần dữ liệu được quản lý bởi SQLITE
Xây dựng lớp quản lý dữ liệu DBHelper
public class DbHelper {

static String DB_NAME = "NoteDB.db";


Context context;
public DbHelper(Context context) {
this.context = context;
}

//Cach 1
public SQLiteDatabase openDBOption1() {
File dbFile = context.getDatabasePath(DB_NAME);

if (!dbFile.exists()) {
try {
copyDatabase(dbFile);
} catch (IOException e) {
throw new RuntimeException("Error creating source database", e);
}
}

return SQLiteDatabase.openDatabase(dbFile.getPath(), null,


SQLiteDatabase.OPEN_READWRITE);
}

private void copyDatabase(File dbFile) throws IOException {


InputStream is = context.getAssets().open(DB_NAME);
OutputStream os = new FileOutputStream(dbFile);

byte[] buffer = new byte[1024];


while (is.read(buffer) > 0) {
os.write(buffer);
}

os.flush();
os.close();
is.close();
}

//Cach 2
public SQLiteDatabase openDBOption2(){
return context.openOrCreateDatabase(DB_NAME,Context.MODE_PRIVATE, null);
}
public void createTable(){
SQLiteDatabase db = openDBOption2();
String query = "CREATE TABLE IF NOT EXISTS NoteTbl(" +
" id INTEGER PRIMARY KEY AUTOINCREMENT, " +
" title TEXT," +
" content TEXT," +
" createDate TEXT )";
db.execSQL(query);
closeDB(db);

Trang 37
Bài tập TH LTDĐCB

void closeDB(SQLiteDatabase db){


db.close();
}

public void insertNote(Note note){

}
public void updateNote(Note note){

}
public void deleteNote(int id){

}
public ArrayList<Note> getNotes(){

return null;
}

public Note getNoteById(int id){


return null;
}

public ArrayList<Note> searchNote(String newString){


return null;
}

public ArrayList<Note> sortNote(int type){


return null;
}
}

Trang 38
Bài tập TH LTDĐCB

Buổi 7,8: Xây dựng ứng dụng với dữ liệu JSON


Mục tiêu: Thiết kế và xây dựng ứng dụng với JSON
Kiến thức: hiểu và triển khai ứng dụng với JSON
Kỹ năng: vận dụng và triển khai với Android Studio
Bài tập hướng dẫn:
Xây dựng ứng dụng đọc dữ liệu từ file JSON với dữ liệu JSON cho sẵn có giao diện được
thiết kế như sau

Hướng dẫn chi tiết


Thêm 2 file json cho sẵn vào thư mục
Assets

Xây dựng lớp Astronaut.java


public class Astronaut implements Serializable {
String id;
String name;
String description;
String role;

public Astronaut() {
}

public Astronaut(String id, String name, String description, String role) {


this.id = id;
this.name = name;
this.description = description;
this.role = role;
}

public String getId() {


return id;
}

Trang 39
Bài tập TH LTDĐCB

public void setId(String id) {


this.id = id;
}

public String getName() {


return name;
}

public void setName(String name) {


this.name = name;
}

public String getDescription() {


return description;
}

public void setDescription(String description) {


this.description = description;
}

public String getRole() {


return role;
}

public void setRole(String role) {


this.role = role;
}
}

Xây dựng lớp Mission.java


public class Mission implements Serializable {
String id;
String launchDate;
ArrayList<Crew> crews;
String description;

public Mission() {
}

public Mission(String id, String launchDate, ArrayList<Crew> crews, String description) {


this.id = id;
this.launchDate = launchDate;
this.crews = crews;
this.description = description;
}

public String getId() {


return id;
}

public void setId(String id) {


this.id = id;
}

Trang 40
Bài tập TH LTDĐCB

public String getLaunchDate() {


return launchDate;
}

public void setLaunchDate(String launchDate) {


this.launchDate = launchDate;
}

public ArrayList<Crew> getCrews() {


return crews;
}

public void setCrews(ArrayList<Crew> crews) {


this.crews = crews;
}

public String getDescription() {


return description;
}

public void setDescription(String description) {


this.description = description;
}

public static class Crew implements Serializable {


String name;
String role;

public Crew(String name, String role) {


this.name = name;
this.role = role;
}

public String getName() {


return name;
}

public void setName(String name) {


this.name = name;
}

public String getRole() {


return role;
}

public void setRole(String role) {


this.role = role;
}
}
}

Xây dựng lớp Ultilities.java


public class Utilities {
public static Mission convertJsonToMission(JSONObject json) throws JSONException {

Trang 41
Bài tập TH LTDĐCB

Mission mission = new Mission();


mission.setId(json.getString("id"));
if(json.has("launchDate")){
mission.setLaunchDate(json.getString("launchDate"));
}else {
mission.setLaunchDate("N/A");
}
JSONArray jsonArray = json.getJSONArray("crew");
ArrayList<Mission.Crew> crews = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject_i = (JSONObject) jsonArray.get(i);
crews.add(new Mission.Crew(jsonObject_i.getString("name"),
jsonObject_i.getString("role")));
}
mission.setCrews(crews);
mission.setDescription(json.getString("description"));
return mission;
}

public static ArrayList<Mission> getMissionFromString(String data) throws


JSONException {
ArrayList<Mission> missions = new ArrayList<>();

JSONArray jsonArray = new JSONArray(data);


for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = (JSONObject) jsonArray.get(i);
missions.add(convertJsonToMission(jsonObject));
}

return missions;
}

public static ArrayList<Astronaut> convertJsonToAstronauts(ArrayList<Mission.Crew>


crews,String data) throws JSONException {
JSONObject jsonObject = new JSONObject(data);
ArrayList<Astronaut> astronauts = new ArrayList<>();
for (Mission.Crew item: crews) {
JSONObject json = jsonObject.getJSONObject(item.name);
Astronaut astronaut = new Astronaut();
astronaut.setId(json.getString("id"));
astronaut.setName(json.getString("name"));
astronaut.setDescription(json.getString("description"));
astronaut.setRole(item.getRole());
astronauts.add(astronaut);
}
return astronauts;
}

public static String convertInputStreamToString(InputStream inputStream) throws


IOException {
StringBuilder sb = new StringBuilder();
for (int ch; (ch = inputStream.read()) != -1; ) {
sb.append((char) ch);

Trang 42
Bài tập TH LTDĐCB

}
return sb.toString();
}

public static int getImageMissionFromImageData(String id){


return imageMissionData().get(id);
}
public static int getImageAstronautFromImageData(String id){
return imageAstronautData().get(id);
}

public static HashMap<String, Integer> imageMissionData(){


HashMap<String, Integer> map = new HashMap<>();
map.put("1", R.drawable.apollo1);
map.put("7", R.drawable.apollo7);
map.put("8", R.drawable.apollo8);
map.put("9", R.drawable.apollo9);
map.put("10", R.drawable.apollo10);
map.put("11", R.drawable.apollo11);
map.put("12", R.drawable.apollo12);
map.put("13", R.drawable.apollo13);
map.put("14", R.drawable.apollo14);
map.put("15", R.drawable.apollo15);
map.put("16", R.drawable.apollo16);
map.put("17", R.drawable.apollo17);
return map;
}

public static HashMap<String, Integer> imageAstronautData(){


HashMap<String, Integer> map = new HashMap<>();
map.put("aldrin", R.drawable.aldrin);
map.put("anders", R.drawable.anders);
map.put("armstrong", R.drawable.armstrong);
map.put("borman", R.drawable.borman);
map.put("cernan", R.drawable.cernan);
map.put("chaffee", R.drawable.chaffee);
map.put("collins", R.drawable.collins);
map.put("conrad", R.drawable.conrad);
map.put("cunningham", R.drawable.cunningham);
map.put("duke", R.drawable.duke);
map.put("eisele", R.drawable.eisele);
map.put("evans", R.drawable.evans);
map.put("evans", R.drawable.evans);
map.put("gordon", R.drawable.gordon);
map.put("grissom", R.drawable.grissom);
map.put("haise", R.drawable.haise);
map.put("irwin", R.drawable.irwin);
map.put("lovell", R.drawable.lovell);
map.put("mattingly", R.drawable.mattingly);
map.put("mcdivitt", R.drawable.mcdivitt);
map.put("roosa", R.drawable.roosa);
map.put("schirra", R.drawable.schirra);
map.put("schmitt", R.drawable.schmitt);
map.put("schweickart", R.drawable.schweickart);
map.put("scott",R.drawable.scott );

Trang 43
Bài tập TH LTDĐCB

map.put("shepard", R.drawable.shepard);
map.put("stafford", R.drawable.stafford);
map.put("swigert", R.drawable.swigert);
map.put("white", R.drawable.white);
map.put("worden", R.drawable.worden);
map.put("young", R.drawable.young);
return map;
}
}

Phần thiết kế xử lý và giao diện được sử dụng lại kiến thức như RecylerView, Intent,
ActivityResultLanucher

Trang 44
Bài tập TH LTDĐCB

Buổi 9,10: Xây dựng ứng dụng nghe nhạc với Mediaplayer
Mục tiêu: Thiết kế và xây dựng ứng dụng với Mediaplayer
Kiến thức: hiểu và triển khai ứng dụng với Mediaplayer
Kỹ năng: vận dụng và triển khai với Android Studio
Bài tập hướng dẫn:
Xây dựng ứng dụng nghe nhạc offline có
chức năng điều khiển nhạc (play, pause,
tua nhanh và tua ngược 5s) với nguồn của
nhạc được lấy từ bộ nhớ ngoài theo
đường dẫn
“/storage/emulated/0/Music/song_2.mp3”
và có giao diện như sau

Hướng dẫn chi tiết


Xây dựng Song.java
public class Song {
String title;
String artist;
String album;
Bitmap bitmap;

public Song(String title, String artist, String album, Bitmap bitmap) {


this.title = title;
this.artist = artist;
this.album = album;
this.bitmap = bitmap;
}

public String getTitle() {


return title;
}

public void setTitle(String title) {


this.title = title;
}

public String getArtist() {


return artist;
}

Trang 45
Bài tập TH LTDĐCB

public void setArtist(String artist) {


this.artist = artist;
}

public String getAlbum() {


return album;
}

public void setAlbum(String album) {


this.album = album;
}

public Bitmap getBitmap() {


return bitmap;
}

public void setBitmap(Bitmap bitmap) {


this.bitmap = bitmap;
}
}

Thiết kế giao diện cho màn hình quản lý điều khiển nhạc “activity_play_song.xml”
<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"
tools:context=".PlaySongActivity">

<TextView
android:id="@+id/txtTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="64dp"
android:text="Title"
android:textSize="35dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/btnForward"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="8dp"
android:layout_marginBottom="32dp"
android:text="@string/forward"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />

Trang 46
Bài tập TH LTDĐCB

<Button
android:id="@+id/btnPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

android:layout_alignParentBottom="true"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="@string/pause"
app:layout_constraintEnd_toStartOf="@+id/btnRewind"
app:layout_constraintStart_toEndOf="@+id/btnPlay"
app:layout_constraintTop_toTopOf="@+id/btnPlay" />

<Button
android:id="@+id/btnPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/btnPause"
android:layout_marginStart="8dp"
android:layout_toEndOf="@+id/btnPause"
android:layout_toRightOf="@+id/btnPause"
android:text="@string/back"
app:layout_constraintStart_toEndOf="@+id/btnForward"
app:layout_constraintTop_toTopOf="@+id/btnForward" />

<Button
android:id="@+id/btnRewind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/btnPlay"
android:layout_marginEnd="8dp"
android:layout_toEndOf="@+id/btnPlay"
android:layout_toRightOf="@+id/btnPlay"
android:text="@string/rewind"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/btnPause" />

<SeekBar
android:id="@+id/seekBar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_above="@+id/btnForward"
android:layout_alignStart="@+id/txtTitle"
android:layout_alignLeft="@+id/txtTitle"
android:layout_alignEnd="@+id/txtTitle"
android:layout_alignRight="@+id/txtTitle"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toTopOf="@+id/btnPlay"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.464"
app:layout_constraintStart_toStartOf="parent"

Trang 47
Bài tập TH LTDĐCB

app:layout_constraintTop_toBottomOf="@+id/txtStart" />

<TextView
android:id="@+id/txtEnd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/seekBar"
android:layout_marginEnd="16dp"
android:layout_marginBottom="32dp"
android:text="00:00"
android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintBottom_toTopOf="@+id/btnRewind"
app:layout_constraintEnd_toEndOf="parent" />

<TextView
android:id="@+id/txtStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/seekBar"
android:layout_alignEnd="@+id/btnRewind"
android:layout_alignRight="@+id/btnRewind"
android:layout_marginStart="16dp"
android:layout_marginBottom="32dp"
android:text="00:00"
android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintBottom_toTopOf="@+id/btnForward"
app:layout_constraintStart_toStartOf="parent" />

<TextView
android:id="@+id/txtAlbum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/txtEnd"
android:layout_alignBottom="@+id/txtEnd"
android:layout_centerHorizontal="true"
android:layout_marginBottom="36dp"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium"
app:layout_constraintBottom_toTopOf="@+id/seekBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent" />

<TextView
android:id="@+id/txtArtist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtTitle" />

<ImageView
android:id="@+id/imgCover"

Trang 48
Bài tập TH LTDĐCB

android:layout_width="160dp"
android:layout_height="160dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:scaleType="center"
android:background="@drawable/bg_image"
app:layout_constraintBottom_toTopOf="@+id/txtAlbum"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtArtist"
android:src="@drawable/song_cover"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

Thiết kế xử lý “PlaySongActivity.java”
public class PlaySongActivity extends AppCompatActivity {

MediaPlayer mediaPlayer;
double startTime = 0;
double finalTime = 0;
int forwardTime = 5000;
int backwardTime = 5000;
static int oneTimeOnly = 0;
Handler myHandler = new Handler();

Button btnPlay, btnPause, btnForward, btnRewind;


SeekBar seekBar;
TextView txtStart, txtEnd, txtTitle, txtAlbum, txtArtist;
ImageView imgCover;
Song song;
String filePath;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play_song);

btnPlay = findViewById(R.id.btnPlay);
btnPause = findViewById(R.id.btnPause);
btnForward = findViewById(R.id.btnForward);
btnRewind = findViewById(R.id.btnRewind);
txtEnd = findViewById(R.id.txtEnd);
txtStart = findViewById(R.id.txtStart);
txtTitle = findViewById(R.id.txtTitle);
txtAlbum = findViewById(R.id.txtAlbum);
txtArtist = findViewById(R.id.txtArtist);
imgCover = findViewById(R.id.imgCover);

seekBar = findViewById(R.id.seekBar);
seekBar.setClickable(false);

Trang 49
Bài tập TH LTDĐCB

try {
filePath = "/storage/emulated/0/Music/song_2.mp3";
mediaPlayer= new MediaPlayer();
mediaPlayer.setDataSource(filePath);
mediaPlayer.prepare();

} catch (IOException e) {
e.printStackTrace();
}

song = getSongInfo();

txtTitle.setText(song.getTitle());
txtArtist.setText(song.getArtist());
txtAlbum.setText(song.getAlbum());
if(song.getBitmap()!=null){
imgCover.setImageBitmap(song.getBitmap());
imgCover.setScaleType(ImageView.ScaleType.FIT_CENTER);
}

btnPause.setEnabled(false);
btnPlay.setOnClickListener(view -> {
mediaPlayer.start();
finalTime = mediaPlayer.getDuration();
startTime = mediaPlayer.getCurrentPosition();

if (oneTimeOnly == 0) {
seekBar.setMax((int) finalTime);
oneTimeOnly = 1;
}

txtEnd.setText(String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes((long) finalTime),
TimeUnit.MILLISECONDS.toSeconds((long) finalTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long)
finalTime)))
);

txtStart.setText(String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes((long) startTime),
TimeUnit.MILLISECONDS.toSeconds((long) startTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long)
startTime)))
);

seekBar.setProgress((int)startTime);
myHandler.postDelayed(UpdateSongTime,100);
btnPlay.setEnabled(false);
btnPause.setEnabled(true);

});

btnPause.setOnClickListener(v -> {

Trang 50
Bài tập TH LTDĐCB

mediaPlayer.pause();
btnPause.setEnabled(false);
btnPlay.setEnabled(true);
});

btnForward.setOnClickListener(v -> {
int temp = (int)startTime;

if((temp+forwardTime)<=finalTime){
startTime = startTime + forwardTime;
mediaPlayer.seekTo((int) startTime);
}
});

btnRewind.setOnClickListener(v -> {
int temp = (int)startTime;

if((temp-backwardTime)>0){
startTime = startTime - backwardTime;
mediaPlayer.seekTo((int) startTime);

}
});
}

private Song getSongInfo() {

MediaMetadataRetriever mmr = new MediaMetadataRetriever();


File file = new File(filePath);
mmr.setDataSource(file.getAbsolutePath());
String title = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
String artist =mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
String album =
mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
Bitmap bitmap = BitmapFactory.decodeByteArray(mmr.getEmbeddedPicture(),
0,mmr.getEmbeddedPicture().length );
return new Song(title, artist, album, bitmap);
}

Runnable UpdateSongTime = new Runnable() {


public void run() {
startTime = mediaPlayer.getCurrentPosition();
txtStart.setText(String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes((long) startTime),
TimeUnit.MILLISECONDS.toSeconds((long) startTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.
toMinutes((long) startTime)))
);
seekBar.setProgress((int)startTime);
myHandler.postDelayed(this, 100);
}
};

Trang 51
Bài tập TH LTDĐCB

@Override
protected void onResume() {
super.onResume();
seekBar.setProgress((int)startTime);
myHandler.postDelayed(UpdateSongTime,100);

}
}

Bài tập về nhà:


Hãy xây dựng ứng dụng hoàn chỉnh hơn với các chức năng sau :
● hiển thị danh sách bài hát có trong bộ nhớ ngoài
● Phát nhạc cho từng bài khi chọn vào bài hát trong danh sách bài hát
Gợi ý:
Xây dựng giao diện mới với RecyclerView (SongListActivity)
Khai báo các quyền truy cập bộ nhớ ngoài trong Android Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="vn.edu.csc.buoi9">

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
/>

<application
android:requestLegacyExternalStorage="true"
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/Theme.Buoi9">
<activity android:name=".PlaySongActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />


</intent-filter>
</activity>
<activity android:name=".MainActivity">

</activity>
</application>

</manifest>

Sử dụng intent để kết nối giữa SongListActivty và PlaySongActiviity

Trang 52

You might also like