Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Edistynyt mobiiliohjelmointi, 16.2.2023
- // current weather API OpenWeatherMap
- https://openweathermap.org/current
- // rajapinnasta dataa esim näin:
- https://api.openweathermap.org/data/2.5/weather?lat=66.50336579596632&lon=25.727513206740678&appid=OMA_API_KEY_TÄHÄN&units=metric
- // esimerkki-dataa:
- {"coord":{"lon":25.7275,"lat":66.5034},"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}],"base":"stations","main":{"temp":-1.29,"feels_like":-7.89,"temp_min":-1.29,"temp_max":-1.29,"pressure":1005,"humidity":100},"visibility":10000,"wind":{"speed":7.72,"deg":180},"clouds":{"all":75},"dt":1676543953,"sys":{"type":1,"id":1354,"country":"FI","sunrise":1676528625,"sunset":1676558334},"timezone":7200,"id":638936,"name":"Rovaniemi","cod":200}
- // Tehdään seuraava osio, eli haetaan säätiedot kaupungin koordinaattien perusteella:
- 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. CityWeatherFragmentissa – ota vastaan argumentit, ja luo uusi JSON_URL -muuttuja (ks. esimerkki alta).
- 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 (response)
- 6. Luo säädatan pohjalta CityWeather-niminen luokka käyttämällä json2kt.com -palvelua, ja lataa se Android-projektiisi. aseta OpenWeatherMapista tuleva JSON esim. Rovaniemen säätilanteesta esimerkkidataksi
- 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
- -----------------------------
- Tehdään ensin uusi fragment -> CityWeatherFragment, ja sille kaksi parametria, latitude ja longitude (float)
- Lisäksi action MapsFragmentista -> CityWeatherFragment
- MapsFragment.kt, onMarkerClick():
- // OnMarkerClickiä kutsutaan jos mitä tahansa markeria kartalla klikataan
- override fun onMarkerClick(p0: Marker): Boolean {
- Log.d("TESTI", "MARKKERI CLICK! JES!")
- // kaivetaan marker-oliosta klikatun markkerin nimi ja koordinaatit
- Log.d("TESTI", p0.tag.toString())
- Log.d("TESTI", p0.position.latitude.toString())
- Log.d("TESTI", p0.position.longitude.toString())
- val latitude : Float = p0.position.latitude.toFloat()
- val longitude : Float = p0.position.longitude.toFloat()
- // tähän action ja navigate, parametreiksi ylläolevat latitude ja longitude -muuttujat
- val action = MapsFragmentDirections.actionMapsFragmentToCityWeatherFragment(latitude, longitude)
- findNavController().navigate(action)
- // OnMarkerClick vaatii että lopuksi palautetaan Boolean
- return false
- }
- // CItyWeatherFragment:
- class CityWeatherFragment : Fragment() {
- // change this to match your fragment name
- private var _binding: FragmentCityWeatherBinding? = null
- 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", args.latitude.toString())
- Log.d("TESTI", args.longitude.toString())
- getWeather()
- // the binding -object allows you to access views in the layout, textviews etc.
- return root
- }
- fun getWeather() {
- val API_KEY = BuildConfig.OPENWEATHER_API_KEY
- val JSON_URL : String = "https://api.openweathermap.org/data/2.5/weather?lat=${args.latitude}&lon=${args.longitude}&units=metric&appid=${API_KEY}"
- 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)
- var item : CityWeather = gson.fromJson(response, CityWeather::class.java)
- Log.d("TESTI", "Lämpötila: ${item.main?.temp} C")
- // asetetaan lämpötila esim. TextViewiin, tässä tapauksessa TextViewin
- // id = textView_city_temperature
- // binding.textViewCityTemperature.text = item.main?.temp.toString() + " C"
- },
- Response.ErrorListener {
- // typically this is a connection error
- Log.d("TESTI", 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
- }
- }
- #######################################
- Muutetaan permissionit Manifestiin OpenStreetMapia varten, eli:
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- huom, jos pyydät permissioneita koodila, samat permissionit pitää löytyä myös manifestissa.
- MainActivity.kt:
- import alkuun ylös:
- import android.Manifest
- onCreaten loppuun:
- // in Activity onCreate:
- val PERMISSION_ALL = 123
- val PERMISSIONS = arrayOf(
- Manifest.permission.ACCESS_FINE_LOCATION,
- Manifest.permission.ACCESS_COARSE_LOCATION,
- Manifest.permission.ACCESS_NETWORK_STATE,
- Manifest.permission.INTERNET
- )
- if (!hasPermissions(this, *PERMISSIONS)) {
- ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL)
- }
- omaksi funktioksi MainActivityyn:
- fun hasPermissions(context: Context, vararg permissions: String): Boolean = permissions.all {
- ActivityCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
- }
- eli kokonaisuus, esim:
- class MainActivity : AppCompatActivity() {
- private lateinit var appBarConfiguration: AppBarConfiguration
- private lateinit var binding: ActivityMainBinding
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- binding = ActivityMainBinding.inflate(layoutInflater)
- setContentView(binding.root)
- setSupportActionBar(binding.appBarMain.toolbar)
- binding.appBarMain.fab.setOnClickListener { view ->
- Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
- .setAction("Action", null).show()
- }
- val drawerLayout: DrawerLayout = binding.drawerLayout
- val navView: NavigationView = binding.navView
- val navController = findNavController(R.id.nav_host_fragment_content_main)
- // Passing each menu ID as a set of Idds because each
- // menu should be considered as top level destinations.
- appBarConfiguration = AppBarConfiguration(setOf(
- R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow, R.id.dataReadFragment,
- R.id.commentApiFragment, R.id.mapsFragment), drawerLayout)
- setupActionBarWithNavController(navController, appBarConfiguration)
- navView.setupWithNavController(navController)
- // in Activity onCreate:
- val PERMISSION_ALL = 123
- val PERMISSIONS = arrayOf(
- Manifest.permission.ACCESS_FINE_LOCATION,
- Manifest.permission.ACCESS_COARSE_LOCATION,
- Manifest.permission.ACCESS_NETWORK_STATE,
- Manifest.permission.INTERNET
- )
- if (!hasPermissions(this, *PERMISSIONS)) {
- ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL)
- }
- }
- // add a new function to ACTIVITY
- fun hasPermissions(context: Context, vararg permissions: String): Boolean = permissions.all {
- ActivityCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
- }
- override fun onCreateOptionsMenu(menu: Menu): Boolean {
- // Inflate the menu; this adds items to the action bar if it is present.
- menuInflater.inflate(R.menu.main, menu)
- return true
- }
- override fun onSupportNavigateUp(): Boolean {
- val navController = findNavController(R.id.nav_host_fragment_content_main)
- return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
- }
- }
- ####################################
- OpenStreetMap Androidille:
- https://github.com/osmdroid/osmdroid
- Käyttöohje:
- https://github.com/osmdroid/osmdroid/wiki
- Tarvittavat gradle-dependencyt:
- implementation 'org.osmdroid:osmdroid-android:6.1.14'
- implementation 'androidx.preference:preference:1.2.0'
- Tehdään oma fragment OpenStreetMapFragment, ja lisätään päävalikkoon.
- OpenStreetMapFragmentin ulkoasuksi:
- <?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>
- OpenStreetFragment.kt:
- import androidx.preference.PreferenceManager
- import org.osmdroid.config.Configuration.*
- import org.osmdroid.tileprovider.tilesource.TileSourceFactory
- import org.osmdroid.util.GeoPoint
- import org.osmdroid.views.overlay.Marker
- 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
- // haetaan viittaus Androidin sisäiseen SharedPreferences-ominaisuuteen
- // jonne OpenStreetMap voi tallentaa tarvittaessa dataa (esim. kartta-tile-kuvat)
- getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context as Context))
- // the binding -object allows you to access views in the layout, textviews etc.
- // asetetaan TileSource, oletus MAPNIK
- binding.map.setTileSource(TileSourceFactory.MAPNIK)
- // asetetaan zoom-taso ja koordinatit Rovaniemelle
- // huom, setZoom olettaa floatin!
- val mapController = binding.map.controller
- mapController.setZoom(16.0)
- val startPoint = GeoPoint(66.50336579596632, 25.727513206740678);
- mapController.setCenter(startPoint);
- // lisätään marker Rovaniemielle
- 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()
- // markeria jos klikataan, ajetaan tämä
- marker.setOnMarkerClickListener { marker, mapView ->
- Log.d("TESTI", "Markeria klikattu!")
- return@setOnMarkerClickListener false
- }
- return root
- }
- override fun onDestroyView() {
- super.onDestroyView()
- _binding = null
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement