Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Edistynyt mobiiliohjelmointi, 11.4.2023
- // tehdään ensin uusi fragment mobile_navigationin kautta, ei laiteta päävalikkoon
- // esim. CityWeatherFragment , action MapsFragmentista -> CityWeatherFragment
- // CityWeatherFragmentiin argumentteja kaksi: lat ja lon (molemmat tyypiltään Float)
- // esim:
- class CityWeatherFragment : Fragment() {
- private var _binding: FragmentCityWeatherBinding? = null
- // get fragment parameters from previous fragment
- val args: CityWeatherFragmentArgs by navArgs()
- // This property is only valid between onCreateView and
- // onDestroyView.
- private val binding get() = _binding!!
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- _binding = FragmentCityWeatherBinding.inflate(inflater, container, false)
- val root: View = binding.root
- return root
- }
- override fun onDestroyView() {
- super.onDestroyView()
- _binding = null
- }
- }
- // kun action ja parametrit ovat kunnossa, voidaan onMarkerClickistä siirtyä CityWeatherFragmentiin
- // kahden parametrin kera
- // tämä metodi vastaa siitä, kun jotakin markeria klikataan kartalla
- override fun onMarkerClick(p0: Marker): Boolean {
- Log.d("TESTI", "Marker CLICK!")
- // klikatun markerin koordinaatit löytyvät p0-muuttujan positionista:
- Log.d("TESTI", p0.position.latitude.toString())
- Log.d("TESTI", p0.position.longitude.toString())
- // jos markerilla on tagi, tällä tavalla sen saa haettua siitä
- Log.d("TESTI", p0.tag.toString())
- // tallennetaan koordinaatit apumuuttujiin selkeyden vuoksi
- val lat = p0.position.latitude.toFloat()
- val lon = p0.position.longitude.toFloat()
- // actionin avulla siirrytään CityWeatherFragmentiin ja lähetetään
- // tarvittavat koordinaatit parametreina
- val action = MapsFragmentDirections.actionMapsFragmentToCityWeatherFragment(lat, lon)
- findNavController().navigate(action)
- return false
- }
- // perus Volley-runko CityWeatherFragmentiin, sekä apufunktio minne keskitetään säädatan hakemiskoodi
- class CityWeatherFragment : Fragment() {
- private var _binding: FragmentCityWeatherBinding? = null
- // get fragment parameters from previous fragment
- val args: CityWeatherFragmentArgs by navArgs()
- // This property is only valid between onCreateView and
- // onDestroyView.
- private val binding get() = _binding!!
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- _binding = FragmentCityWeatherBinding.inflate(inflater, container, false)
- val root: View = binding.root
- Log.d("TESTI", "CityWeatherFragment START")
- Log.d("TESTI", args.lat.toString())
- Log.d("TESTI", args.lon.toString())
- // kutsutaan apufunktiota
- getWeatherData()
- return root
- }
- // apufunktio, johon voidaan eriyttää säädatan hakeminen ja käsittely
- fun getWeatherData() {
- // this is the url where we want to get our data from
- // OpenWeatherMap-osoite on tätä muotoa:
- // https://api.openweathermap.org/data/2.5/weather?lat=66.50247&lon=25.73009&units=metric&appid=OMAKEYTAHAN
- val JSON_URL = "THE URL OF THE DATA API"
- // Request a string response from the provided URL.
- val stringRequest: StringRequest = object : StringRequest(
- Request.Method.GET, JSON_URL,
- Response.Listener { response ->
- // print the response as a whole
- // we can use GSON to modify this response into something more usable
- Log.d("ADVTECH", response)
- },
- Response.ErrorListener {
- // typically this is a connection error
- Log.d("ADVTECH", it.toString())
- })
- {
- @Throws(AuthFailureError::class)
- override fun getHeaders(): Map<String, String> {
- // basic headers for the data
- val headers = HashMap<String, String>()
- headers["Accept"] = "application/json"
- headers["Content-Type"] = "application/json; charset=utf-8"
- return headers
- }
- }
- // Add the request to the RequestQueue. This has to be done in both getting and sending new data.
- // if using this in an activity, use "this" instead of "context"
- val requestQueue = Volley.newRequestQueue(context)
- requestQueue.add(stringRequest)
- }
- override fun onDestroyView() {
- super.onDestroyView()
- _binding = null
- }
- }
- // ajatuksena on rakentaa lennosta tarvittava JSON_URL, joka hakee tietyn kaupungin säätiedotus koordinaattien perusteella
- // esim.
- fun getWeatherData() {
- // haetaan local.properties -tiedostosta OpenWeatherMapin API key
- // huom: local.propertiesin muuttujat päivittyvät vasta kun projektia käytetään
- // emulaattorissa päällä!
- val API_KEY = BuildConfig.OPENWEATHER_API_KEY
- // OpenWeatherMap-osoite on tätä muotoa:
- // https://api.openweathermap.org/data/2.5/weather?lat=66.50247&lon=25.73009&units=metric&appid=OMAKEYTAHAN
- // eli rakennetaan Kotlinissa osoite lat/lon ja OPENWEATHER_API_KEY:n pohjalta:
- val JSON_URL = "https://api.openweathermap.org/data/2.5/weather?lat=${args.lat}&lon=${args.lon}&units=metric&appid=${API_KEY}"
- // Request a string response from the provided URL.
- val stringRequest: StringRequest = object : StringRequest(
- Request.Method.GET, JSON_URL,
- Response.Listener { response ->
- .... jne jne jne....
- // datan muuntaminen JSONista -> CityWeather-dataksi Kotliniin:
- val gson = GsonBuilder().setPrettyPrinting().create()
- // Request a string response from the provided URL.
- val stringRequest: StringRequest = object : StringRequest(
- Request.Method.GET, JSON_URL,
- Response.Listener { response ->
- // print the response as a whole
- // we can use GSON to modify this response into something more usable
- Log.d("TESTI", response)
- // datassa tulee vain yhden kaupungin JSON, muutetaan GSON:illa käyttökelpoiseen muotoon
- // tämä vaatii CityWeather-luokan, joka tehdään esimerkkidatan pohjalta
- // json2kt.com -palvelussa (ks. edellinen luento, loppuosa)
- var item : CityWeather = gson.fromJson(response, CityWeather::class.java)
- // haetaan testimielessä pari muuttujaa
- // huom main? tarkoittaa sitä, että jos main-olio
- // on arvoltaan null, koodi ei yritä väkisin ajaa
- // koodia läpi koska se tilttaisi
- // tämä liittyy ns. null-safety -ominaisuuteen ohjelmointikielessä
- val temperature = item.main?.temp
- val humidity = item.main?.humidity
- // nämä muuttujat voi halutessaan laittaa vaikka ulkoasuun:
- // esim. jos CityWeatherin xml-ulkoasussa on TextView, jonka id on textView_city_temperature
- // voitaisiin laittaa se näkyviin näin:
- // binding.textViewCityTemperature.text = "${temperature}C"
- // kokeillaan lokittaa tarkemmat tiedot
- Log.d("TESTI", "Lämpötila: ${temperature}C, kosteusprosentti: ${humidity}%")
- },
- Response.ErrorListener {
- // typically this is a connection error
- Log.d("TESTI", it.toString())
- })
- {
- ... jne jne ....
- // OSMDroid, eli OpenStreetMap Androidissa, module.gradle import:
- implementation 'org.osmdroid:osmdroid-android:6.1.16'
- // tämän ohjeen pohjalta toimitaan:
- https://github.com/osmdroid/osmdroid/wiki/How-to-use-the-osmdroid-library-(Kotlin)
- Päivitetään permissionit seuraavanlaiseksi:
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
- // Nykypäivänä permissionit pitää kysyä myös koodin kautta, pelkkä AndroidManifest ei riitä yksistään
- // helpoiten tämän voi tehdä Activityyn, esim. MainActivity:
- // apufunktio, tarkistetaan oikeudet
- fun hasPermissions(context: Context, vararg permissions: String): Boolean = permissions.all {
- ActivityCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
- }
- // ja tämä koodi onCreaten loppupuolelle:
- // lista permissioneista, joita ohjelma käyttää
- // TÄMÄN PITÄÄ TÄSMÄTÄ ANDROIDMANIFESTIN KANSSA
- val PERMISSION_ALL = 123
- val PERMISSIONS = arrayOf(
- android.Manifest.permission.INTERNET,
- android.Manifest.permission.ACCESS_FINE_LOCATION,
- android.Manifest.permission.ACCESS_COARSE_LOCATION,
- android.Manifest.permission.ACCESS_NETWORK_STATE
- )
- // tarkistetaan kaikki oikeudet kerralla
- if (!hasPermissions(this, *PERMISSIONS)) {
- ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL)
- }
- // ulkoasu OpenStreetMapFragmentille:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <org.osmdroid.views.MapView android:id="@+id/map"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" />
- </LinearLayout>
- // ohjeen mukaista pohjaa kun säädetään, saadaan seuraavanlainen pohja:
- class OpenStreetMapFragment : Fragment() {
- private var _binding: FragmentOpenStreetMapBinding? = null
- // This property is only valid between onCreateView and
- // onDestroyView.
- private val binding get() = _binding!!
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- _binding = FragmentOpenStreetMapBinding.inflate(inflater, container, false)
- val root: View = binding.root
- // muutetaan activity Context-tyyppiseksi lennosta, jotta se kelpaa uudelle PreferenceManagerille
- // tietotyypin muuntaminen luokasta toiseen on nimeltään typecasting
- // jotta deprecated saadaan koodista pois, muuta ylhäältä import tähän:
- // import androidx.preference.PreferenceManager
- // ja lisää build.gradleen: implementation 'androidx.preference:preference:1.2.0'
- getInstance().load(activity, PreferenceManager.getDefaultSharedPreferences(activity as Context))
- // asetetaan mapViewiin tietty ulkonäkö
- binding.map.setTileSource(TileSourceFactory.MAPNIK)
- // Zoomataan rovaniemelle
- val mapController = binding.map.controller
- mapController.setZoom(19.0)
- val startPoint = GeoPoint(66.50247438013193, 25.7300978471244);
- mapController.setCenter(startPoint);
- return root
- }
- override fun onDestroyView() {
- super.onDestroyView()
- _binding = null
- }
- }
- // marker-koodia testattavaksi:
- // kokeillaan lisätä Marker Rovaniemelle
- val firstMarker = Marker(binding.map)
- firstMarker.position = startPoint
- firstMarker.title = "Rovaniemi!"
- firstMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER)
- binding.map.overlays.add(firstMarker)
- binding.map.invalidate()
- // kun markkeria klikataan:
- firstMarker.setOnMarkerClickListener { marker, mapView ->
- // sijainti, esim: marker.position.latitude
- Log.d("TESTI", "Marker click!")
- return@setOnMarkerClickListener false
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement