Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Edistynyt mobiiliohjelmointi, 14.2.2023
- // OpenWeatherMapin API:
- // https://openweathermap.org/current
- // esim. Rantavitikan kampus, Lapin AMK:
- https://api.openweathermap.org/data/2.5/weather?lat=66.48130266083665&lon=25.723290728723306&appid=OMA_API_KEY_TÄHÄN
- // data on esim:
- {"coord":{"lon":25.7233,"lat":66.4813},"weather":[{"id":600,"main":"Snow","description":"light snow","icon":"13n"}],"base":"stations","main":{"temp":269.94,"feels_like":265.71,"temp_min":269.94,"temp_max":269.94,"pressure":1020,"humidity":86},"visibility":10000,"wind":{"speed":3.09,"deg":210},"snow":{"1h":0.12},"clouds":{"all":20},"dt":1676355896,"sys":{"type":1,"id":1354,"country":"FI","sunrise":1676356275,"sunset":1676385095},"timezone":7200,"id":638936,"name":"Rovaniemi","cod":200}
- // muutetaan yksiköt metriseen järjestelmään (oletuksena lämpötila on näemmä Kelvineitä)
- https://api.openweathermap.org/data/2.5/weather?lat=66.48130266083665&lon=25.723290728723306&appid=OMA_API_KEY_TÄHÄN&units=metric
- // nyt data on:
- {"coord":{"lon":25.7233,"lat":66.4813},"weather":[{"id":600,"main":"Snow","description":"light snow","icon":"13n"}],"base":"stations","main":{"temp":-3.21,"feels_like":-7.44,"temp_min":-3.21,"temp_max":-3.21,"pressure":1020,"humidity":86},"visibility":10000,"wind":{"speed":3.09,"deg":210},"snow":{"1h":0.1},"clouds":{"all":20},"dt":1676356259,"sys":{"type":1,"id":1354,"country":"FI","sunrise":1676356275,"sunset":1676385095},"timezone":7200,"id":638936,"name":"Rovaniemi","cod":200}
- Google Maps -> OpenStreetMap -ohjeet:
- 1. MapsFragment -> onMarkerClick:
- Tarvitsemme markerin koordinaatit seuraavia vaiheita varten (esim. p0.position.latitude jne.)
- 2. Luo uusi fragment navigation editorin avulla: CityWeatherFragment (ota käyttöön myös binding layer) ja tee action MapsFragmentista CityWeatherFragmentiin. CityWeatherFragmentille kaksi argumenttia: latitude ja longitude (molemmat Float).
- 3. Navigoi onMarkerClickistä CityWeatherFragmentiin käyttämällä navController -> navigate
- 4. CityWeatherFragment – ota vastaan argumentit, ja luo uusi JSON_URL -muuttuja.
- Tee ensin muuttuja API_KEY, johon tallennat oman OpenWeatherMapin API keyn. Jos tallensit API key:n local.properties-tiedostoon, voit hakea sen koodissa näin:
- val API_KEY : String = BuildConfig.OPENWEATHER_API_KEY
- HUOM! BuildConfig päivittyy vain silloin kun ohjelmaa ajetaan emulaattorissa (play-nappi), pelkkä rebuild ei riitä!
- val JSON_URL : String = https://api.openweathermap.org/data/2.5/weather?lat=${args.latitude}&long=${args.longitude}&units=metric&appid=${API_KEY}
- 5. Käytä Volleyta, ja lataa JSON_URLin avulla JSON-data
- 6. Luo säädatan pohjalta CityWeather-niminen luokka käyttämällä json2kt.com -palvelua, ja lataa se Android-projektiisi
- 7. Muunna JSON-data (response) GSONin avulla CityWeather-olioksi. Käytä oikeaa versiota GSON-koodista, eli tässä tapauksessa dataa tulee vain yksi objekti!
- 8. Tulosta CityWeather -olion avulla tämän hetkinen lämpötila
- LogCatiin ja esim. ulkoasussa olevaan TextViewiin
- ------------------------------------------------------
- Muista luoda tarvittavat data-luokat json2kt.com-palvelussa! Lopputuloksena tulee 8 luokkatiedostoa (kannattaa tehdä oma paketti projektiin, esim. datatypes -> cityweather, ettei projektin kansio ole sekaisin fragmentteja ja dataluokkia.)
- Jos Snow-luokkaan tulee virhe, ota muuttujan nimestä 1 pois (eli pelkkä h)
- Ohjaajan versio (täydennetään myöhemmin):
- MapsFragment.kt, onMarkerClick():
- // jos mitä tahansa markeria klikataan, ajetaan tämä funktio
- override fun onMarkerClick(p0: Marker): Boolean {
- Log.d("ADVTECH", "MARKKERI!")
- // lokitetaan/tulostetaan markeriin liitetyt koordinaatit sekä
- // tagi, jossa pitäisi olla kaupungin nimi
- Log.d("ADVTECH", p0.position.latitude.toString())
- Log.d("ADVTECH", p0.position.longitude.toString())
- Log.d("ADVTECH", p0.tag.toString())
- // navigoidaan CityWeatherFragmentiin, ja laitetaan koordinaatit parametreiksi
- val action = MapsFragmentDirections.actionMapsFragmentToCityWeatherFragment(p0.position.latitude.toFloat(), p0.position.longitude.toFloat())
- findNavController().navigate(action)
- // onMarkerClick vaatii lopussa että palautetaan boolean
- return false
- }
- CityWeatherFragment.kt:
- 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
- // print out the given parameter into logs
- getWeather()
- return root
- }
- fun getWeather() {
- // haetaan API-key local.properties-tiedostosta, muista käyttää projektia päällä play-napista että tiedosto päivittyy
- // voit myös asettaa API keyn suoraan muuttujaan tekstinä, mutta se ei ole optimaalinen ratkaisu
- val API_KEY : String = BuildConfig.OPENWEATHERMAP_API_KEY
- // rakennetaan URL rajapintaan muuttujien avulla
- val JSON_URL : String = "https://api.openweathermap.org/data/2.5/weather?lat=${args.latitude}&lon=${args.longitude}&appid=${API_KEY}&units=metric"
- 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("ADVTECH", response)
- // muunnetaan data CityWeather-olioksi
- var item : CityWeather = gson.fromJson(response, CityWeather::class.java)
- // haetaan pelkkä lämpötila
- Log.d("ADVTECH", item.main?.temp.toString() + " C")
- // jos halutaan näyttää esim. TextViewissä ja sen id on textView_temperature:
- // binding.textViewTemperature.text = item.main?.temp.toString() + " C"
- },
- 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)
- Log.d("ADVTECH", JSON_URL)
- }
- override fun onDestroyView() {
- super.onDestroyView()
- _binding = null
- }
- }
- EXTRA:
- Stylen asettaminen TextViewiin koodissa:
- textViewTitle.setTextAppearance(this, R.style.RedHUGEText);
- TextViewin värin muuttaminen koodissa:
- textView.setTextColor(Color.parseColor("#FF0000"))
- // Permissionit tulee aina kysyä myös koodissa, jotta käyttäjä voi antaa suostumuksensa
- // uusissa Androideissa tämä on vaadittua
- // AndroidManifest:
- <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" />
- Lisätään MainActivityyn funktio:
- fun hasPermissions(context: Context, vararg permissions: String): Boolean = permissions.all {
- ActivityCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
- }
- // lisätään MainActivityn onCreaten loppuun:
- // in Activity onCreate:
- val PERMISSION_ALL = 123
- // näiden permissioneiden pitää olla myös AndroidManifestissa
- val PERMISSIONS = arrayOf(
- Manifest.permission.INTERNET,
- Manifest.permission.ACCESS_FINE_LOCATION,
- Manifest.permission.ACCESS_COARSE_LOCATION,
- Manifest.permission.ACCESS_NETWORK_STATE
- )
- if (!hasPermissions(this, *PERMISSIONS)) {
- ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL)
- }
- // OpenStreetMap
- https://github.com/osmdroid/osmdroid/wiki/How-to-use-the-osmdroid-library-(Kotlin)
- // Uusi fragment, OpenStreetMapFragment.kt:
- import org.osmdroid.views.MapView
- import org.osmdroid.config.Configuration.*
- import org.osmdroid.tileprovider.tilesource.TileSourceFactory
- import org.osmdroid.util.GeoPoint
- import org.osmdroid.views.overlay.Marker
- /**
- * A simple [Fragment] subclass.
- * Use the [OpenStreetMapFragment.newInstance] factory method to
- * create an instance of this fragment.
- */
- class OpenStreetMapFragment : Fragment() {
- // change this to match your fragment name
- 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
- // tarvittavat gradle-importit:
- // implementation 'org.osmdroid:osmdroid-android:6.1.14'
- // implementation 'androidx.preference:preference:1.2.0'
- // käytetään tätä versiota PreferenceMananagerista ettei ole deprecated Android 10:stä eteenpäin
- // huom: import ylhäällä: import androidx.preference.PreferenceManager
- getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context as Context))
- // binding-layerin kautta mapViewiin pääsy, ks. osm-droidin ohje miten lisätään ulkoasu tälle fragmentille
- // https://github.com/osmdroid/osmdroid/wiki/How-to-use-the-osmdroid-library-(Kotlin)
- binding.map.setTileSource(TileSourceFactory.MAPNIK)
- // asetetaan alkupiste + zoomaus
- val mapController = binding.map.controller
- mapController.setZoom(18.0)
- val startPoint = GeoPoint(66.50352001528042, 25.727189822733095);
- mapController.setCenter(startPoint);
- // lisätään marker Rovaniemelle
- val marker = Marker(binding.map)
- marker.position = startPoint
- marker.title = "Rovaniemi marker!"
- marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER)
- binding.map.overlays.add(marker)
- binding.map.invalidate()
- // onClick onnistuu mm. näin
- marker.setOnMarkerClickListener { marker, mapView ->
- Log.d("ADVTECH", "MARKKKERIIIII!")
- return@setOnMarkerClickListener false
- }
- return root
- }
- override fun onDestroyView() {
- super.onDestroyView()
- _binding = null
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement