Đang tải... (xem toàn văn)
ĐẠI HỌC QUỐC GIA TP HỒ CHÍ MINH
TRƯỜNG ĐẠI HỌC AN GIANG
KHOA CÔNG NGHỆ THÔNG TIN
Trang 3MỤC LỤC
Lời Nói Đầu 3
I MỤC TIÊU YÊU CẦU 4
II.1 Mục Tiêu 4
I.2 Yêu Cầu 5
II ĐỐI TƯỢNG SỬ DỤNG 6
II.1 Nhà phát triển ứng dụng: 6
II.2 Người quản lý nội dung âm nhạc: 6
II.3 Người dùng cuối (End Users): 6
III PHÂN TÍCH THIẾT KẾ HỆ THỐNG 8
IV GIAO DIỆN ỨNG DỤNG 9
IV.1 Giao diện Đăng nhập, Đăng ký 9
IV.2 Giao diện Quên mật khẩu và Đổi mật khẩu 10
IV.3 Giao diện Trang chủ người dùng 11
IV.4 Giao diện Chức năng người dùng 12
IV.5 Giao diện Phát nhạc và List nhạc đang phát 13
IV.6 Giao diện Thông báo phát nhạc 14
IV.7 Giao diện Nhạc đang phát mà trở về màn hình chính 15
IV.8 Giao diện Danh sách (List) tất cả nhạc của hệ thống 16
IV.9 Giao diện Các bài hát nổi bật 17
IV.10 Giao diện Các bài hát mới nhất 18
IV.11 Giao diện Kết nối với các diễn đàn và mạng xã hội 19
IV.12 Giao diện Đóng góp ý kiến về ứng dụng 20
IV.13 Giao diện Người quản trị (admin) 21
IV.13 Giao diện Thêm nhạc dành cho Người quản trị 22
IV.14 Giao diện Cập nhật nhạc dành cho Người quản trị 23
Trang 4V.8 Hiển thị danh sách bài hát mới nhất 44
V.9 Hiển thị danh sách bài hát đã yêu thích 46
V.10 Hiển thị tất cả các bài hát trên hệ thống 49
V.11 Kết nối đến mạng xã hội 51
V.12 Đổi mật khẩu 53
V.13 Thêm bài hát mới hoặc sửa bài hát 54
VI TÀI LIỆU THAM KHẢO 58
VI.1 Kho lưu trữ GitHub: 58
VI.2 Video YouTube: 58
Lời Nói Đầu
Môn học “Lập trình di động” là một phần quan trọng trongchương trình đào tạo ngành Công nghệ thông tin Trong khóa học này,sinh viên chúng em sẽ được trang bị kiến thức và kỹ năng cần thiết đểphát triển các ứng dụng di động cho các thiết bị như điện thoại thôngminh, máy tính bảng và các thiết bị di dộng khác Nó giúp chúng em đãcùng nhau khám phá thế giới của ứng dụng di động
Ngày nay, điện thoại thông minh và máy tính bảng đã trởthành một phần không thể thiếu của cuộc sống của chúng em Chúngem sử dụng chúng để nghe nhạc, xem phim, đọc tin tức, và thậm chí làlàm việc Và để tạo ra những ứng dụng tuyệt vời cho các thiết bị này,chúng em cần phải hiểu rõ về lập trình di động.
Chủ đề báo cáo của môn học này là “Ứng dụng Nghe Nhạc,”một lĩnh vực thú vị và phổ biến trong cuộc sống hàng ngày chúng emsẽ học cách phát triển một ứng dụng nghe nhạc từ đầu đến cuối Chúngem sẽ tìm hiểu về việc kết nối với các dịch vụ nhạc trực tuyến, xâydựng giao diện người dùng thân thiện, và tối ưu hóa hiệu suất ứngdụng Điều này sẽ giúp các bạn có kiến thức thực tế và sẵn sàng ápdụng vào công việc sau khi tốt nghiệp.
4
Trang 5I MỤC TIÊU YÊU CẦU
II.1 Mục Tiêu
1 Giao diện người dùng thân thiện:
Thiết kế giao diện đơn giản, dễ sử dụng với các biểu tượng rõ ràng.
Đảm bảo giao diện phù hợp với mọi đối tượng người dùng, từ người mới sử dụng đến người dùng kỳ cựu.
2 Chức năng cơ bản của ứng dụng:
Phát nhạc: Hỗ trợ phát các tập tin âm thanh ở nhiều định dạng phổ biến (MP3,
FLAC, AAC, vv.).
Tìm kiếm nhạc: Cho phép người dùng tìm kiếm theo nghệ sĩ, album, bài hát, thể
loại, và hiển thị kết quả chính xác.
Danh sách phát yêu thích: Cho phép người dùng tạo danh sách nhạc yêu thích để
dễ dàng truy cập.
Điều chỉnh âm lượng và chất lượng âm thanh: Cung cấp thanh điều chỉnh âm
lượng và tùy chọn chất lượng âm thanh.
Hỗ trợ tai nghe và loa ngoài: Tự động chuyển đổi giữa loa ngoài và tai nghe khi
cắm hoặc rút tai nghe.
3 Tính năng nâng cao (tùy chọn):
Chia sẻ nhạc: Hỗ trợ chia sẻ bài hát với bạn bè qua mạng xã
hội hoặc ứng dụng nhắn tin.
Gợi ý nhạc: Dựa trên sở thích của người dùng, gợi ý các bài hát
4 Kiểm tra ổn định và hiệu suất:
Thử nghiệm ứng dụng trên các thiết bị di động phổ biến (Android, iOS) để đảm bảo hoạt động ổn định và mượt mà.
5
Trang 6Xử lý các vấn đề liên quan đến tốc độ phản hồi, tiêu thụ tài nguyên, và khả năng phát nhạc liên tục.
Tổng quát: Phát triển một ứng dụng nghe nhạc di động hoàn chỉnh, đáp ứng nhu cầu giải trí và nghe nhạc của người dùng.
I.2 Yêu Cầu
1 Yêu cầu về chức năng:
Ứng dụng phải đáp ứng đầy đủ các chức năng cơ bản của một ứng dụng nghe nhạc di động như đã nêu ở mục trên.
Các chức năng nâng cao (nếu có) phải được triển khai một cáchhoàn chỉnh và hiệu quả.
Ứng dụng phải tương thích với nhiều phiên bản hệ điều hành Android phổ biến.
2 Yêu cầu về kỹ thuật:
Ứng dụng được phát triển bằng ngôn ngữ lập trình Java.Sử dụng Android Studio làm môi trường phát triển chính.Thiết kế giao diện người dùng đẹp mắt, thân thiện và dễ sử dụng.
Sử dụng các thư viện và API phù hợp để tối ưu hóa hiệu suất và tính năng của ứng dụng.
Viết code tuân theo các quy tắc lập trình tốt nhất, đảm bảo tínhbảo mật và dễ bảo trì.
3 Yêu cầu về tài liệu:
Báo cáo tài liệu đầy đủ, chi tiết về quá trình thiết kế, phát triển và thử nghiệm ứng dụng.
Bao gồm hướng dẫn sử dụng ứng dụng dành cho người dùng.Cung cấp mã nguồn đầy đủ của ứng dụng.
6
Trang 7II ĐỐI TƯỢNG SỬ DỤNGII.1 Nhà phát triển ứng dụng:
Quản lý nội dung toàn diện:
Người quản lý nội dung âm nhạc có quyền truy cập vào các công cụ quản lý mạnh mẽ để tảilên, quản lý và phân loại các bài hát, album và nghệ sĩ.
Họ có thể thêm thông tin chi tiết về âm nhạc, chỉnh sửa metadata, tạo danh sách phát vàsắp xếp nội dung theo nhiều tiêu chí khác nhau.
Điều này giúp đảm bảo tính chính xác, nhất quán và dễ dàng tìm kiếm nội dung âm nhạccho người dùng.
Quyền kiểm soát nội dung:
Người quản lý nội dung âm nhạc có thể kiểm soát quyền truy cập vào nội dung, cho phéphọ giới hạn quyền truy cập vào một số nội dung nhất định hoặc cung cấp quyền truy cập độcquyền cho người dùng cụ thể.
Điều này hữu ích cho việc quản lý bản quyền, phân phối nội dung độc quyền hoặc tạo cácgói đăng ký trả phí.
II.3 Người dùng cuối (End Users):
Ứng dụng nghe nhạc di động có thể được sử dụng bởi rất nhiều đối tượng, bao gồm:
Học sinh, sinh viên:
o Giải trí trong giờ nghỉ ngơi, thư giãn sau giờ học căng thẳng.o Nghe nhạc khi học tập, giúp tăng khả năng tập trung và ghi nhớ.
7
Trang 8 Người đi làm:
o Nghe nhạc khi di chuyển trên đường đi làm, giúp giảm bớt căng thẳng và mệt mỏi.o Nghe nhạc trong giờ nghỉ trưa để thư giãn và giải trí.
Người cao tuổi:
o Nghe nhạc để thư giãn, giảm bớt stress và cải thiện sức khỏe tinh thần.o Nghe nhạc quen thuộc để gợi nhớ về những kỷ niệm đẹp trong quá khứ. Các vận động viên:
o Nghe nhạc trước khi tập luyện để tăng cường động lực và tinh thần.
o Nghe nhạc khi tập luyện để giúp cơ thể vận động nhịp nhàng và hiệu quả hơn. Nghệ sĩ:
o Nghe nhạc để lấy cảm hứng sáng tác.
o Nghe nhạc của các nghệ sĩ khác để học hỏi và trau dồi kỹ năng âm nhạc.
Ngoài ra, ứng dụng này còn có thể được sử dụng cho nhiều mục đích khác nhau như:
Giáo dục:
o Nghe nhạc tiếng Anh để học ngoại ngữ.o Nghe nhạc thiếu nhi để giáo dục trẻ em. Kinh doanh:
o Phát nhạc trong cửa hàng để tạo bầu không khí mua sắm thoải mái.o Sử dụng nhạc quảng cáo để thu hút khách hàng.
Trang 9III PHÂN TÍCH THIẾT KẾ HỆ THỐNG
9
Trang 10IV GIAO DIỆN ỨNG DỤNG IV.1 Giao diện Đăng nhập, Đăng ký
10
Trang 11IV.2 Giao diện Quên mật khẩu và Đổi mật khẩu
11
Trang 12IV.3 Giao diện Trang chủ người dùng
12
Trang 13IV.4 Giao diện Chức năng người dùng
13
Trang 14IV.5 Giao diện Phát nhạc và List nhạc đang phát
14
Trang 15IV.6 Giao diện Thông báo phát nhạc
15
Trang 16IV.7 Giao diện Nhạc đang phát mà trở về màn hình chính
16
Trang 17IV.8 Giao diện Danh sách (List) tất cả nhạc của hệ thống
17
Trang 18IV.9 Giao diện Các bài hát nổi bật
18
Trang 19IV.10 Giao diện Các bài hát mới nhất
19
Trang 20IV.11 Giao diện Kết nối với các diễn đàn và mạng xã hội
20
Trang 21IV.12 Giao diện Đóng góp ý kiến về ứng dụng
21
Trang 22IV.13 Giao diện Người quản trị (admin)
22
Trang 23IV.13 Giao diện Thêm nhạc dành cho Người quản trị
23
Trang 24IV.14 Giao diện Cập nhật nhạc dành cho Người quản trị
24
Trang 25V CÁC CHỨC NĂNG CỦA ỨNG DỤNGV.1 Kết nối với firebase (Sử lý trong hệ thống)
* Mô tả
Để kết nối ứng dụng với Firebase ta cần khởi tạo 1 dự án trên Firebase và kết nối ứngdụng với Firebase thông qua tên của gói (name-package của dự án) và thêm fileservices.json của firebase bằng cách tải về và thêm vào thư mục có tên là app để thực hiệnkết nối.
Tiếp theo cần dán đường link dự án trên Firebase vào file MyApplication File nàyđược tạo ra để kết nối với Firebase Và lấy các liên kết đến các bảng dữ liệu trên Firebase.Để thực hiện các việc như lấy dữ liệu, thêm dữ liệu và xóa dữ liệu.
public static MyApplication get(Context context) {
return (MyApplication) context.getApplicationContext(); }
private void createChannelNotification() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_MIN);
25
Trang 26channel.setSound(null, null);
NotificationManager manager = getSystemService(NotificationManager.class); manager.createNotificationChannel(channel);
} }
public DatabaseReference getSongsDatabaseReference() { return mFirebaseDatabase.getReference("/songs"); }
public DatabaseReference getFeedbackDatabaseReference() { return mFirebaseDatabase.getReference("/feedback"); }
public DatabaseReference getCountViewDatabaseReference(long songId) {
return FirebaseDatabase.getInstance().getReference("/songs/" + songId + "/count"); }
package com.medium.music.activity;import android.os.Bundle;
import android.widget.Toast;import com.medium.music.R;
import com.medium.music.constant.Constant;
import com.medium.music.constant.GlobalFunction;
import com.medium.music.databinding.ActivitySignUpBinding;import com.medium.music.model.User;
import com.medium.music.prefs.DataStoreManager;import com.medium.music.utils.StringUtil;
import com.google.firebase.auth.FirebaseAuth;import com.google.firebase.auth.FirebaseUser;
public class SignUpActivity extends BaseActivity {
private ActivitySignUpBinding mActivitySignUpBinding; @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
mActivitySignUpBinding =
26
Trang 27setContentView(mActivitySignUpBinding.getRoot()); mActivitySignUpBinding.rdbUser.setChecked(true);
mActivitySignUpBinding.imgBack.setOnClickListener(v -> onBackPressed());
mActivitySignUpBinding.layoutSignIn.setOnClickListener(v -> finish());
mActivitySignUpBinding.btnSignUp.setOnClickListener(v -> onClickValidateSignUp());
} else if (StringUtil.isEmpty(strPassword)) {
Toast.makeText(SignUpActivity.this,
getString(R.string.msg_password_require), Toast.LENGTH_SHORT).show();
} else if (!StringUtil.isValidEmail(strEmail)) {
Toast.makeText(SignUpActivity.this,
getString(R.string.msg_email_invalid), Toast.LENGTH_SHORT).show();
} else {
signUpUser(strEmail, strPassword); }
return; }
if (strEmail.contains(Constant.ADMIN_EMAIL_FORMAT)) {
Toast.makeText(SignUpActivity.this,
getString(R.string.msg_email_invalid_user), Toast.LENGTH_SHORT).show();
} else {
signUpUser(strEmail, strPassword); }
} }
27
Trang 28private void signUpUser(String email, String password) { showProgressDialog(true);
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
firebaseAuth.createUserWithEmailAndPassword(email, password)
addOnCompleteListener(this, task -> { showProgressDialog(false);
if (task.isSuccessful()) { FirebaseUser user =
Trang 29import com.medium.music.prefs.DataStoreManager;
import com.medium.music.utils.StringUtil;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
public class SignInActivity extends BaseActivity {
private ActivitySignInBinding mActivitySignInBinding; @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
mActivitySignInBinding =
setContentView(mActivitySignInBinding.getRoot());
// mặc định khởi đầu là check người dùng
mActivitySignInBinding.rdbUser.setChecked(true);
mActivitySignInBinding.layoutSignUp.setOnClickListener(
v -> GlobalFunction.startActivity(SignInActivity.this, SignUpActivity.class));
private void onClickForgotPassword() {
GlobalFunction.startActivity(this, ForgotPasswordActivity.class); }
private void onClickValidateSignIn() { String strEmail =
mActivitySignInBinding.edtEmail.getText().toString().trim(); String strPassword =
mActivitySignInBinding.edtPassword.getText().toString().trim(); if (StringUtil.isEmpty(strEmail)) {
return; }
Trang 30signInUser(strEmail, strPassword); }
} }
private void signInUser(String email, String password) { showProgressDialog(true);
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
// thực hiện quá trình đăng nhập từ phía firebase khi truyền vào gmail và pass
FirebaseUser user = firebaseAuth.getCurrentUser(); if (user != null) {
User userObject = new User(user.getEmail(),
//Kiểm tra xem email của người dùng có chứa định dạng email của quản trị viên (kiểm tra với hằng số Constant.ADMIN_EMAIL_FORMATđã được định nghĩa)
if (user.getEmail() != null && user.getEmail().contains(Constant.ADMIN_EMAIL_FORMAT)) { userObject.setAdmin(true); }
DataStoreManager.setUser(userObject);
GlobalFunction.startActivity(SignInActivity.this, MainActivity.class);
finishAffinity(); // đóng các tác vụ khác đang chạy
} } else {
Toast.makeText(SignInActivity.this, getString(R.string.msg_sign_in_error),
Toast.LENGTH_SHORT).show(); }
}); }
Trang 31protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
mActivityForgotPasswordBinding =
setContentView(mActivityForgotPasswordBinding.getRoot());
mActivityForgotPasswordBinding.imgBack.setOnClickListener(v -> onBackPressed());
Toast.makeText(ForgotPasswordActivity.this,
Trang 32Khi người dùng đăng nhập thành công vào giao diện chính (HomeScreen) dữ liệutừ database trên Firebase sẽ được tải xuống Quá trình này nhanh hay chậm phụ thuộcvào internet của thiết bị Để lấy dữ liệu từ Firebase tại code này cần phải kết nối đếnfile MyApplication đây là file thực hiện việc kết nối đến cơ sở dữ liệu trên Firebase(Mục kết nối file Firebase bên trên có nói rõ) Giao diện chính sẽ gọi đến fileMyApplication rồi từ file MyApplication sẽ kết nối với cơ sở dữ liệu và lấy dữ liệu rồitrả về cho nơi yêu cầu lấy là tại giao diện HomeScreen này.
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class HomeFragment extends Fragment {
private FragmentHomeBinding mFragmentHomeBinding; private List<Song> mListSong;
private List<Song> mListSongBanner;
private final Handler mHandlerBanner = new Handler();
32
Trang 33private final Runnable mRunnableBanner = new Runnable() { @Override
public void run() {
if (mListSongBanner == null || mListSongBanner.isEmpty()) { return;
g viewpager2.setCurrentItem(mFragmentHomeBinding.viewpager2.getCurrentItem() +
} };
@Nullable @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable
ViewGroup container, @Nullable Bundle savedInstanceState) {
mFragmentHomeBinding = FragmentHomeBinding.inflate(inflater,
container, false);
getListSongFromFirebase(""); initListener();
return mFragmentHomeBinding.getRoot(); }
private void initListener() {
mFragmentHomeBinding.edtSearchName.addTextChangedListener(new
TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int
count, int after) {
// Do nothing }
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// Do nothing }
@Override
public void afterTextChanged(Editable s) { String strKey = s.toString().trim();
if (strKey.equals("") || strKey.length() == 0) { if (mListSong != null) mListSong.clear(); getListSongFromFirebase("");
} } });
mFragmentHomeBinding.imgSearch.setOnClickListener(view -> searchSong());
mFragmentHomeBinding.edtSearchName.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_SEARCH) { searchSong();
33