Разработка мобильного приложения на Android

Заказать уникальную курсовую работу
Тип работы: Курсовая работа
Предмет: Разработка мобильных приложений
  • 58 58 страниц
  • 10 + 10 источников
  • Добавлена 29.08.2024
1 496 руб.
  • Содержание
  • Часть работы
  • Список литературы
ВВЕДЕНИЕ 2
1 РАЗРАБОТКА ИНТЕРФЕЙСА МОБИЛЬНОГО ПРИЛОЖЕНИЯ 4
1.1 Анализ предметной области 4
1.2 Анализ программных средств разработки 5
1.3 Принципы Material Design 6
1.4 Проектирование пользовательского интерфейса (UI) 7
1.5 Реализация интерфейса в Android Studio 10
1.6 Юзабилити-тестирование интерфейса 12
2 ПРОЕКТИРОВАНИЕ И РАЗРАБОТКА МОБИЛЬНОГО ПРИЛОЖЕНИЯ 14
2.1 Постановка задачи и формулировка требований 14
2.2 Архитектура приложения 16
2.3 Разработка базы данных 19
2.4 Интеграция с Firebase 22
2.5 Реализация бизнес-логики на Kotlin 26
2.6 Тестирование и отладка 29
ЗАКЛЮЧЕНИЕ 32
СПИСОК ИСПОЛЬЗОВАННЫХ ЛИТЕРАТУР 33
ПРИЛОЖЕНИЯ 35
Приложение А 35
Приложение Б 37
Фрагмент для ознакомления

os.Bundleimport android.text.TextUtilsimport android.view.Viewimport android.widget.Toastimport androidx.appcompat.app.AppCompatActivityimport com.example.newsapp.databinding.ActivityLoginBindingimport com.google.firebase.auth.FirebaseAuthclass LoginActivity : AppCompatActivity() { private lateinit var binding: ActivityLoginBinding private lateinit var mAuth: FirebaseAuth public override fun onStart() { super.onStart() val currentUser = mAuth.currentUser if (currentUser != null) { val intent = Intent(applicationContext, MainActivity::class.java) startActivity(intent) finish() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityLoginBinding.inflate(layoutInflater) setContentView(binding.root) val actionBar = supportActionBar actionBar?.hide() mAuth = FirebaseAuth.getInstance() binding.signupNow.setOnClickListener { val intent = Intent(applicationContext, SignupActivity::class.java) startActivity(intent) finish() } binding.signupBtn.setOnClickListener { binding.progressBar.visibility = View.VISIBLE val email = binding.email1.text.toString() val password = binding.password1.text.toString() if (TextUtils.isEmpty(email)){ binding.progressBar.visibility = View.GONE binding.email1.error = "Email cannot be empty" return@setOnClickListener } if (TextUtils.isEmpty(password)) { binding.progressBar.visibility = View.GONE binding.password1.error = "Password cannot be empty" return@setOnClickListener } mAuth.signInWithEmailAndPassword(email, password) .addOnCompleteListener { task -> binding.progressBar.visibility = View.GONE if (task.isSuccessful) { Toast.makeText( this@login, "Login successful.", Toast.LENGTH_SHORT ).show() val intent = Intent(applicationContext, MainActivity::class.java) startActivity(intent) finish() } else { Toast.makeText( this@login, "Authentication failed.", Toast.LENGTH_SHORT ).show() } } } }}MainActivity.ktpackage com.example.newsapp.uiimport android.content.Intentimport android.os.Bundleimport android.view.Viewimport androidx.activity.viewModelsimport androidx.appcompat.app.AppCompatActivityimport androidx.core.content.ContextCompatimport androidx.lifecycle.lifecycleScopeimport androidx.recyclerview.widget.LinearLayoutManagerimport androidx.recyclerview.widget.RecyclerViewimport com.example.newsapp.Appimport com.example.newsapp.Rimport com.example.newsapp.databinding.ActivityMainBindingimport com.example.newsapp.room.AppDBimport com.example.newsapp.room.repo.UserRepositoryimport com.example.newsapp.utils.AddCommentAdapterimport com.example.newsapp.viewmodel.MainViewModelimport com.example.newsapp.viewmodel.MainViewModelFactoryimport com.google.android.material.bottomnavigation.BottomNavigationViewimport com.google.firebase.auth.FirebaseAuthimport kotlinx.coroutines.launchclass MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private lateinit var auth: FirebaseAuth private lateinit var commentShowLayout: RecyclerView private lateinit var database: AppDB private lateinit var adapter: AddCommentAdapter private val viewModel: MainViewModel by viewModels { val userRepository = UserRepository((applicationContext as App).database.userDao()) MainViewModelFactory(userRepository) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) window.navigationBarColor = ContextCompat.getColor(this, R.color.black) auth = FirebaseAuth.getInstance() val user = auth.currentUser if (user == null) { startActivity(Intent(applicationContext, LoginActivity::class.java)) finish() } // Bottom Navigation val bottomNavigationView = findViewById(R.id.bottomNavigationView) bottomNavigationView?.selectedItemId = R.id.navigation_home bottomNavigationView.setOnItemSelectedListener { item -> when (item.itemId) { R.id.navigation_home -> { true } R.id.navigation_eventpick -> { startActivity(Intent(this@MainActivity, PickEventActivity::class.java)) true } R.id.navigation_profile -> { startActivity(Intent(this@MainActivity, ProfileActivity::class.java)) true } else -> false } } // Display Class/School binding.btnClass.isSelected = true binding.btnClass.setOnClickListener { binding.btnClass.isSelected = true binding.btnSchool.isSelected = false binding.classTenkai.visibility = View.VISIBLE binding.scTenkai.visibility = View.GONE } binding.btnSchool.setOnClickListener { binding.btnSchool.isSelected = true binding.btnClass.isSelected = false binding.classTenkai.visibility = View.GONE binding.scTenkai.visibility = View.VISIBLE } // Like class val likeBtn = binding.likeBtn likeBtn.setOnCheckedChangeListener { checkBox, isChecked -> viewModel.toggleLike(auth.currentUser?.email.toString()) } val likeBtn1 = binding.likeBtn1 likeBtn1.setOnCheckedChangeListener { checkBox, isChecked -> viewModel.toggleLike(auth.currentUser?.email.toString()) } // Like sc val likeBtnSc = binding.likeBtnSc likeBtnSc.setOnCheckedChangeListener { checkBox, isChecked -> viewModel.toggleLike(auth.currentUser?.email.toString()) } val likeBtnSc1 = binding.likeBtnSc1 likeBtnSc1.setOnCheckedChangeListener { checkBox, isChecked -> viewModel.toggleLike(auth.currentUser?.email.toString()) } // Comment database = (applicationContext as App).database commentShowLayout = findViewById(R.id.commentShowLayout) binding.showCommentRecycleView.apply { layoutManager = LinearLayoutManager(this@MainActivity) adapter = AddCommentAdapter(this@MainActivity, emptyList()) } lifecycleScope.launch { val comments = database.commentDao().getComments() adapter.setComments(comments) } //Log Out binding.buttonLogOut.setOnClickListener { FirebaseAuth.getInstance().signOut() startActivity(Intent(this, LoginActivity::class.java)) finish() } }}PickEventActivity.ktpackage com.example.newsapp.uiimport android.os.Bundleimport androidx.appcompat.app.AppCompatActivityimport androidx.recyclerview.widget.LinearLayoutManagerimport androidx.recyclerview.widget.RecyclerViewimport com.example.newsapp.Appimport com.example.newsapp.databinding.ActivityPickEventBindingimport com.example.newsapp.room.AppDBimport com.example.newsapp.utils.AddEventAdapterimport com.example.newsapp.viewmodel.MainViewModelimport com.example.newsapp.viewmodel.MainViewModelFactoryclass PickEventActivity : AppCompatActivity() { private lateinit var binding: ActivityPickEventBinding private lateinit var database: AppDB private lateinit var adapter: AddEventAdapter private val viewModel: MainViewModel by viewModels { val userRepository = UserRepository((applicationContext as App).database.userDao()) MainViewModelFactory(userRepository) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityPickEventBinding.inflate(layoutInflater) setContentView(binding.root) database = (applicationContext as App).database // RecyclerView val recyclerView = findViewById(R.id.eventRecycleView) recyclerView.layoutManager = LinearLayoutManager(this) adapter = AddEventAdapter(this, emptyList()) recyclerView.adapter = adapter // Fetch events viewModel.fetchEvents() viewModel.events.observe(this, { events -> adapter.setData(events) }) // Back Button binding.backButton.setOnClickListener { onBackPressed() } }}ProfileActivity.ktpackage com.example.newsapp.uiimport android.content.Intentimport android.os.Bundleimport android.view.Viewimport androidx.activity.viewModelsimport androidx.appcompat.app.AppCompatActivityimport com.example.newsapp.Appimport com.example.newsapp.Rimport com.example.newsapp.databinding.ActivityProfileBindingimport com.example.newsapp.room.AppDBimport com.example.newsapp.room.repo.UserRepositoryimport com.example.newsapp.viewmodel.MainViewModelimport com.example.newsapp.viewmodel.MainViewModelFactoryimport com.google.android.material.bottomnavigation.BottomNavigationViewimport com.google.firebase.auth.FirebaseAuthclass ProfileActivity : AppCompatActivity() { private lateinit var binding: ActivityProfileBinding private lateinit var auth: FirebaseAuth private lateinit var database: AppDB private val viewModel: MainViewModel by viewModels { val userRepository = UserRepository((applicationContext as App).database.userDao()) MainViewModelFactory(userRepository) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityProfileBinding.inflate(layoutInflater) setContentView(binding.root) database = (applicationContext as App).database auth = FirebaseAuth.getInstance() // Bottom Navigation val bottomNavigationView = findViewById(R.id.bottomNavigationView) bottomNavigationView.selectedItemId = R.id.navigation_profile bottomNavigationView.setOnItemSelectedListener { item -> when (item.itemId) { R.id.navigation_home -> { startActivity(Intent(this, MainActivity::class.java)) true } R.id.navigation_eventpick -> { startActivity(Intent(this, PickEventActivity::class.java)) true } R.id.navigation_profile -> { true } else -> false } } // Logout binding.logoutButton.setOnClickListener { auth.signOut() startActivity(Intent(this, LoginActivity::class.java)) finish() } // Update Profile binding.updateProfileButton.setOnClickListener { val intent = Intent(this, UpdateProfileActivity::class.java) startActivity(intent) } }}RegisterActivity.ktpackage com.example.newsapp.uiimport android.content.Intentimport android.os.Bundleimport android.text.TextUtilsimport android.view.Viewimport android.widget.Toastimport androidx.appcompat.app.AppCompatActivityimport com.example.newsapp.databinding.ActivityRegisterBindingimport com.google.firebase.auth.FirebaseAuthclass RegisterActivity : AppCompatActivity() { private lateinit var binding: ActivityRegisterBinding private lateinit var mAuth: FirebaseAuth override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityRegisterBinding.inflate(layoutInflater) setContentView(binding.root) val actionBar = supportActionBar actionBar?.hide() mAuth = FirebaseAuth.getInstance() binding.loginNow.setOnClickListener { val intent = Intent(applicationContext, LoginActivity::class.java) startActivity(intent) finish() } binding.signupBtn.setOnClickListener { binding.progressBar.visibility = View.VISIBLE val email = binding.email.text.toString() val password = binding.password.text.toString() if (TextUtils.isEmpty(email)) { binding.progressBar.visibility = View.GONE binding.email.error = "Email cannot be empty" return@setOnClickListener } if (TextUtils.isEmpty(password)) { binding.progressBar.visibility = View.GONE binding.password.error = "Password cannot be empty" return@setOnClickListener } mAuth.createUserWithEmailAndPassword(email, password) .addOnCompleteListener { task -> binding.progressBar.visibility = View.GONE if (task.isSuccessful) { Toast.makeText( this@RegisterActivity, "Registration successful.", Toast.LENGTH_SHORT ).show() val intent = Intent(applicationContext, MainActivity::class.java) startActivity(intent) finish() } else { Toast.makeText( this@RegisterActivity, "Registration failed.", Toast.LENGTH_SHORT ).show() } } } }}SplashActivity.ktpackage com.example.newsapp.uiimport android.content.Intentimport android.os.Bundleimport android.os.Handlerimport android.os.Looperimport androidx.appcompat.app.AppCompatActivityimport com.example.newsapp.databinding.ActivitySplashBindingimport com.google.firebase.auth.FirebaseAuthclass SplashActivity : AppCompatActivity() { private lateinit var binding: ActivitySplashBinding private lateinit var mAuth: FirebaseAuth override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivitySplashBinding.inflate(layoutInflater) setContentView(binding.root) mAuth = FirebaseAuth.getInstance() Handler(Looper.getMainLooper()).postDelayed({ val currentUser = mAuth.currentUser if (currentUser != null) { val intent = Intent(applicationContext, MainActivity::class.java) startActivity(intent) finish() } else { val intent = Intent(applicationContext, LoginActivity::class.java) startActivity(intent) finish() } }, 3000) }}AddCommentAdapter.ktpackage com.example.newsapp.utilsimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.TextViewimport androidx.recyclerview.widget.RecyclerViewimport com.example.newsapp.Rimport com.example.newsapp.models.Commentclass AddCommentAdapter(private val context: MainActivity, private var comments: List) : RecyclerView.Adapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CommentViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.comment_item, parent, false) return CommentViewHolder(view) } override fun onBindViewHolder(holder: CommentViewHolder, position: Int) { val comment = comments[position] holder.commentText.text = comment.commentText holder.commentAuthor.text = comment.commentAuthor } override fun getItemCount(): Int { return comments.size } fun setComments(comments: List) { this.comments = comments notifyDataSetChanged() } inner class CommentViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val commentText: TextView = itemView.findViewById(R.id.comment_text) val commentAuthor: TextView = itemView.findViewById(R.id.comment_author) }}AddEventAdapter.ktpackage com.example.newsapp.utilsimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.TextViewimport androidx.recyclerview.widget.RecyclerViewimport com.example.newsapp.Rimport com.example.newsapp.models.CalEventTextclass AddEventAdapter(private val context: PickEventActivity, private var events: List) : RecyclerView.Adapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EventViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.event_item, parent, false) return EventViewHolder(view) } override fun onBindViewHolder(holder: EventViewHolder, position: Int) { val event = events[position] holder.eventText.text = event.eventText } override fun getItemCount(): Int { return events.size } fun setData(events: List) { this.events = events notifyDataSetChanged() } inner class EventViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val eventText: TextView = itemView.findViewById(R.id.event_text) }}CalendarViewHolder.ktpackage com.example.newsapp.utilsimport android.view.Viewimport androidx.recyclerview.widget.RecyclerViewimport com.example.newsapp.Rimport com.google.android.material.button.MaterialButtonclass CalendarViewHolder(itemView: View, private val onItemClickListener: (Int, String) -> Unit) : RecyclerView.ViewHolder(itemView) { val dayOfMonth: MaterialButton = itemView.findViewById(R.id.cellDayText) init { dayOfMonth.setOnClickListener { onItemClickListener(adapterPosition, dayOfMonth.text.toString()) } }}RoleConverter.ktpackage com.example.newsapp.utilsimport androidx.room.TypeConverterimport com.example.newsapp.models.Roleclass RoleConverter { @TypeConverter fun fromRole(role: Role): String { return role.name } @TypeConverter fun toRole(roleName: String): Role { return enumValueOf(roleName) }}WebView.ktpackage com.example.newsapp.utilsimport android.content.Contextimport android.util.AttributeSetimport android.webkit.WebViewclass WebView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : WebView(context, attrs, defStyleAttr) { init { settings.javaScriptEnabled = true }}MainViewModel.ktpackage com.example.newsapp.viewmodelimport androidx.lifecycle.LiveDataimport androidx.lifecycle.MutableLiveDataimport androidx.lifecycle.ViewModelimport androidx.lifecycle.viewModelScopeimport com.example.newsapp.models.CalEventTextimport com.example.newsapp.models.Commentimport com.example.newsapp.models.Userimport com.example.newsapp.room.repo.UserRepositoryimport kotlinx.coroutines.Dispatchersimport kotlinx.coroutines.launchclass MainViewModel(private val repository: UserRepository) : ViewModel() { private val _events = MutableLiveData>() val events: LiveData> get() = _events private val _comments = MutableLiveData>() val comments: LiveData> get() = _comments fun fetchEvents() { viewModelScope.launch(Dispatchers.IO) { val eventsList = repository.getEvents() _events.postValue(eventsList) } } fun getComments() { viewModelScope.launch(Dispatchers.IO) { val commentsList = repository.getComments() _comments.postValue(commentsList) } } fun toggleLike(email: String) { viewModelScope.launch(Dispatchers.IO) { repository.toggleLike(email) } }}class MainViewModelFactory(private val repository: UserRepository) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { if (modelClass.isAssignableFrom(MainViewModel::class.java)) { @Suppress("UNCHECKED_CAST") return MainViewModel(repository) as T } throw IllegalArgumentException("Unknown ViewModel class") }}

1) Макконнелл С. Совершенный код: практическое руководство по разработке программного обеспечения : пер. с англ. – М.: Русская редакция, 2010. – 867 с. – ISBN 5750200647, 9785750200641.
2) Жемеров Д., Исакова С. Kotlin в действии / пер. с англ. Киселев А. Н. – М.: ДМК Пресс, 2018. – 402 с.: ил. – ISBN 978-5-97060-497-7.
3) Мартин Роберт. Идеальный программист. Как стать профессионалом разработки ПО. – СПб.: Издательский дом "Питер", 2011. – 224 с. – ISBN 5459010446, 9785459010442.
4) Филлипс Билл, Стюарт Крис, Марсикано Кристин, Гарднер Брайан. Android. Программирование для профессионалов. 4-е издание. – СПб.: Издательский дом "Питер", 2020. – 704 с. – ISBN 5446116577, 9785446116577.
5) Колисниченко Денис Николаевич. Самоучитель программирования для Android. – СПб.: БХВ-Петербург, 2012. – 272 с. – ISBN 5977507704, 9785977507707.
6) Android Developers. Write your app with Android Studio. [Электронный ресурс]. – Режим доступа: https://developer.android.com/studio/write?_gl=1*139p6w7*_up*MQ..*_ga*ODA2MjE0MzMyLjE3MjA1MjIxMDc.*_ga_6HH9YJMN9M*MTcyMDUyMjEwNi4xLjAuMTcyMDUyMjEwNi4wLjAuMA...
7) Room: Android Jetpack. Room. [Электронный ресурс]. – Режим доступа: https://developer.android.com/jetpack/androidx/releases/room.
8) Firebase. Build apps with Firebase. [Электронный ресурс]. – Режим доступа: https://firebase.google.com/docs/build?hl=ru.
9) Material Components for Android. GitHub Repository. [Электронный ресурс]. – Режим доступа: https://github.com/material-components/material-components-android/tree/master.
10) Статья "Разработка архитектуры под мобильное приложение". [Электронный ресурс]. – Режим доступа: https://habr.com/ru/companies/ozontech/articles/742854/.