tuomasvaltanen

Untitled

Mar 3rd, 2023 (edited)
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.08 KB | None | 0 0
  1. // Edistynyt mobiiliohjelmointi, 3.3.2023
  2.  
  3. 1. Tehdään ensiksi mobile_navigationin avulla uusi fragment nimeltä FeedbackSendFragment
  4. (ei lisätä päävalikkoon)
  5.  
  6. 2. Lisää mobile_navigationissa action:
  7. FeedbackReadFragment -> FeedbackSendFragment
  8. (ei argumentteja)
  9.  
  10. 3. Lopuksi lisätään Button FeedbackReadFragmentiin (ListViewin päälle esim.), jota klikattaessa ohjelma siirtyy FeedbackSendFragmentiin
  11.  
  12. // napilla siirtyminen FeedbackReadFragmentista -> FeedbackSendFragmentiin
  13.  
  14. // ulkoasu-xml (FeedbackReadFragment)
  15.  
  16. <?xml version="1.0" encoding="utf-8"?>
  17. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  18. xmlns:tools="http://schemas.android.com/tools"
  19. android:layout_width="match_parent"
  20. android:layout_height="match_parent"
  21. android:orientation="vertical"
  22. tools:context=".FeedbackReadFragment">
  23.  
  24. <Button
  25. android:id="@+id/button_send_feedback_fragment"
  26. android:layout_width="match_parent"
  27. android:layout_height="wrap_content"
  28. android:text="Send feedback" />
  29.  
  30. <ListView
  31. android:id="@+id/listView_feedbacks"
  32. android:layout_width="match_parent"
  33. android:layout_height="match_parent" />
  34. </LinearLayout>
  35.  
  36.  
  37. // muutetaan FeedbackReadFragment.kt:ssa onCreateViewiä:
  38.  
  39. override fun onCreateView(
  40. inflater: LayoutInflater,
  41. container: ViewGroup?,
  42. savedInstanceState: Bundle?
  43. ): View? {
  44. _binding = FragmentFeedbackReadBinding.inflate(inflater, container, false)
  45. val root: View = binding.root
  46.  
  47. // navigoidaan napista FeedbackSendFragmentiin
  48. binding.buttonSendFeedbackFragment.setOnClickListener {
  49. val action = FeedbackReadFragmentDirections.actionFeedbackReadFragmentToFeedbackSendFragment()
  50. it.findNavController().navigate(action)
  51. }
  52.  
  53. getFeedbacks()
  54.  
  55. return root
  56. }
  57.  
  58. // FeedbackSendFragmentin xml-ulkoasu, esimerkkilomake uutta Feedbackia varten
  59.  
  60. <?xml version="1.0" encoding="utf-8"?>
  61. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  62. xmlns:tools="http://schemas.android.com/tools"
  63. android:layout_width="match_parent"
  64. android:layout_height="match_parent"
  65. android:orientation="vertical"
  66. android:layout_margin="10dp"
  67. tools:context=".FeedbackSendFragment">
  68.  
  69. <TextView
  70. android:layout_width="match_parent"
  71. android:layout_height="wrap_content"
  72. android:layout_marginBottom="10dp"
  73. android:text="Send us feedback!"
  74. android:textColor="#239A5D"
  75. android:textSize="24sp"
  76. android:textStyle="bold" />
  77.  
  78. <TextView
  79. android:layout_width="match_parent"
  80. android:layout_height="wrap_content"
  81. android:text="Your name"
  82. android:textStyle="bold" />
  83.  
  84. <EditText
  85. android:id="@+id/editText_feedback_name"
  86. android:layout_width="match_parent"
  87. android:layout_height="48dp"
  88. android:ems="10"
  89. android:hint="Write your name here"
  90. android:inputType="textPersonName" />
  91.  
  92. <TextView
  93. android:layout_width="match_parent"
  94. android:layout_height="wrap_content"
  95. android:text="Your location"
  96. android:textStyle="bold" />
  97.  
  98. <EditText
  99. android:id="@+id/editText_feedback_location"
  100. android:layout_width="match_parent"
  101. android:layout_height="48dp"
  102. android:ems="10"
  103. android:hint="Where are you?"
  104. android:inputType="textPersonName" />
  105.  
  106. <TextView
  107. android:layout_width="match_parent"
  108. android:layout_height="wrap_content"
  109. android:text="Your feedback"
  110. android:textStyle="bold" />
  111.  
  112. <EditText
  113. android:id="@+id/editText_feedback_value"
  114. android:layout_width="match_parent"
  115. android:layout_height="48dp"
  116. android:ems="10"
  117. android:hint="How did we do today?"
  118. android:inputType="textPersonName" />
  119.  
  120. <Button
  121. android:id="@+id/button_send_feedback"
  122. android:layout_width="match_parent"
  123. android:layout_height="wrap_content"
  124. android:layout_marginTop="20dp"
  125. android:text="SEND FEEDBACK" />
  126. </LinearLayout>
  127.  
  128. // FeedbackSendFragment.kt , otetaan binding layer käyttöön:
  129.  
  130. class FeedbackSendFragment : Fragment() {
  131. // change this to match your fragment name
  132. private var _binding: FragmentFeedbackSendBinding? = null
  133.  
  134. // This property is only valid between onCreateView and
  135. // onDestroyView.
  136. private val binding get() = _binding!!
  137.  
  138. override fun onCreateView(
  139. inflater: LayoutInflater,
  140. container: ViewGroup?,
  141. savedInstanceState: Bundle?
  142. ): View? {
  143. _binding = FragmentFeedbackSendBinding.inflate(inflater, container, false)
  144. val root: View = binding.root
  145.  
  146.  
  147.  
  148. return root
  149. }
  150.  
  151. override fun onDestroyView() {
  152. super.onDestroyView()
  153. _binding = null
  154. }
  155. }
  156.  
  157. // FeedbackSendFragment, kokeillaan hakea napilla arvot edittexteistä
  158.  
  159. class FeedbackSendFragment : Fragment() {
  160. // change this to match your fragment name
  161. private var _binding: FragmentFeedbackSendBinding? = null
  162.  
  163. // This property is only valid between onCreateView and
  164. // onDestroyView.
  165. private val binding get() = _binding!!
  166.  
  167. override fun onCreateView(
  168. inflater: LayoutInflater,
  169. container: ViewGroup?,
  170. savedInstanceState: Bundle?
  171. ): View? {
  172. _binding = FragmentFeedbackSendBinding.inflate(inflater, container, false)
  173. val root: View = binding.root
  174.  
  175. // kun nappia painetaan, haetaan edittexteistä arvot, ja kutsutaan apufunktiota
  176. binding.buttonSendFeedback.setOnClickListener{
  177. var name = binding.editTextFeedbackName.text.toString()
  178. var location = binding.editTextFeedbackLocation.text.toString()
  179. var value = binding.editTextFeedbackValue.text.toString()
  180.  
  181. Log.d("TESTI", "${name} - ${location} - ${value}")
  182. }
  183.  
  184. return root
  185. }
  186.  
  187.  
  188.  
  189. override fun onDestroyView() {
  190. super.onDestroyView()
  191. _binding = null
  192. }
  193. }
  194.  
  195. // FeedbackSendFragment, Volley-koodin kanssa
  196.  
  197. class FeedbackSendFragment : Fragment() {
  198. // change this to match your fragment name
  199. private var _binding: FragmentFeedbackSendBinding? = null
  200.  
  201. // This property is only valid between onCreateView and
  202. // onDestroyView.
  203. private val binding get() = _binding!!
  204.  
  205. override fun onCreateView(
  206. inflater: LayoutInflater,
  207. container: ViewGroup?,
  208. savedInstanceState: Bundle?
  209. ): View? {
  210. _binding = FragmentFeedbackSendBinding.inflate(inflater, container, false)
  211. val root: View = binding.root
  212.  
  213. // kun nappia painetaan, haetaan edittexteistä arvot, ja kutsutaan apufunktiota
  214. binding.buttonSendFeedback.setOnClickListener{
  215. var name = binding.editTextFeedbackName.text.toString()
  216. var location = binding.editTextFeedbackLocation.text.toString()
  217. var value = binding.editTextFeedbackValue.text.toString()
  218.  
  219. Log.d("TESTI", "${name} - ${location} - ${value}")
  220.  
  221. sendFeedback(name, location, value)
  222. }
  223.  
  224. return root
  225. }
  226.  
  227. // apufunktio, jonka kautta uusi feedback lähetetään Volleyllä
  228. fun sendFeedback(name : String, location : String, value : String) {
  229. val JSON_URL = "https://xxxxxxxx.directus.app/items/feedback/?access_token=${BuildConfig.DIRECTUS_ACCESS_TOKEN}"
  230.  
  231. // luodaan GSON-objekti
  232. var gson = GsonBuilder().create()
  233.  
  234. // Request a string response from the provided URL.
  235. val stringRequest: StringRequest = object : StringRequest(
  236. Request.Method.POST, JSON_URL,
  237. Response.Listener { response ->
  238. Log.d("TESTI", "Directusiin lähetys ok!")
  239.  
  240. // asetetaan kaikki edittextit tyhjiksi, jotta käyttäjä huomaa että jotain tapahtui
  241. binding.editTextFeedbackName.setText("")
  242. binding.editTextFeedbackLocation.setText("")
  243. binding.editTextFeedbackValue.setText("")
  244.  
  245. // ilmoitetaan käyttäjälle myös Toast-viestillä että operaatio oli ok!
  246. Toast.makeText(context, "Thank you for your feedback!", Toast.LENGTH_SHORT).show()
  247.  
  248. // koska activity.onBackPressed on deprecated, voidaan tehdä näin
  249. // eli palataan aiempaan fragmentiin.
  250. // tosin, näyttäisi siltä että tämä on hieman buginen, koska äppi
  251. // kaatuu mikäli yritetään heti perää siirtyä takaisin tähän frgamentiin lähettämään uutta feedbackia
  252. // activity?.getSupportFragmentManager()?.popBackStack()
  253.  
  254. // parempi tapa -> tehdään action myös FeedbackSendFragmentista FeedbackReadFragmentiin
  255. // ja navigoidaan normaalisti takaisin aiempaan fragmentiin
  256. val action = FeedbackSendFragmentDirections.actionFeedbackSendFragmentToFeedbackReadFragment()
  257. findNavController().navigate(action)
  258. },
  259. Response.ErrorListener {
  260. // typically this is a connection error
  261. Log.d("ADVTECH", it.toString())
  262. })
  263. {
  264. @Throws(AuthFailureError::class)
  265. override fun getHeaders(): Map<String, String> {
  266. // we have to specify a proper header, otherwise Apigility will block our queries!
  267. // define we are after JSON data!
  268. val headers = HashMap<String, String>()
  269. headers["Accept"] = "application/json"
  270. headers["Content-Type"] = "application/json; charset=utf-8"
  271. return headers
  272. }
  273.  
  274. // let's build the new data here
  275. @Throws(AuthFailureError::class)
  276. override fun getBody(): ByteArray {
  277. // this function is only needed when sending data
  278. var body = ByteArray(0)
  279. try { // check the example "Converting a Kotlin object to JSON"
  280. // on how to create this newData -variable
  281. var newData = ""
  282.  
  283. // luodaan lennosta uusi Feedback-olio edittextien arvojen pohjalta
  284. var f : Feedback = Feedback()
  285. f.name = name
  286. f.location = location
  287. f.value = value
  288.  
  289. // muutetaan Fedeback-olio -> JSON-muotoon GSONin avulla
  290. newData = gson.toJson(f);
  291.  
  292. // JSON to bytes
  293. body = newData.toByteArray(Charsets.UTF_8)
  294. } catch (e: UnsupportedEncodingException) {
  295. // problems with converting our data into UTF-8 bytes
  296. }
  297. return body
  298. }
  299. }
  300.  
  301. // Add the request to the RequestQueue. This has to be done in both getting and sending new data.
  302. val requestQueue = Volley.newRequestQueue(context)
  303. requestQueue.add(stringRequest)
  304. }
  305.  
  306. override fun onDestroyView() {
  307. super.onDestroyView()
  308. _binding = null
  309. }
  310. }
  311.  
  312. ##############################################################################################
  313. #### Harjoitukset 3 - Lisätehtävistä (Basic Auth ja temporary access tokenin käyttäminen) ####
  314. ##############################################################################################
  315.  
  316. Basic Authin käyttäminen.
  317.  
  318. Basic Auth ei itsessään ole kovin turvallinen, koska käyttäjänimi ja salasana "kryptataan" ainoastaan Base64-algoritmillä. Käytännössä Base64-algoritmin voi kääntää molempiin suuntiin, joten se ei ole varsinaisesti suojausalgoritmi. Toisin sanoen, jos joku saa kaapattua viestin, jossa Basic Auth tiedot ovat, se on helppo kääntää takaisin toisinpäin.
  319.  
  320. Basic Auth vaatii seuraavanlaisen headerin, jotta se toimii:
  321. Authorization ---> Basic BASE64_MUODOSSA-OLEVA-USERNAME+SALASANA
  322.  
  323. Ennen kuin käyttäjänimi ja salasana muutetaan Base64-muotoon, pitää ne asettaa samaan Stringiin, tällä tavalla (huomaa kaksoispiste välissä, erittäin tärkeä):
  324. username:password
  325.  
  326. Eli jos username on admin ja salasana on 12345, silloin String olisi:
  327. admin:12345
  328.  
  329. Muilta osin Volley-kutsu on täysin sama kuin aiemmin.
  330.  
  331. Esim:
  332.  
  333. class BasicAuthFragment : Fragment() {
  334. // change this to match your fragment name
  335. private var _binding: FragmentBasicAuthBinding? = null
  336.  
  337. // This property is only valid between onCreateView and
  338. // onDestroyView.
  339. private val binding get() = _binding!!
  340.  
  341. override fun onCreateView(
  342. inflater: LayoutInflater,
  343. container: ViewGroup?,
  344. savedInstanceState: Bundle?
  345. ): View? {
  346. _binding = FragmentBasicAuthBinding.inflate(inflater, container, false)
  347. val root: View = binding.root
  348.  
  349. // the binding -object allows you to access views in the layout, textviews etc.
  350.  
  351. getUsers()
  352.  
  353. return root
  354. }
  355.  
  356. fun getUsers() {
  357. // this is the url where we want to get our data
  358. // Note: if using a local server, use http://10.0.2.2 for localhost. this is a virtual address for Android emulators, since
  359. // localhost refers to the Android device instead of your computer
  360. val JSON_URL = "https://apingweb.com/api/auth/users"
  361.  
  362. // Request a string response from the provided URL.
  363. val stringRequest: StringRequest = object : StringRequest(
  364. Request.Method.GET, JSON_URL,
  365. Response.Listener { response ->
  366. Log.d("TESTI", response)
  367. },
  368. Response.ErrorListener {
  369. // typically this is a connection error
  370. Log.d("ADVTECH", it.toString())
  371. })
  372. {
  373. @Throws(AuthFailureError::class)
  374. override fun getHeaders(): Map<String, String> {
  375. // we have to specify a proper header, otherwise Apigility will block our queries!
  376. // define we are after JSON data!
  377. val headers = HashMap<String, String>()
  378. headers["Accept"] = "application/json"
  379. headers["Content-Type"] = "application/json; charset=utf-8"
  380.  
  381.  
  382. // tämä on ainoa muutos mikä pitää koodiin tehdä, jos rajapinta käyttää Basic Authia
  383. // --> Luodaan Authorization header, joka sisältää kirjautumistiedot Base64-formaatissa
  384. // replace with your own API's login info
  385. val authorizationString = "Basic " + Base64.encodeToString(
  386. ("admin" + ":" + "12345").toByteArray(), Base64.DEFAULT
  387. )
  388.  
  389. Log.d("TESTI", authorizationString)
  390.  
  391. headers.put("Authorization", authorizationString)
  392.  
  393. return headers
  394. }
  395. }
  396.  
  397. // Add the request to the RequestQueue. This has to be done in both getting and sending new data.
  398. val requestQueue = Volley.newRequestQueue(context)
  399. requestQueue.add(stringRequest)
  400. }
  401.  
  402. override fun onDestroyView() {
  403. super.onDestroyView()
  404. _binding = null
  405. }
  406. }
  407.  
  408. // Temporary access tokenin käyttäminen Androidissa, tätä varten tehty erillinen fragment päävalikkoon
  409. // nimeltä TempAccessFragment, ulkoasussa on textview ja button
  410.  
  411. class TempAccessFragment : Fragment() {
  412.  
  413. // HUOM! Tämä esimerkki on tehty hyvin pitkälle tyyliin "siitä mistä aita on matalin".
  414. // Jos haluat optimoida tätä rakennetta, ks. alla olevat kommentit
  415.  
  416. // tällä hetkellä koodin logiikka on tämä:
  417.  
  418. // jos datan hakemisessa tulee Auth-error -> kirjaudutaan kokonaan uudestaan rajapintaan.
  419. // tämäkin ratkaisu toimii (varsinkin pienillä käyttäjämäärillä), mutta tämän johdosta
  420. // Android-sovellus tekee paljon turhia kyselyjä Directusiin, koska kirjautuminen tehdään
  421. // aina virheen sattuessa tai fragmentin latautuessa uudelleen
  422.  
  423. // tämä voi muodostua ongelmaksi, mikäli sovelluksella on tuhansia aktiivisia käyttäjiä.
  424. // tällaisessa tilanteessa jokainen säästetty ja optimoitu kysely Directusin rajapintaan
  425. // säästää Androidin käyttämää suoritusaikaa, akkua sekä myös Directusista tulevaa käyttölaskua.
  426. // Mitä vähemmän Android-sovellus "rassaa" Directusin rajapintaa, sen halvempi ja energiatehokkaampi
  427. // oma Android-sovellus on.
  428.  
  429. // Parannusehdotus 1:
  430.  
  431. // hyödynnetään refresh tokenia access tokenin uusimisessa (kevyempi operaatio kuin uudestaan kirjautuminen)
  432. // refresh token tulee samassa datassa kuin access token myös. Access token on 15min voimassa, ja refresh
  433. // token on 7 päivää voimassa. Refresh tokenin avulla voi pyytää uuden access tokenin, mikäli refresh token
  434. // on vielä voimassa. Jos myös refresh token vanhenee -> kirjaudutaan uudestaan. (tämä logiikka pitää koodata itse)
  435.  
  436. // Parannusehdotus 2:
  437.  
  438. // Directusin kirjautumisdatassa tulee mukana myös tieto siitä, kuinka kauan access token on voimassa kirjautumishetkestä
  439. // alkaen, oletuksena 900000 millisekuntia -> 900 sekuntia -> 15min
  440. // Voidaan koodata Android-sovellus siten, että niin kauan kuin aikaa on jäljellä, Directusiin ei lähetetä
  441. // yhtään kirjautumispyyntöä. Tällä tavalla Android-sovellus ei turhaan ole yhteydessä Directusiin,
  442. // koska äppi pitää itse kirjaa siitä milloin pitää kirjautua uusiksi.
  443.  
  444. // Parannusehdotus 3:
  445.  
  446. // kaikki kirjautumiseen liittyvä Volley-logiikka on hyvä keskittää yhteen paikkaan, joko kustomoituun
  447. // Application -luokkaan, tai tehdä (suositellumpi tapa) Volley-kutsuille om a Singleton-luokka.
  448. // ks. Google ja Volleyn dokumentaatio esimerkistä miten tämä tehdään.
  449.  
  450. // change this to match your fragment name
  451. private var _binding: FragmentTempAccessBinding? = null
  452.  
  453. // This property is only valid between onCreateView and
  454. // onDestroyView.
  455. private val binding get() = _binding!!
  456.  
  457. // VARIABLES USED BY THE SESSION MANAGEMENT
  458. val LOGIN_URL = "https://xxxxx.directus.app/auth/login"
  459.  
  460. // these should be placed in the local properties file and used by BuildConfig
  461. // JSON_URL should be WITHOUT a trailing slash (/)!
  462. val JSON_URL = "https://xxxxx.directus.app/items/feedback"
  463.  
  464.  
  465. // if using username + password in the service (e.g. Directus), use these
  466. val username = BuildConfig.DIRECTUS_USERNAME
  467. val password = BuildConfig.DIRECTUS_PASSWORD
  468.  
  469. // request queues for requests
  470. var requestQueue: RequestQueue? = null
  471. var refreshRequestQueue: RequestQueue? = null
  472.  
  473. // state booleans to determine our session state
  474. var loggedIn: Boolean = false
  475. var needsRefresh: Boolean = false
  476.  
  477. // stored tokens. refresh is used when our session token has expired
  478. // access token in this case is the same as session token
  479. var refreshToken = ""
  480. var accessToken = ""
  481.  
  482. override fun onCreateView(
  483. inflater: LayoutInflater,
  484. container: ViewGroup?,
  485. savedInstanceState: Bundle?
  486. ): View? {
  487. _binding = FragmentTempAccessBinding.inflate(inflater, container, false)
  488. val root: View = binding.root
  489.  
  490. // napin kautta haetaan data uusiksi, jotta voidaan testata että vieläkö access token toimii
  491. binding.buttonDataAction.setOnClickListener {
  492. dataAction()
  493. }
  494.  
  495.  
  496. return root
  497. }
  498.  
  499. // fragment entry point
  500. override fun onViewCreated(view: View, savedInstanceState: Bundle?)
  501. {
  502. super.onViewCreated(view, savedInstanceState);
  503.  
  504. requestQueue = Volley.newRequestQueue(context)
  505. refreshRequestQueue = Volley.newRequestQueue(context)
  506.  
  507. // start with login
  508. loginAction()
  509. }
  510.  
  511. // kirjaudutaan Directusiin
  512. fun loginAction()
  513. {
  514. Log.d("ADVTECH", "login")
  515. Log.d("ADVTECH", JSON_URL + " login")
  516. requestQueue?.add(loginRequest)
  517. }
  518.  
  519. // kirjaudutaan uusiksi jos refresh-muuttuja on tilassa True
  520. fun refreshLogin() {
  521. if (needsRefresh) {
  522. loggedIn = false
  523. // use this if using refresh logic
  524. // refreshRequestQueue?.add(loginRefreshRequest)
  525.  
  526. // if using refresh logic, comment this line out
  527. loginAction()
  528. }
  529. }
  530.  
  531. fun dataAction() {
  532. // haetaan dataa vain jos olemme vielä kirjautuneina sisään
  533. if (loggedIn) {
  534. requestQueue?.add(dataRequest)
  535. }
  536. }
  537.  
  538. override fun onDestroyView() {
  539. super.onDestroyView()
  540. _binding = null
  541. }
  542.  
  543. // REQUEST OBJECT 1: LOGIN
  544. var loginRequest: StringRequest = object : StringRequest(
  545. Request.Method.POST, LOGIN_URL,
  546. Response.Listener { response ->
  547.  
  548. var responseJSON: JSONObject = JSONObject(response)
  549.  
  550. // otetaan access token talteen (tässäkin voisi käyttää json2kt.com + GSON)
  551. // tämä esimerkki käyttää sisäänrakennettuja JSON-työkaluja
  552. accessToken = responseJSON.getJSONObject("data").get("access_token").toString()
  553.  
  554. loggedIn = true
  555.  
  556. // after login's done, get data from API
  557. dataAction()
  558.  
  559. Log.d("ADVTECH", response)
  560. },
  561. Response.ErrorListener {
  562. // typically this is a connection error
  563. Log.d("ADVTECH", it.toString())
  564. }) {
  565. @Throws(AuthFailureError::class)
  566. override fun getHeaders(): Map<String, String> {
  567. // we have to provide the basic header info
  568. // + Bearer info => accessToken
  569. val headers = HashMap<String, String>()
  570. headers["Accept"] = "application/json"
  571.  
  572. // for Directus, the typical approach works:
  573. headers["Content-Type"] = "application/json; charset=utf-8"
  574.  
  575. return headers
  576. }
  577.  
  578.  
  579. // use this to build the needed JSON-object
  580. // this approach is used by Directus, IBM Cloud uses the commented version instead
  581. @Throws(AuthFailureError::class)
  582. override fun getBody(): ByteArray {
  583. // this function is only needed when sending data
  584. var body = ByteArray(0)
  585. try {
  586. // on how to create this newData -variable
  587. var newData = ""
  588.  
  589. // a very quick 'n dirty approach to creating the needed JSON body for login
  590. newData = "{\"email\":\"${username}\", \"password\": \"${password}\"}"
  591.  
  592. // JSON to bytes
  593. body = newData.toByteArray(Charsets.UTF_8)
  594. } catch (e: UnsupportedEncodingException) {
  595. // problems with converting our data into UTF-8 bytes
  596. }
  597. return body
  598. }
  599.  
  600. }
  601.  
  602. // REQUEST OBJECT 3 : ACTUAL DATA -> FEEDBACK
  603. var dataRequest: StringRequest = object : StringRequest(
  604. Request.Method.GET, JSON_URL,
  605. Response.Listener { response ->
  606. Log.d("ADVTECH", response)
  607. binding.textViewRawData.text = response
  608. },
  609. Response.ErrorListener {
  610. // typically this is a connection error
  611. Log.d("ADVTECH", it.toString())
  612.  
  613. // jos tulee Auth-error -> kirjaudutaan uusiksi
  614. if (it is AuthFailureError) {
  615. Log.d("ADVTECH", "EXPIRED start")
  616.  
  617. needsRefresh = true
  618. loggedIn = false
  619. refreshLogin()
  620.  
  621. Log.d("ADVTECH", "EXPIRED end")
  622. }
  623. }) {
  624. @Throws(AuthFailureError::class)
  625. override fun getHeaders(): Map<String, String> {
  626. // we have to provide the basic header info
  627. // + Bearer info => accessToken
  628. val headers = HashMap<String, String>()
  629.  
  630. // access tokenin täytyy kulkea headerseissa mukana
  631. // muutoin tulee virhe Directusin rajapinnasta (koska emme käytä enää
  632. // staattista tokenia)
  633. headers["Authorization"] = "Bearer " + accessToken
  634.  
  635. return headers
  636. }
  637.  
  638. }
  639. }
Add Comment
Please, Sign In to add comment