Weather app #14 : Показ прогноза на экране

MainFragment

import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.location.Geocoder
import android.location.Location
import android.location.LocationManager
import android.os.Bundle
import android.os.Looper
import android.provider.Settings
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.activityViewModels
import com.android.volley.Request
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import com.google.android.gms.location.*
import com.google.android.gms.tasks.*
import com.google.android.material.tabs.TabLayoutMediator
import com.meter_alc_rgb.weatherappcurse.MainViewModel
import com.meter_alc_rgb.weatherappcurse.R
import com.meter_alc_rgb.weatherappcurse.adapters.VpAdapter
import com.meter_alc_rgb.weatherappcurse.adapters.WeatherItem
import com.meter_alc_rgb.weatherappcurse.databinding.FragmentMainBinding
import com.meter_alc_rgb.weatherappcurse.utils.DialogManager
import com.meter_alc_rgb.weatherappcurse.utils.TimeUtils
import com.squareup.picasso.Picasso
import org.json.JSONObject
import java.lang.NumberFormatException

const val API_KEY = "Ваш API ключ"

class MainFragment : Fragment() {
private var mFusedLocationClient: FusedLocationProviderClient? = null
private val model : MainViewModel by activityViewModels()
private val fList = listOf<Fragment>(
HoursFragment.newInstance(),
DaysFragment.newInstance()
)
private val tList = listOf(
"Hours",
"Days"
)
private var isPermissionGranted = false
private lateinit var pLauncher: ActivityResultLauncher<String>
private lateinit var binding: FragmentMainBinding

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentMainBinding.inflate(layoutInflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.ibRefresh.setOnClickListener {
binding.tvCurrentTemp.text = ""
getLocation()
}
model.liveDataCurrent.observe(viewLifecycleOwner){
binding.apply {
val cTemp = try{
"${it.currentTemp.toFloat().toInt()}º"
} catch (i: NumberFormatException){
""
}
val temp = "${it.maxTemp.toFloat().toInt()}º/${it.minTemp.toFloat().toInt()}º"
tvCurrentTemp.text = if(it.currentTemp.isEmpty()) "${it.maxTemp.toFloat().toInt()}º/${it.minTemp.toFloat().toInt()}º" else cTemp
tvMaxMinTemp.text = if(it.currentTemp.isNotEmpty()) temp else ""
tvWeatherType.text = it.sunType
tvCity.text = it.city
tvDate.text = if(it.currentTemp.isEmpty())
TimeUtils.changePattern(
"yyyy-MM-dd",
"dd MMM yyyy",
it.time
)
else TimeUtils.changePattern(
"yyyy-MM-dd hh:mm",
"dd MMM yyyy / HH:mm",
it.time)
Picasso.get().load("https:" + it.imageUri).into(imWeather)
}
}
permissionListener()
checkLocationPermission()
initVp()
checkLocationEnabled()
}

private fun checkLocationEnabled(){
val m = activity?.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val isEnabled = m.isProviderEnabled(LocationManager.GPS_PROVIDER)
if (!isEnabled){
DialogManager.showLocationEnableDialog(activity as AppCompatActivity,
object : DialogManager.Listener{
override fun onClickYes() {
startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS))
}
})
}
}

private fun initVp() = with(binding){
val adapter = VpAdapter(activity as AppCompatActivity, fList)
vp.adapter = adapter
TabLayoutMediator(tabLayout, vp){
tab, pos-> tab.text = tList[pos]
}.attach()
}

private fun checkLocationPermission(){
if(checkPermission(Manifest.permission.ACCESS_FINE_LOCATION)){
isPermissionGranted = true
initLocation()
getLocation()
} else {
pLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}
}

private fun permissionListener(){
pLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
){
isPermissionGranted = it
if(isPermissionGranted){
initLocation()
getLocation()
}
}
}

private fun getResult(name: String){
val url = "https://api.weatherapi.com/v1/forecast.json" +
"?key=$API_KEY&q=$name&days=10&aqi=no&alerts=no"
val queue = Volley.newRequestQueue(context)
val stringRequest = StringRequest(
Request.Method.GET,
url,
{
response->
binding.pbRefresh.visibility = View.GONE
getDaysList(response)
},
{
Log.d("MyLog","Volley error: $it")
}
)
queue.add(stringRequest)
}

private fun getDaysList(data: String){
val gObject = JSONObject(data)
val forecastObject = gObject.getJSONObject("forecast")
val daysArray = forecastObject.getJSONArray("forecastday")
val list = ArrayList<WeatherItem>()
for(i in 0 until daysArray.length()){
val day = daysArray[i] as JSONObject
val item = WeatherItem(
gObject.getJSONObject("location").getString("name"),
day.getString("date"),
day.getJSONObject("day")
.getJSONObject("condition")
.getString("text"),
"",
day.getJSONObject("day").getString("maxtemp_c"),
day.getJSONObject("day").getString("mintemp_c"),
day.getJSONObject("day")
.getJSONObject("condition")
.getString("icon"),
day.getJSONArray("hour").toString()
)
list.add(item)
}
getCurrentWeather(gObject, list, 0)
model.liveDayList.value = list
}

private fun getCurrentWeather(jObject: JSONObject, list: List<WeatherItem>, index: Int){
val item = WeatherItem(
jObject.getJSONObject("location").getString("name"),
jObject.getJSONObject("current").getString("last_updated"),
jObject.getJSONObject("current")
.getJSONObject("condition")
.getString("text"),
jObject.getJSONObject("current").getString("temp_c"),
list[index].maxTemp,
list[index].minTemp,
jObject.getJSONObject("current")
.getJSONObject("condition")
.getString("icon"),
list[index].hours
)
model.liveDataCurrent.value = item
}

private fun initLocation(){
mFusedLocationClient =
LocationServices.getFusedLocationProviderClient(activity as AppCompatActivity)
}

private fun getLocation(){
if (
!checkPermission(Manifest.permission.ACCESS_FINE_LOCATION)
&& !checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION
)) {
return
}
binding.pbRefresh.visibility = View.VISIBLE
val cts = CancellationTokenSource()
val task = cts.token
val taskL = mFusedLocationClient
?.getCurrentLocation(
LocationRequest.PRIORITY_HIGH_ACCURACY,
task
) as Task<Location>
taskL.addOnCompleteListener {
if(it.result != null){
val latLon = "${it.result.latitude},${it.result.longitude}"
getResult(latLon)
} else {
Toast.makeText(activity, "Location not found", Toast.LENGTH_LONG).show()
}
}

}

override fun onDetach() {
super.onDetach()
}

companion object {
@JvmStatic
fun newInstance() = MainFragment()
}
}

2 комментария для “Weather app #14 : Показ прогноза на экране”

  1. Здравствуйте подскажите пожалуйста если вам не трудно почему в mainfragment когда я инициализирую viewmodel андроид студио пишет что не видит activityViewModels ?

Добавить комментарий

Ваш адрес email не будет опубликован.