Advertisement
tuomasvaltanen

Untitled

Apr 11th, 2023 (edited)
191
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.20 KB | None | 0 0
  1. // Edistynyt mobiiliohjelmointi, 11.4.2023
  2.  
  3. // tehdään ensin uusi fragment mobile_navigationin kautta, ei laiteta päävalikkoon
  4. // esim. CityWeatherFragment , action MapsFragmentista -> CityWeatherFragment
  5. // CityWeatherFragmentiin argumentteja kaksi: lat ja lon (molemmat tyypiltään Float)
  6.  
  7. // esim:
  8.  
  9. class CityWeatherFragment : Fragment() {
  10. private var _binding: FragmentCityWeatherBinding? = null
  11.  
  12. // get fragment parameters from previous fragment
  13. val args: CityWeatherFragmentArgs by navArgs()
  14.  
  15. // This property is only valid between onCreateView and
  16. // onDestroyView.
  17. private val binding get() = _binding!!
  18. override fun onCreateView(
  19. inflater: LayoutInflater,
  20. container: ViewGroup?,
  21. savedInstanceState: Bundle?
  22. ): View? {
  23. _binding = FragmentCityWeatherBinding.inflate(inflater, container, false)
  24. val root: View = binding.root
  25.  
  26.  
  27. return root
  28. }
  29. override fun onDestroyView() {
  30. super.onDestroyView()
  31. _binding = null
  32. }
  33. }
  34.  
  35. // kun action ja parametrit ovat kunnossa, voidaan onMarkerClickistä siirtyä CityWeatherFragmentiin
  36. // kahden parametrin kera
  37.  
  38. // tämä metodi vastaa siitä, kun jotakin markeria klikataan kartalla
  39. override fun onMarkerClick(p0: Marker): Boolean {
  40. Log.d("TESTI", "Marker CLICK!")
  41.  
  42. // klikatun markerin koordinaatit löytyvät p0-muuttujan positionista:
  43. Log.d("TESTI", p0.position.latitude.toString())
  44. Log.d("TESTI", p0.position.longitude.toString())
  45.  
  46. // jos markerilla on tagi, tällä tavalla sen saa haettua siitä
  47. Log.d("TESTI", p0.tag.toString())
  48.  
  49. // tallennetaan koordinaatit apumuuttujiin selkeyden vuoksi
  50. val lat = p0.position.latitude.toFloat()
  51. val lon = p0.position.longitude.toFloat()
  52.  
  53. // actionin avulla siirrytään CityWeatherFragmentiin ja lähetetään
  54. // tarvittavat koordinaatit parametreina
  55. val action = MapsFragmentDirections.actionMapsFragmentToCityWeatherFragment(lat, lon)
  56. findNavController().navigate(action)
  57.  
  58. return false
  59. }
  60.  
  61.  
  62. // perus Volley-runko CityWeatherFragmentiin, sekä apufunktio minne keskitetään säädatan hakemiskoodi
  63.  
  64. class CityWeatherFragment : Fragment() {
  65. private var _binding: FragmentCityWeatherBinding? = null
  66.  
  67. // get fragment parameters from previous fragment
  68. val args: CityWeatherFragmentArgs by navArgs()
  69.  
  70. // This property is only valid between onCreateView and
  71. // onDestroyView.
  72. private val binding get() = _binding!!
  73. override fun onCreateView(
  74. inflater: LayoutInflater,
  75. container: ViewGroup?,
  76. savedInstanceState: Bundle?
  77. ): View? {
  78. _binding = FragmentCityWeatherBinding.inflate(inflater, container, false)
  79. val root: View = binding.root
  80.  
  81. Log.d("TESTI", "CityWeatherFragment START")
  82. Log.d("TESTI", args.lat.toString())
  83. Log.d("TESTI", args.lon.toString())
  84.  
  85. // kutsutaan apufunktiota
  86. getWeatherData()
  87.  
  88. return root
  89. }
  90.  
  91. // apufunktio, johon voidaan eriyttää säädatan hakeminen ja käsittely
  92. fun getWeatherData() {
  93. // this is the url where we want to get our data from
  94.  
  95. // OpenWeatherMap-osoite on tätä muotoa:
  96. // https://api.openweathermap.org/data/2.5/weather?lat=66.50247&lon=25.73009&units=metric&appid=OMAKEYTAHAN
  97. val JSON_URL = "THE URL OF THE DATA API"
  98.  
  99. // Request a string response from the provided URL.
  100. val stringRequest: StringRequest = object : StringRequest(
  101. Request.Method.GET, JSON_URL,
  102. Response.Listener { response ->
  103.  
  104. // print the response as a whole
  105. // we can use GSON to modify this response into something more usable
  106. Log.d("ADVTECH", response)
  107.  
  108. },
  109. Response.ErrorListener {
  110. // typically this is a connection error
  111. Log.d("ADVTECH", it.toString())
  112. })
  113. {
  114. @Throws(AuthFailureError::class)
  115. override fun getHeaders(): Map<String, String> {
  116.  
  117. // basic headers for the data
  118. val headers = HashMap<String, String>()
  119. headers["Accept"] = "application/json"
  120. headers["Content-Type"] = "application/json; charset=utf-8"
  121. return headers
  122. }
  123. }
  124.  
  125. // Add the request to the RequestQueue. This has to be done in both getting and sending new data.
  126. // if using this in an activity, use "this" instead of "context"
  127. val requestQueue = Volley.newRequestQueue(context)
  128. requestQueue.add(stringRequest)
  129. }
  130.  
  131. override fun onDestroyView() {
  132. super.onDestroyView()
  133. _binding = null
  134. }
  135. }
  136.  
  137. // ajatuksena on rakentaa lennosta tarvittava JSON_URL, joka hakee tietyn kaupungin säätiedotus koordinaattien perusteella
  138.  
  139. // esim.
  140. fun getWeatherData() {
  141. // haetaan local.properties -tiedostosta OpenWeatherMapin API key
  142. // huom: local.propertiesin muuttujat päivittyvät vasta kun projektia käytetään
  143. // emulaattorissa päällä!
  144. val API_KEY = BuildConfig.OPENWEATHER_API_KEY
  145.  
  146. // OpenWeatherMap-osoite on tätä muotoa:
  147. // https://api.openweathermap.org/data/2.5/weather?lat=66.50247&lon=25.73009&units=metric&appid=OMAKEYTAHAN
  148.  
  149. // eli rakennetaan Kotlinissa osoite lat/lon ja OPENWEATHER_API_KEY:n pohjalta:
  150. val JSON_URL = "https://api.openweathermap.org/data/2.5/weather?lat=${args.lat}&lon=${args.lon}&units=metric&appid=${API_KEY}"
  151.  
  152. // Request a string response from the provided URL.
  153. val stringRequest: StringRequest = object : StringRequest(
  154. Request.Method.GET, JSON_URL,
  155. Response.Listener { response ->
  156.  
  157. .... jne jne jne....
  158.  
  159.  
  160.  
  161. // datan muuntaminen JSONista -> CityWeather-dataksi Kotliniin:
  162.  
  163. val gson = GsonBuilder().setPrettyPrinting().create()
  164.  
  165. // Request a string response from the provided URL.
  166. val stringRequest: StringRequest = object : StringRequest(
  167. Request.Method.GET, JSON_URL,
  168. Response.Listener { response ->
  169. // print the response as a whole
  170. // we can use GSON to modify this response into something more usable
  171. Log.d("TESTI", response)
  172.  
  173. // datassa tulee vain yhden kaupungin JSON, muutetaan GSON:illa käyttökelpoiseen muotoon
  174. // tämä vaatii CityWeather-luokan, joka tehdään esimerkkidatan pohjalta
  175. // json2kt.com -palvelussa (ks. edellinen luento, loppuosa)
  176. var item : CityWeather = gson.fromJson(response, CityWeather::class.java)
  177.  
  178. // haetaan testimielessä pari muuttujaa
  179. // huom main? tarkoittaa sitä, että jos main-olio
  180. // on arvoltaan null, koodi ei yritä väkisin ajaa
  181. // koodia läpi koska se tilttaisi
  182. // tämä liittyy ns. null-safety -ominaisuuteen ohjelmointikielessä
  183. val temperature = item.main?.temp
  184. val humidity = item.main?.humidity
  185.  
  186. // nämä muuttujat voi halutessaan laittaa vaikka ulkoasuun:
  187. // esim. jos CityWeatherin xml-ulkoasussa on TextView, jonka id on textView_city_temperature
  188. // voitaisiin laittaa se näkyviin näin:
  189. // binding.textViewCityTemperature.text = "${temperature}C"
  190.  
  191. // kokeillaan lokittaa tarkemmat tiedot
  192. Log.d("TESTI", "Lämpötila: ${temperature}C, kosteusprosentti: ${humidity}%")
  193.  
  194. },
  195. Response.ErrorListener {
  196. // typically this is a connection error
  197. Log.d("TESTI", it.toString())
  198. })
  199. {
  200.  
  201. ... jne jne ....
  202.  
  203.  
  204. // OSMDroid, eli OpenStreetMap Androidissa, module.gradle import:
  205.  
  206. implementation 'org.osmdroid:osmdroid-android:6.1.16'
  207.  
  208. // tämän ohjeen pohjalta toimitaan:
  209.  
  210. https://github.com/osmdroid/osmdroid/wiki/How-to-use-the-osmdroid-library-(Kotlin)
  211.  
  212. Päivitetään permissionit seuraavanlaiseksi:
  213.  
  214. <uses-permission android:name="android.permission.INTERNET" />
  215. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  216. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  217. <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  218.  
  219. // Nykypäivänä permissionit pitää kysyä myös koodin kautta, pelkkä AndroidManifest ei riitä yksistään
  220. // helpoiten tämän voi tehdä Activityyn, esim. MainActivity:
  221.  
  222. // apufunktio, tarkistetaan oikeudet
  223. fun hasPermissions(context: Context, vararg permissions: String): Boolean = permissions.all {
  224. ActivityCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
  225. }
  226.  
  227. // ja tämä koodi onCreaten loppupuolelle:
  228.  
  229. // lista permissioneista, joita ohjelma käyttää
  230. // TÄMÄN PITÄÄ TÄSMÄTÄ ANDROIDMANIFESTIN KANSSA
  231. val PERMISSION_ALL = 123
  232.  
  233. val PERMISSIONS = arrayOf(
  234. android.Manifest.permission.INTERNET,
  235. android.Manifest.permission.ACCESS_FINE_LOCATION,
  236. android.Manifest.permission.ACCESS_COARSE_LOCATION,
  237. android.Manifest.permission.ACCESS_NETWORK_STATE
  238. )
  239.  
  240. // tarkistetaan kaikki oikeudet kerralla
  241. if (!hasPermissions(this, *PERMISSIONS)) {
  242. ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL)
  243. }
  244.  
  245.  
  246.  
  247. // ulkoasu OpenStreetMapFragmentille:
  248.  
  249. <?xml version="1.0" encoding="utf-8"?>
  250. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  251. android:orientation="vertical"
  252. android:layout_width="fill_parent"
  253. android:layout_height="fill_parent">
  254. <org.osmdroid.views.MapView android:id="@+id/map"
  255. android:layout_width="fill_parent"
  256. android:layout_height="fill_parent" />
  257. </LinearLayout>
  258.  
  259. // ohjeen mukaista pohjaa kun säädetään, saadaan seuraavanlainen pohja:
  260.  
  261. class OpenStreetMapFragment : Fragment() {
  262. private var _binding: FragmentOpenStreetMapBinding? = null
  263. // This property is only valid between onCreateView and
  264. // onDestroyView.
  265. private val binding get() = _binding!!
  266. override fun onCreateView(
  267. inflater: LayoutInflater,
  268. container: ViewGroup?,
  269. savedInstanceState: Bundle?
  270. ): View? {
  271. _binding = FragmentOpenStreetMapBinding.inflate(inflater, container, false)
  272. val root: View = binding.root
  273.  
  274. // muutetaan activity Context-tyyppiseksi lennosta, jotta se kelpaa uudelle PreferenceManagerille
  275. // tietotyypin muuntaminen luokasta toiseen on nimeltään typecasting
  276. // jotta deprecated saadaan koodista pois, muuta ylhäältä import tähän:
  277. // import androidx.preference.PreferenceManager
  278. // ja lisää build.gradleen: implementation 'androidx.preference:preference:1.2.0'
  279. getInstance().load(activity, PreferenceManager.getDefaultSharedPreferences(activity as Context))
  280.  
  281. // asetetaan mapViewiin tietty ulkonäkö
  282. binding.map.setTileSource(TileSourceFactory.MAPNIK)
  283.  
  284. // Zoomataan rovaniemelle
  285. val mapController = binding.map.controller
  286. mapController.setZoom(19.0)
  287. val startPoint = GeoPoint(66.50247438013193, 25.7300978471244);
  288. mapController.setCenter(startPoint);
  289.  
  290. return root
  291. }
  292.  
  293. override fun onDestroyView() {
  294. super.onDestroyView()
  295. _binding = null
  296. }
  297. }
  298.  
  299. // marker-koodia testattavaksi:
  300.  
  301. // kokeillaan lisätä Marker Rovaniemelle
  302. val firstMarker = Marker(binding.map)
  303. firstMarker.position = startPoint
  304. firstMarker.title = "Rovaniemi!"
  305. firstMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER)
  306. binding.map.overlays.add(firstMarker)
  307. binding.map.invalidate()
  308.  
  309. // kun markkeria klikataan:
  310. firstMarker.setOnMarkerClickListener { marker, mapView ->
  311. // sijainti, esim: marker.position.latitude
  312.  
  313. Log.d("TESTI", "Marker click!")
  314.  
  315. return@setOnMarkerClickListener false
  316. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement