1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
| package com.example.diary_3.activity import androidx.appcompat.app.AlertDialog import android.view.View import android.widget.EditText import com.example.diary_3.utils.DateUtils import android.content.Intent import android.content.pm.PackageManager import android.net.Uri import android.os.Bundle import android.os.Looper import android.provider.MediaStore import android.util.Log import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import com.bumptech.glide.Glide import com.bumptech.glide.request.RequestOptions import com.example.diary_3.R import com.example.diary_3.database.Diary import com.example.diary_3.database.DiaryDatabase import com.example.diary_3.databinding.ActivityAddDiaryBinding import com.example.diary_3.model.CityResponse import com.example.diary_3.model.WeatherResponse import com.example.diary_3.network.RetrofitClient import com.example.diary_3.network.WeatherApi import com.example.diary_3.utils.LocationUtils import retrofit2.Call import retrofit2.Callback import retrofit2.Response import java.util.Calendar import java.util.concurrent.Executors
class AddDiaryActivity : AppCompatActivity() { private val selectedLocalImageUris = mutableListOf<Uri>() private val networkImageUrls = mutableListOf<String>() private val API_KEY = "670ca929136a456992608cd2e794df24" private lateinit var binding: ActivityAddDiaryBinding private var selectedDate: Calendar = Calendar.getInstance() private lateinit var diaryDatabase: DiaryDatabase private lateinit var locationUtils: LocationUtils private val PERMISSION_REQUEST_CODE = 1 private var selectedLocalImageUri: Uri? = null private var networkImageUrl: String? = null
private fun hasPermission(permission: String): Boolean { return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED }
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityAddDiaryBinding.inflate(layoutInflater) setContentView(binding.root)
diaryDatabase = DiaryDatabase.getInstance(this) locationUtils = LocationUtils(this)
binding.selectImageButton.setOnClickListener { pickLocalImage() }
binding.addNetworkImageButton.setOnClickListener { // 创建一个输入框 val input = EditText(this) input.hint = "请输入有效的图片链接"
// 构建对话框 AlertDialog.Builder(this) .setTitle("输入图片URL") .setView(input) .setPositiveButton("确定") { dialog, which -> val url = input.text.toString().trim() if (url.isNotBlank()) { networkImageUrl = url Glide.with(this) .load(url) .placeholder(R.drawable.loading_placeholder) // 加载过程中的占位符图片 .apply(RequestOptions.circleCropTransform()) .error(R.drawable.no) // 加载失败时显示的图片 .into(binding.selectedImageView) binding.selectedImageView.visibility = View.VISIBLE } else { Toast.makeText(this, "请输入有效的图片链接", Toast.LENGTH_SHORT).show() binding.selectedImageView.visibility = View.GONE } } .setNegativeButton("取消") { dialog, which -> dialog.cancel() } .show() }
binding.saveDiaryButton.setOnClickListener { saveDiary() }
// 新增按钮:点击刷新地点和天气 binding.refreshWeatherLocationButton.setOnClickListener { getLocation() }
val permissionsToRequest = mutableListOf<String>()
if (!hasPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)) { permissionsToRequest.add(android.Manifest.permission.ACCESS_FINE_LOCATION) }
if (!hasPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)) { permissionsToRequest.add(android.Manifest.permission.READ_EXTERNAL_STORAGE) }
if (permissionsToRequest.isNotEmpty()) { ActivityCompat.requestPermissions( this, permissionsToRequest.toTypedArray(), PERMISSION_REQUEST_CODE ) } else { getLocation() } }
private fun pickLocalImage() { val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) startActivityForResult(intent, 1) }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1 && resultCode == RESULT_OK && data != null) { selectedLocalImageUri = data.data Glide.with(this) .load(selectedLocalImageUri) .into(binding.selectedImageView) binding.selectedImageView.visibility = android.view.View.VISIBLE } }
private fun getLocation() { locationUtils.getLocation { location -> if (location != null) { val latitude = location.latitude val longitude = location.longitude Log.d("AddDiaryActivity", "获取到的经纬度: 纬度 $latitude, 经度 $longitude") // 格式化经纬度字符串,注意这里 longitude 和 latitude 的顺序可以根据接口要求调整 val loc = String.format("%.2f,%.2f", location.longitude, location.latitude) Executors.newSingleThreadExecutor().execute { runOnUiThread { binding.locationTextView.text = loc getCityId(loc) } } } else { runOnUiThread { Toast.makeText(this, "无法获取当前位置", Toast.LENGTH_SHORT).show() } } } }
private fun showToastOnUiThread(message: String) { if (Looper.myLooper() == Looper.getMainLooper()) { Toast.makeText(this, message, Toast.LENGTH_SHORT).show() } else { runOnUiThread { Toast.makeText(this, message, Toast.LENGTH_SHORT).show() } } }
private fun getCityId(cityName: String) { val weatherApi = RetrofitClient.geoInstance.create(WeatherApi::class.java) weatherApi.getCityInfo(API_KEY, cityName).enqueue(object : Callback<CityResponse> { override fun onResponse(call: Call<CityResponse>, response: Response<CityResponse>) { if (response.isSuccessful && response.body()?.code == "200") { val cityLocation = response.body()?.location?.firstOrNull() if (cityLocation != null) { binding.locationTextView.text = cityLocation.name getWeatherInfo(cityLocation.id) } } else { Log.e("AddDiaryActivity", "获取城市 ID 失败: ${response.message()}, 响应代码: ${response.code()}, 响应体: ${response.errorBody()?.string()}") showToastOnUiThread("获取城市 ID 失败") } }
override fun onFailure(call: Call<CityResponse>, t: Throwable) { Log.e("AddDiaryActivity", "获取城市 ID 网络请求失败: ${t.message}", t) showToastOnUiThread("获取城市 ID 网络请求失败") } }) }
private fun getWeatherInfo(cityId: String) { val weatherApi = RetrofitClient.weatherInstance.create(WeatherApi::class.java) weatherApi.getWeatherInfo(API_KEY, cityId).enqueue(object : Callback<WeatherResponse> { override fun onResponse(call: Call<WeatherResponse>, response: Response<WeatherResponse>) { if (response.isSuccessful && response.body()?.code == "200") { val today = DateUtils.formatDate(Calendar.getInstance().time) val todayWeather = response.body()?.daily?.firstOrNull { it.fxDate == today } if (todayWeather != null) { val weatherText = todayWeather.textDay binding.weatherTextView.text = weatherText } } else { Log.e("AddDiaryActivity", "获取天气信息失败: ${response.message()}, 响应代码: ${response.code()}, 响应体: ${response.errorBody()?.string()}") showToastOnUiThread("获取天气信息失败") } }
override fun onFailure(call: Call<WeatherResponse>, t: Throwable) { Log.e("AddDiaryActivity", "获取天气信息网络请求失败: ${t.message}", t) showToastOnUiThread("获取天气信息网络请求失败") } }) }
private fun saveDiary() { Executors.newSingleThreadExecutor().execute { val title = binding.titleEditText.text.toString() val content = binding.contentEditText.text.toString() val localImagePath = selectedLocalImageUri?.toString() val date = DateUtils.formatDate(Calendar.getInstance().time) val weather = binding.weatherTextView.text.toString() val location = binding.locationTextView.text.toString()
val diary = Diary( title = title, content = content, localImagePath = localImagePath, networkImageUrl = networkImageUrl, date = date, weather = weather, location = location )
diaryDatabase.diaryDao().insertDiary(diary) runOnUiThread { Toast.makeText(this, "日记保存成功", Toast.LENGTH_SHORT).show() val intent = Intent("SAVED") // 或者 "com.example.app.DIARY_SAVED" sendBroadcast(intent) finish() } } } }
|