Dự án App Android Ứng Dụng Bán Sách là một ứng dụng thương mại điện tử dành cho nền tảng Android, cho phép người dùng duyệt, tìm kiếm, và mua sách trực tuyến dễ dàng. Ứng dụng tích hợp các chức năng quản lý sản phẩm, giỏ hàng, thanh toán, và quản lý tài khoản người dùng. Gói tải về bao gồm full source code và báo cáo chi tiết, phù hợp cho học tập, nghiên cứu hoặc triển khai thực tế.
KHẢO SÁT VÀ PHÂN TÍCH THIẾT KẾ ỨNG DỤNG
Khảo sát và phân tích bài toán
1.1 Xác định yêu cầu bài toán:
Hiện nay, điện thoại di động đã trở thành thiết bị phổ biến với nhu cầu sử dụng ngày càng tăng cao Xu hướng này đã thúc đẩy sự phát triển của các ứng dụng di động bán sách, tạo ra một tiềm năng lớn cho công nghệ trong tương lai Do đó, doanh thu từ các ứng dụng bán sách cũng liên tục gia tăng.
Với ứng dụng bán sách thông minh, người dùng có thể dễ dàng tìm kiếm sách mong muốn, nắm bắt giá cả và thông tin chi tiết chỉ với vài cú lướt Trong thời đại thông tin nhanh chóng, ứng dụng này hỗ trợ người dùng tiếp cận nhanh và thuận lợi trên điện thoại, mang lại nhiều lợi ích như tìm kiếm thông tin về các quyển sách mới nhất, mua sách và đặt hàng đến địa chỉ mong muốn, cũng như hỗ trợ bán sách cũ.
+ Người mua hàng: Những người được hệ thống phục vụ công việc mua sách và thanh toán
+ Người bán sách cũ: là người dùng bán lại sách cũ của mình thông qua ứng dụng
+ Admin: Đảm bảo hệ thống hoạt động thông suốt, đồng thời là người điều hành hệ thống.
Xây dựng cơ sở dữ liệu
- Sơ đồ cơ sở dữ liệu:
Mô Tả: Bảng Dữ Liệu Chứa Thông Tin Sách
Value Constraint id Mã sách int Not Null N/A PK
TenSach Tên sách Nvarchar 50 Not Null
TenTacGia Tên tác giả Nvarchar 50 Null idTheLoai Mã Thể Loại int Null N/A FK
SoLuong Số Lượng int Null
HinhAnh Hình ảnh Nvarchar 1000 Null
MoTa Mô tả Nvarchar 2000 Null
DaBan Số lượng sách đã bán int Null
Phân loại sách cũ và mới int Null
Mô Tả: Bảng Dữ Liệu Chứa Thông Tin Thể Loại
Value Constraint idTheLoai Mã thể loại int Not Null N/A PK
TheLoai Tên thể loại Nvarchar 50 Null
HinhAnh Hình ảnh thể loại Nvarchar 1000 Null
Mô Tả: Bảng Dữ Liệu Chứa Thông Tin Về Khách Hàng
Value Constraint id Mã Khách
Hàng int Not Null N/A PK
Pass Mật Khẩu Nvarchar 50 Null
Mô Tả: Bảng Dữ Liệu Chứa Thông Tin Đơn Hàng
Value Constraint id Mã Đơn
Hàng Nvarchar 50 Not Null N/A PK iduser Mã khách hàng Nvarchar 50 Null N/A FK diachi Địa chỉ Nvarchar 50 Null sodienthoai Số điện thoại Nvarchar 50 Null email Email Nvarchar 50 Null soluongtong
Tổng số lượng sách đã mua int Null tongtien Tổng tiền int Null
2.5 Bảng Chi Tiết Đơn Hàng
Mô Tả: Bảng Dữ Liệu Chứa Thông Tin Chi Tiết Về Đơn Hàng
Value Constraint idDonHang Mã Đơn
Hàng Nvarchar 50 Null N/A FK idsp Mã Sách int Null N/A FK soluongdamua
Số lượng sách đã mua int Null gia Giá sach int Null
CƠ SỞ NGHIÊN CỨU LÝ THUYẾT
Ngôn ngữ truy vấn SQL
Mục đích: Thêm dữ liệu vào bảng
INSERT INTO Table_Ten (cot1, cot2, cot3, …, cotN)]
VALUES (giatri1, giatri2, giatri3, …, giatriN);
INSERT INTO TheLoai (matheloai, tentheloai) VALUES (p_matheloai, p_tentheloai)
Mục đích: Cập nhật dữ liệu vào bảng
UPDATE ten_bang SET cot1 = giatri1, cot2 = giatri2, …, cotN = giatriN WHERE [dieu_kien];
Ví dụ: UPDATE GiaoVien SET Luong = 3500 WHERE MAGV = 001 1.3 Delete:
Mục đích: Xóa dữ liệu trong bảng
DELETE FROM ten_bang [WHERE dieu_kien];
Ví dụ: DELETE GiaoVien WHERE MaGV = 002
Mục đích: Tên cột trong danh sách chọn
Cú pháp: SELECT giatri1, giatri2, …, giatriN FROM table name;
Ví dụ: SELECT * FROM KhachHang;
Ngôn ngữ lập trình Android
- Các Control (điều khiển cơ bản): TextView, EditText, Listview, Button,RecyclerView, ImageView, Toolbar, …
XÂY DỰNG ỨNG DỤNG
Chức Năng Đăng Nhập
The provided XML code defines a LinearLayout in an Android application, specifying its width and height to match the parent container It includes namespaces for Android, app, and tools, and sets the orientation to vertical, indicating that child views will be arranged in a column The layout is associated with the Login_Activity context for proper functionality within the app.
The provided XML code snippet defines a TextView for a login button in an Android application It specifies the button's ID as "tv_dangnhap," sets its dimensions to match the parent layout, and centers the text both horizontally and vertically The text "Đăng Nhập," meaning "Login" in Vietnamese, is displayed in a large font size of 25dp, with a top margin of 20dp The text color is set to a specific color resource, and the font style is defined as extrabold, enhancing its visibility and emphasis for users.
The `TextInputLayout` component in Android allows for customizable text input fields, with attributes such as `layout_width` set to "match_parent" and `layout_height` set to "wrap_content." It features margin settings of 5dp on the top and bottom, and 30dp on the right and left, ensuring proper spacing Additionally, it includes 7dp of padding and a background defined by a drawable resource named "border," enhancing the visual appeal and usability of the input field.
The provided XML code snippet defines an EditText element for user email input in an Android application It specifies attributes such as full width layout, adjustable height, a regular font family, and customized text and hint colors Additionally, it incorporates an email icon on the left, tinted to match the text color, and includes padding for better spacing.
The `TextInputLayout` is a versatile component in Android development, designed to enhance user input experiences It allows developers to create input fields with customizable dimensions, including a width that matches the parent layout and a height that wraps content Additionally, it supports margins and padding for better visual appeal, while also enabling a background drawable, such as a border, to improve aesthetics This layout is essential for building user-friendly interfaces in Android applications.
The EditText component for user password input is designed with a full-width layout, utilizing a regular font and customized text colors It features a hint labeled "Pass" and includes a key icon on the left, which is tinted to match the background color The drawable padding is set to 10dp for improved aesthetics.
The provided XML code defines an AppCompatButton for a login interface in an Android application This button, identified by the ID "btn_dangnhap," is set to match the parent width and has a height of 40dp, with margins of 40dp on the left and right and 12dp on the top It features padding of 7dp, white text color, a background drawable named "border_full," and uses a semibold font family, displaying the text "Đăng Nhập," which translates to "Login" in English.
The TextView element is designed for user registration, featuring the text "Đăng Ký" which translates to "Register" in English It utilizes a medium font style, displays in a specific text color, and is set at a text size of 15sp The layout parameters allow for flexible content display, ensuring it wraps appropriately within the designated space.
1.3 Login_Activity public class Login_Activity extends AppCompatActivity {
CompositeDisposable compositeDisposable = new CompositeDisposable(); boolean isLogin = false;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.login); anhxa(); controll();
} private void controll() { txtdangki.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) {
Intent(getApplicationContext(),Register_Activity.class); startActivity(intent);
}); btndangnhap.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) {
String str_email = email.getText().toString().trim();
String str_pass = pass.getText().toString().trim(); if(TextUtils.isEmpty(str_email)){
Toast.makeText(getApplicationContext(), "Bạn chưa nhập Email", Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(str_pass)){
Toast.makeText(getApplicationContext(), "Bạn chưa nhập Mật Khẩu", Toast.LENGTH_SHORT).show();
Paper.book().write("email", str_email);
Paper.book().write("pass", str_pass); compositeDisposable.add(apiBookApp.dangNhap(str_email, str_pass)
subscribeOn(Schedulers.io()).observeOn(Android Schedulers.mainThread())
subscribe( userModel -> { if (userModel.isSuccess()){ sever.user_current userModel.getResult().get(0);
Intent(getApplicationContext(), Main_Activity.class); startActivity(intent); finish();
Toast.makeText(getApplicationContext(), throwable.getMessage(),
To initialize the Paper library, use `Paper.init(this);` and create an instance of the API with `RetrofitBookApp.getInstance(sever.BASE_URL).create(ApiBookApp.class);` In your layout, retrieve the necessary views such as `txtdangki` for the registration text, `email` for the email input field, `pass` for the password input field, and `btndangnhap` for the login button Additionally, check if the saved email in Paper is not null to manage user login effectively.
Paper.book().read("pass") != null){ email.setText(Paper.book().read("email")); pass.setText(Paper.book().read("pass"));
@Override protected void onDestroy() { compositeDisposable.clear(); super.onDestroy();
Chức Năng Đăng Ký
The provided XML layout defines a LinearLayout for an Android application, specifying the layout's width and height to match the parent container It utilizes vertical orientation and includes necessary XML namespaces for Android, app attributes, and tools context, indicating that it is designed for the Register_Activity screen.
The XML code snippet defines a TextView in Android with the ID "textView." It is set to match the parent's width and has a height of 45dp The text displayed is "Đăng Ký," centered both horizontally and vertically The text size is 25dp, with a top margin of 20dp, and the text color is specified as "@color/backG2." Additionally, the font used is an extrabold style from the specified font family.
The provided XML code snippet defines a `TextInputLayout` in an Android application, which is set to match the parent width and wrap its height It includes top, right, and left margins of 5dp, 30dp, and 30dp respectively, along with padding of 7dp Additionally, the layout features a custom background defined by a drawable resource named "border."
The provided XML code snippet defines an EditText field for email registration in an Android application It is set to match the parent width and wrap content height, utilizing a regular font family The text color is customized to a specific color, with a hint displayed in a lighter shade Additionally, an email icon is included on the left side of the input field, with appropriate padding and tinting to enhance the visual appearance.
The TextInputLayout in Android allows for customizable input fields with various attributes It is designed to match the parent's width while maintaining a wrap content height, ensuring a flexible layout The element includes margin specifications on the left and right sides, enhancing its visual spacing Additionally, it features padding for improved user experience and a drawable border for aesthetic appeal, with a top margin to provide further separation from adjacent elements.
To create a user registration input field in Android, use the EditText widget with the following attributes: set the ID to "edt_register_user," ensure it matches the parent's width and wraps content height, and apply a regular font family Customize the text color and hint color to match your design, using "@color/backG" for text and "@color/backG3" for hints Include a hint that prompts users for their name and add a user icon on the left with a specified drawable tint and padding of 10dp for better aesthetics.
The TextInputLayout in Android is designed to enhance user input fields by providing a structured layout It is set to match the parent's width while wrapping its height, ensuring a flexible design The layout features margins on the right and left of 30dp, along with a top margin of 5dp for spacing Additionally, it includes 7dp of padding for improved touch interaction and is styled with a custom border background, making it visually appealing and user-friendly.
The EditText component for password registration in an Android application is designed with a width that matches the parent layout and a height that wraps content It utilizes a regular font family, features a text color and hint color that align with the app's color scheme, and includes a hint that prompts users to enter their password Additionally, it incorporates a key icon on the left side, which is tinted to match the text color, and has a drawable padding of 10dp for improved aesthetics.
The `` is designed to provide a flexible input field in Android applications It features a width that matches the parent layout and a height that wraps the content, ensuring an adaptable design The layout includes margins of 30dp on the right and left sides, with a top margin of 5dp, enhancing its visual spacing Additionally, the padding of 7dp and a background drawable defined as `@drawable/border` contribute to its aesthetic appeal and usability.
The EditText component for password confirmation in an Android application is designed with the ID "edt_register_repass." It features a full-width layout and a height that wraps content, utilizing a regular font family The text and hint colors are set to a specific background color, with the hint displaying the prompt "Nhập lại mật khẩu" (Enter password again) Additionally, it includes a key icon on the left, which is tinted to match the background color, and has a drawable padding of 10dp for improved spacing.
The provided XML code snippet defines a TextInputLayout in Android, set to match the parent's width and wrap its height It includes margins on the left and right of 30dp, with a top margin of 5dp The layout features padding of 7dp and a custom background defined by a drawable resource named "border."
The EditText component in Android is designed for mobile number input, featuring a full-width layout and a height that adjusts to content It utilizes a regular font family and displays text in a specified color, with a hint indicating "Phone number." The input field is enhanced with a phone icon on the left, which is tinted to match the background color, and includes padding for better visual spacing.
The provided XML code snippet defines an AppCompatButton in an Android layout, with the ID "btn_dangky" It is designed to match the parent's width and has a height of 40dp, with margins of 40dp on the left and right, and 12dp on the top The button features a padding of 7dp, white text color, a background defined by a drawable resource named "border_full", and uses a semibold font family The button's displayed text is "Đăng Ký", which translates to "Register" in English.
The provided XML code defines an AppCompatButton for an Android application, designed to facilitate user navigation back to the login screen This button has a width that matches the parent layout, a height of 40dp, and includes margins of 40dp on the left and right, and 12dp on the top It features padding of 7dp, a text color set to a specified color resource, and a background defined by a drawable resource that creates a border The button's text, displayed in an extrabold font, reads "Quay Lại Đăng Nhập," which translates to "Return to Login" in English.
2.3 Register_Adapter public class Register_Activity extends AppCompatActivity {
EditText email, pass, repass, mobile, username;
AppCompatButton button_DK, button_backDN;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.register);
} private void Controll() { button_DK.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) { dangKi();
}); button_backDN.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) { finish();
String str_email = email.getText().toString().trim();
String str_pass = pass.getText().toString().trim();
String str_repass = repass.getText().toString().trim();
String str_username = username.getText().toString().trim();
String str_mobile = mobile.getText().toString().trim(); if (TextUtils.isEmpty(str_email)){
Toast.makeText(getApplicationContext(), "Không được bỏ trống", Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(str_pass)){
Toast.makeText(getApplicationContext(), "Không được bỏ trống", Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(str_repass)){
Toast.makeText(getApplicationContext(), "Không được bỏ trống", Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(str_username)){
Toast.makeText(getApplicationContext(), "Không được bỏ trống", Toast.LENGTH_SHORT).show();
} else if (TextUtils.isEmpty(str_mobile)){
Toast.makeText(getApplicationContext(), "Không được bỏ trống", Toast.LENGTH_SHORT).show();
} else { if (str_pass.equals(str_repass)){
// lấy data compositeDisposable.add(apiBookApp.dangKi(str_email,str_pass,str_username,s tr_mobile)
subscribeOn(Schedulers.io()).observeOn(AndroidSche dulers.mainThread())
subscribe( userModel -> { if (userModel.isSuccess()){ sever.user_current.setEmail(str_email); sever.user_current.setPass(str_pass);
Intent(getApplicationContext(), Login_Activity.class); startActivity(intent); finish();
Toast.makeText(getApplicationContext(), userModel.getMessage(),
Toast.makeText(getApplicationContext(),throwable.getMessage(),
Toast.makeText(getApplicationContext(), "Không trùng mật khẩu", Toast.LENGTH_SHORT).show();
In the `AnhXa` method, the `ApiBookApp` interface is initialized using the Retrofit instance from `RetrofitBookApp` with the specified base URL The method also retrieves references to various UI elements, including the email, password, confirm password, mobile number, and username input fields, along with the registration and back-to-login buttons.
@Override protected void onDestroy() { compositeDisposable.clear(); super.onDestroy();
Màn Hình Chính (hiển thị các sách mới nhất, giỏ hàng)
The provided XML code defines a LinearLayout for an Android application, specifying attributes such as layout height to match the parent, context for the main activity, and compatibility with system windows.
The provided XML code defines an ImageView in an Android layout, specifying an ID of "img_main_search." It sets the dimensions to 45dp in width and 30dp in height, includes a top margin of 5dp, and positions the view to the right with a right margin of 15dp The ImageView displays a search icon sourced from the drawable resource "@drawable/ic_search."
The latest book release features a bold title displayed in a medium italic font, ensuring it stands out The text is set to a size of 20sp and is styled in white, providing a clean and modern appearance This design choice enhances readability while maintaining an elegant layout, perfect for attracting attention.
The provided XML code snippet defines a RecyclerView in an Android layout, featuring margins of 5dp on all sides The RecyclerView is assigned an ID of "recyclerview" and is set to match the parent width while adjusting its height to wrap its content.
The CardView in Android, defined with the namespace attributes for Android and app, features a corner radius of 7dp It is designed to match the parent's width and height, with specified margins of 5dp for the top and bottom, and 2dp for the right and left This layout structure enhances the visual appeal of UI components in Android applications.
The XML code snippet defines a TextView element in an Android layout, specifying its ID as "itemsach_tensach." The TextView is designed to display the text "Sách," which means "Book" in Vietnamese It is centered within its layout, features a bold text style, has a text size of 18sp, and is colored black This setup is essential for creating a visually appealing and user-friendly interface in Android applications.
The XML code snippet defines a TextView in an Android layout, where the TextView is identified by the ID "itemsach_tacgia." It is designed to display the text "tác giả," which translates to "author" in English The TextView is centered, features a black text color, has a text size of 12sp, and maintains a normal text style Additionally, it has a top margin set to -2dp, allowing for precise positioning within the layout.
The TextView element in Android displays the price of an item, set at 25,000, with a bold text style and a size of 14sp The text is centered and colored in a striking red (#DC1C1C), ensuring it stands out to users.
3.4 Main_Activity public class Main_Activity extends AppCompatActivity{
ArrayList mangloaisach; loaisachAdapter loaisachAdapter; int id = 0;
ArrayList mangsachmoi; com.example.app_ban_sach.adapter.sachmoiAdapter sachmoiAdapter; public static ArrayList mangshoppingCart;
ImageView img_menu, img_search;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
//Nếu như có kết nối internet ta mới thực hiện if(checkConnect.haveNetWorkConnection(Main_Activity.this)){
//getApplicationContext gọi đến màn hình này
// Bắt sự kiện cho Toolbar
CatchOnItemMenu(); clickMenu(); badge.setText(String.valueOf(Main_Activity.mangshoppingCart.size()));
} else { //ngược lại ta thông báo không có internet checkConnect.ShowToast(Main_Activity.this, "Kiểm tra lại kết nối Internet!"); finish();
} private void clickMenu(){ img_menu.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) {
Intent(getApplicationContext(),ShoppingCart_Activity.class); startActivity(intent); badge.setText(String.valueOf(Main_Activity.mangshoppingCart.size()));
}); img_search.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) {
Intent(getApplicationContext(),TimKiem_Activity.class); startActivity(intent);
//Sự kiện chuyển màn hình cho menu private void CatchOnItemMenu(){ listViewManHinhChinh.setOnItemClickListener(new
@Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { switch (i) { case 0: if
Intent intent = new Intent(Main_Activity.this, Main_Activity.class); startActivity(intent);
{checkConnect.ShowToast(getApplicationContext(),"Kiểm tra lại kết nối!"); } drawerLayout.closeDrawer(GravityCompat.START); break; case 1: if
Intent intent = new Intent(Main_Activity.this, KinhTe_Activity.class); intent.putExtra("idtheloai", mangloaisach.get(1).getIdtheloai()); startActivity(intent);
} else { checkConnect.ShowToast(getApplicationContext(),"Kiểm tra lại kết nối!"); } drawerLayout.closeDrawer(GravityCompat.START); break; case 2: if
Intent intent = new Intent(Main_Activity.this, CongNghe_Activity.class); intent.putExtra("idtheloai", mangloaisach.get(2).getIdtheloai()); startActivity(intent);
{checkConnect.ShowToast(getApplicationContext(),"Kiểm tra lại kết nối!"); } drawerLayout.closeDrawer(GravityCompat.START); break; case 3: if
Intent intent = new Intent(Main_Activity.this, TamLy_Activity.class); intent.putExtra("idtheloai", mangloaisach.get(3).getIdtheloai()); startActivity(intent);
} else { checkConnect.ShowToast(getApplicationContext(),"Kiểm tra lại kết nối!"); } drawerLayout.closeDrawer(GravityCompat.START); break; case 4: if
Intent intent = new Intent(Main_Activity.this, Truyen_Activity.class); intent.putExtra("idtheloai", mangloaisach.get(4).getIdtheloai()); startActivity(intent);
} else { checkConnect.ShowToast(getApplicationContext(),"Kiểm tra lại kết nối!"); } drawerLayout.closeDrawer(GravityCompat.START); break; case 5: if
Intent intent = new Intent(Main_Activity.this, TimKiem_Activity.class); startActivity(intent);
Intent intent = new Intent(Main_Activity.this, Manager_Activity.class); startActivity(intent);
Intent intent = new Intent(Main_Activity.this, LichSu_Activity.class); startActivity(intent);
Intent intent = new Intent(Main_Activity.this, Login_Activity.class); startActivity(intent);
RequestQueue requestQueue Volley.newRequestQueue(getApplicationContext());
JsonArrayRequest(sever.duongdan_SachMoi, new Response.Listener() {
@Override public void onResponse(JSONArray response) { if (response != null){ int id = 0;
String mota = ""; for (int i=0;i