📅  最后修改于: 2023-12-03 15:40:21.788000             🧑  作者: Mango
随着 COVID-19 疫苗的推出,许多人都想获得疫苗接种。但是,由于疫苗供应的有限性,许多人可能会面临检查疫苗接种可用性的困难问题。这个 Android 应用程序的主要目的就是为人们提供一个快速、简单的方式来检查疫苗接种的可用性。
这个 Android 应用程序将具有以下功能:
这个 Android 应用程序将使用以下技术:
首先,我们需要创建一个新的 Android 项目,并为其命名为 "VaccineAvailability"。然后,我们需要添加所需的依赖项:
dependencies {
// Retrofit library for HTTP requests
implementation 'com.squareup.retrofit2:retrofit:2.xx.x'
implementation 'com.squareup.retrofit2:converter-gson:2.xx.x'
// Google Maps library
implementation 'com.google.android.gms:play-services-maps:xx.x.x'
// Firebase libraries
implementation 'com.google.firebase:firebase-auth:xx.x.x'
implementation 'com.google.firebase:firebase-firestore:xx.x.x'
}
接下来,我们需要添加 Google Maps API 的凭据。我们可以通过访问 Google Cloud Console 并创建一个新项目来获取凭据。
我们需要创建一个包含 "Maps SDK for Android" API 的 API 密钥。然后将其添加到我们的 Android 项目中的 AndroidManifest.xml
文件中:
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="YOUR_API_KEY_HERE" />
我们还需要在 AndroidManifest.xml
文件中添加以下权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
现在,我们可以开始编写代码了。我们需要创建一个包含以下类的包:
model
:包含数据模型类。network
:包含 Retrofit 的 API 接口类。view
:包含与 UI 相关的类。ViewModel
:包含视图模型类。repository
:包含数据处理逻辑的类。我们需要使用 Open Vaccine API 来获取可用的疫苗接种信息。我们需要创建一个 API 接口类,在其中定义我们需要使用的 API 请求:
interface OpenVaccineApiService {
@GET("v1/vaccines")
suspend fun getVaccineLocations(
@Query("date") date: String,
@Query("location") location: String,
@Query("dose") dose: String
): List<VaccineLocationResponse>
}
接下来,我们需要创建 VaccineLocationResponse
模型类,以便解析 API 响应:
data class VaccineLocationResponse(
val name: String,
val address: String,
val city: String,
val state: String,
val zip: String,
val availability: List<Availability>,
val phone: String,
val website: String
)
data class Availability(
val date: String,
val available_capacity_dose1: Int,
val available_capacity_dose2: Int
)
我们需要使用 Retrofit 库与 API 交互。我们需要创建一个包含 Retrofit
和 OkHttp
实例的单例类:
object RetrofitInstance {
private const val BASE_URL = "https://open-vaccine-api.herokuapp.com/"
private val client = OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().apply {
level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
})
.build()
private val retrofitInstance: Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
}
val openVaccineApi: OpenVaccineApiService by lazy {
retrofitInstance.create(OpenVaccineApiService::class.java)
}
}
接下来,我们需要创建一个类来处理我们的数据。这个类将使用我们的 API 接口来搜索可用的疫苗接种点:
class VaccineRepository {
suspend fun getVaccineLocations(
date: String,
location: String,
dose: String
): List<VaccineLocation> {
// Call API using Retrofit
val response = RetrofitInstance.openVaccineApi.getVaccineLocations(date, location, dose)
return response.map { it.toVaccineLocation() }
}
private fun VaccineLocationResponse.toVaccineLocation(): VaccineLocation {
val availability = availability.find { it.available_capacity_dose1 > 0 || it.available_capacity_dose2 > 0 }
?: Availability(date = "", available_capacity_dose1 = 0, available_capacity_dose2 = 0)
return VaccineLocation(
name = name,
address = address,
city = city,
state = state,
zip = zip,
availability = availability,
phone = phone,
website = website
)
}
}
现在,我们可以创建 VaccineLocation
和 VaccineAvailability
模型类,以封装我们的数据。我们需要使用 LiveData
类型来通知 UI 层数据的变化:
data class VaccineLocation(
val name: String,
val address: String,
val city: String,
val state: String,
val zip: String,
val availability: Availability,
val phone: String,
val website: String,
var isFavorite: Boolean = false
)
data class VaccineAvailability(
val location: VaccineLocation?,
val date: String?,
val dose1Availability: Int,
val dose2Availability: Int
)
接下来,我们需要创建一个 VaccineViewModel
的类,该类将负责处理 UI 相关的逻辑:
class VaccineViewModel : ViewModel() {
private val repository = VaccineRepository()
private val _vaccineLocations = MutableLiveData<List<VaccineLocation>>()
val vaccineLocations = _vaccineLocations as LiveData<List<VaccineLocation>>
private val _favoriteLocations = MutableLiveData<List<VaccineLocation>>()
val favoriteLocations = _favoriteLocations as LiveData<List<VaccineLocation>>
private val _vaccineAvailability = MutableLiveData<VaccineAvailability>()
val vaccineAvailability = _vaccineAvailability as LiveData<VaccineAvailability>
fun getVaccineLocations(date: String, location: String, dose: String) {
viewModelScope.launch {
_vaccineLocations.value = repository.getVaccineLocations(date, location, dose)
}
}
fun getFavoriteLocations() {
viewModelScope.launch {
_favoriteLocations.value = repository.getFavoriteLocations()
}
}
fun updateFavoriteLocation(location: VaccineLocation) {
viewModelScope.launch {
repository.updateFavoriteLocation(location)
}
}
fun getVaccineAvailability(location: VaccineLocation, date: String, dose: String) {
viewModelScope.launch {
val availability = repository.getVaccineAvailability(location, date, dose)
_vaccineAvailability.value = if (availability != null) {
VaccineAvailability(
location = location,
date = availability.date,
dose1Availability = availability.available_capacity_dose1,
dose2Availability = availability.available_capacity_dose2
)
} else {
null
}
}
}
}
我们将使用 Firebase 来进行身份验证和存储用户数据。我们需要将 Firebase 添加到我们的 Android 项目中。我们可以通过访问 Firebase 官方网站 创建一个新的项目并添加 Firebase 到我们的 Android 应用程序中。
我们需要创建一个带有 Firebase 实例的单例类:
object FirebaseInstance {
val auth: FirebaseAuth = Firebase.auth
val firestore: FirebaseFirestore = Firebase.firestore
}
接下来,我们需要创建一个 FirebaseRepository
类,该类将负责处理与 Firebase 相关的逻辑:
class FirebaseRepository {
suspend fun signIn(email: String, password: String) {
FirebaseInstance.auth.signInWithEmailAndPassword(email, password).await()
}
suspend fun signOut() {
FirebaseInstance.auth.signOut()
}
suspend fun isUserLoggedIn(): Boolean {
return FirebaseInstance.auth.currentUser != null
}
suspend fun getUserData(): User? {
val user = FirebaseInstance.auth.currentUser ?: return null
val userDoc = FirebaseInstance.firestore.collection("users").document(user.uid).get().await()
return if (userDoc.exists()) {
userDoc.toObject(User::class.java)
} else {
createUser(user)
}
}
private suspend fun createUser(firebaseUser: FirebaseUser): User {
val newUser = User(firebaseUser.uid, firebaseUser.displayName ?: "", firebaseUser.email ?: "")
FirebaseInstance.firestore.collection("users").document(firebaseUser.uid).set(newUser).await()
return newUser
}
suspend fun getFavoriteLocations(): List<VaccineLocation> {
val user = FirebaseInstance.auth.currentUser ?: return emptyList()
val snapshot = FirebaseInstance.firestore.collection("favorites").document(user.uid)
.collection("locations").get().await()
return snapshot.documents.map { it.toObject(VaccineLocation::class.java)!! }
}
suspend fun updateFavoriteLocation(location: VaccineLocation) {
val user = FirebaseInstance.auth.currentUser ?: return
val locationMap = mapOf(
"name" to location.name,
"address" to location.address,
"city" to location.city,
"state" to location.state,
"zip" to location.zip,
"availability" to mapOf(
"date" to location.availability.date,
"available_capacity_dose1" to location.availability.available_capacity_dose1,
"available_capacity_dose2" to location.availability.available_capacity_dose2
),
"phone" to location.phone,
"website" to location.website,
"is_favorite" to location.isFavorite
)
FirebaseInstance.firestore.collection("favorites").document(user.uid).collection("locations")
.document(location.name).set(locationMap).await()
}
}
最后,我们需要在 MainActivity
类中创建以下类:
VaccineListAdapter
:用于展示可用的疫苗接种点的 RecyclerView 适配器。FavoriteListAdapter
:用于展示收藏的疫苗接种点的 RecyclerView 适配器。LocationPickerDialogFragment
:用于选择用户位置的 DialogFragment。DatePickerDialogFragment
:用于选择日期的 DialogFragment。TimePickerDialogFragment
:用于选择时间的 DialogFragment。我们还需要在 MainActivity
类中创建以下方法:
setupNavigation()
:用于设置底部导航栏和 ViewPager。showLocationPickerDialog()
:用于显示选择位置的 DialogFragment。showDatePickerDialog()
:用于显示选择日期的 DialogFragment。showTimePickerDialog()
:用于显示选择时间的 DialogFragment。searchAvailability()
:用于搜索可用的疫苗接种点。updateFavoriteLocations()
:用于更新收藏的疫苗接种点。这个 Android 应用程序将为用户提供一个简单、快速的方式来搜索可用的疫苗接种点。使用 Retrofit 库和 Google Maps API,我们可以轻松地与 Open Vaccine API 交互,并展示疫苗接种点的位置。使用 Firebase 实例,我们可以轻松地进行身份验证和存储用户数据。