tuomasvaltanen

Untitled

Apr 17th, 2023 (edited)
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.67 KB | None | 0 0
  1. // Edistynyt mobiiliohjelmointi 17.4.2023
  2.  
  3. // edellisellä luennolla tehtiin valmiiksi kaksi fragmentia:
  4.  
  5. - FeedbackReadFragment
  6. - FeedbackSendFragment
  7.  
  8. Pohjat näille löytyvät edellisen luennon muistiinpanoista.
  9.  
  10. // koska Directus on omalla koneella, muutetaan AndroidManifestia niin että suojaamaton yhteys on sallittu:
  11. // eli lisätään android:usesCleartextTraffic="true" application-tägin sisälle
  12.  
  13. <application
  14. android:usesCleartextTraffic="true"
  15. android:allowBackup="true"
  16. android:dataExtractionRules="@xml/data_extraction_rules"
  17.  
  18. jne
  19.  
  20. // pelkkä datan hakeminen on hyvin samanlaista kuin harjoituksessa 1 (Commment-data)
  21.  
  22. class FeedbackReadFragment : Fragment() {
  23. private var _binding: FragmentFeedbackReadBinding? = null
  24. // This property is only valid between onCreateView and
  25. // onDestroyView.
  26. private val binding get() = _binding!!
  27. override fun onCreateView(
  28. inflater: LayoutInflater,
  29. container: ViewGroup?,
  30. savedInstanceState: Bundle?
  31. ): View? {
  32. _binding = FragmentFeedbackReadBinding.inflate(inflater, container, false)
  33. val root: View = binding.root
  34.  
  35. // haetaan feedback-data Directusista heti kun ladataan fragment
  36. getFeedbacks()
  37.  
  38. return root
  39. }
  40.  
  41. fun getFeedbacks() {
  42. // this is the url where we want to get our data
  43. // Note: if using a local server, use http://10.0.2.2 for localhost. this is a virtual address for Android emulators, since
  44. // localhost refers to the Android device instead of your computer
  45.  
  46. // tämä olisi hyvä olla myös local.propertiesissa
  47. // esim. DIRECTUS_ADDRESS
  48. // koodissa haetaan BuildConfig.DIRECTUS_ADDRESS
  49. // muista tällöin käynnistää sovellus kerran että BuildConfig päivittyy
  50.  
  51. // huomaa että access token on jokaisella omansa
  52. // myös portin pitää olla oikea, tässä tapauksessa 8055
  53. // ip osoite kuten 10.0.2.2 viittaa tietokoneeseen
  54. // ja portti 8055 viittaa tiettyyn sovellukseen tietokoneessa, eli Directusiin
  55. // 10.0.2.2 on virtuaaliosoite, joka osoittaa tietokoneen localhostiin
  56. // pelkkä localhost viittaisi tässä nyt Android-emulaattoriin
  57. val JSON_URL = "http://10.0.2.2:8055/items/feedback?access_token=OMA_ACCESS_TOKEN_TÄHÄN"
  58.  
  59. // Request a string response from the provided URL.
  60. val stringRequest: StringRequest = object : StringRequest(
  61. Request.Method.GET, JSON_URL,
  62. Response.Listener { response ->
  63.  
  64. // näytetään raakadata LogCatissa
  65. Log.d("TESTI", response)
  66.  
  67. },
  68. Response.ErrorListener {
  69. // typically this is a connection error
  70. Log.d("ADVTECH", it.toString())
  71. })
  72. {
  73. @Throws(AuthFailureError::class)
  74. override fun getHeaders(): Map<String, String> {
  75. // we have to specify a proper header, otherwise Apigility will block our queries!
  76. // define we are after JSON data!
  77. val headers = HashMap<String, String>()
  78. headers["Accept"] = "application/json"
  79. headers["Content-Type"] = "application/json; charset=utf-8"
  80. return headers
  81. }
  82. }
  83.  
  84. // Add the request to the RequestQueue. This has to be done in both getting and sending new data.
  85. val requestQueue = Volley.newRequestQueue(context)
  86. requestQueue.add(stringRequest)
  87. }
  88.  
  89. override fun onDestroyView() {
  90. super.onDestroyView()
  91. _binding = null
  92. }
  93. }
  94.  
  95. // kun otetaan myös GSON mukaan, voidaan tehdä funktiossa näin:
  96.  
  97. fun getFeedbacks() {
  98.  
  99. // alustava lista Feedback-datalle + GSONin alustus
  100. var feedbacks : List<Feedback> = emptyList()
  101. val gson = GsonBuilder().setPrettyPrinting().create()
  102.  
  103. // tämä olisi hyvä olla myös local.propertiesissa
  104. // esim. DIRECTUS_ADDRESS
  105. // koodissa haetaan BuildConfig.DIRECTUS_ADDRESS
  106. // muista tällöin käynnistää sovellus kerran että BuildConfig päivittyy
  107.  
  108. // huomaa että access token on jokaisella omansa
  109. // myös portin pitää olla oikea, tässä tapauksessa 8055
  110. // ip osoite kuten 10.0.2.2 viittaa tietokoneeseen
  111. // ja portti 8055 viittaa tiettyyn sovellukseen tietokoneessa, eli Directusiin
  112. // 10.0.2.2 on virtuaaliosoite, joka osoittaa tietokoneen localhostiin
  113. // pelkkä localhost viittaisi tässä nyt Android-emulaattoriin
  114. val JSON_URL = "http://10.0.2.2:8055/items/feedback?access_token=zescNylxyUjOGBTfXrSYgysW52EbspyU"
  115.  
  116. // Request a string response from the provided URL.
  117. val stringRequest: StringRequest = object : StringRequest(
  118. Request.Method.GET, JSON_URL,
  119. Response.Listener { response ->
  120. // näytetään raakadata LogCatissa
  121. Log.d("TESTI", response)
  122.  
  123. // koska Directus tallentaa varsinaisen datan kenttään "data", pitää meidän
  124. // suodattaa alkuperäistä JSONia hieman
  125. val jObject = JSONObject(response)
  126. val jArray = jObject.getJSONArray("data")
  127.  
  128. // muutetaan lista Feedback-dataa Kotlin-dataksi
  129. feedbacks = gson.fromJson(jArray.toString() , Array<Feedback>::class.java).toList()
  130.  
  131. // testataan toimiiko data oikeasti -> silmukalla sijainnit LogCatiin
  132. for(item : Feedback in feedbacks) {
  133. Log.d("TESTI", item.location.toString())
  134. }
  135.  
  136. },
  137. Response.ErrorListener {
  138. // typically this is a connection error
  139. Log.d("ADVTECH", it.toString())
  140. })
  141. {
  142. @Throws(AuthFailureError::class)
  143. override fun getHeaders(): Map<String, String> {
  144. // we have to specify a proper header, otherwise Apigility will block our queries!
  145. // define we are after JSON data!
  146. val headers = HashMap<String, String>()
  147. headers["Accept"] = "application/json"
  148. headers["Content-Type"] = "application/json; charset=utf-8"
  149. return headers
  150. }
  151. }
  152.  
  153. // Add the request to the RequestQueue. This has to be done in both getting and sending new data.
  154. val requestQueue = Volley.newRequestQueue(context)
  155. requestQueue.add(stringRequest)
  156. }
  157.  
  158. // kytketään ulkkoasussa olevaan ListViewiin
  159. // ks. tämän osalta edellisen luennon muistiinpanot
  160.  
  161. Response.Listener { response ->
  162. // näytetään raakadata LogCatissa
  163. Log.d("TESTI", response)
  164.  
  165. // koska Directus tallentaa varsinaisen datan kenttään "data", pitää meidän
  166. // suodattaa alkuperäistä JSONia hieman
  167. val jObject = JSONObject(response)
  168. val jArray = jObject.getJSONArray("data")
  169.  
  170. // muutetaan lista Feedback-dataa Kotlin-dataksi
  171. feedbacks = gson.fromJson(jArray.toString() , Array<Feedback>::class.java).toList()
  172.  
  173. // testataan toimiiko data oikeasti -> silmukalla sijainnit LogCatiin
  174. for(item : Feedback in feedbacks) {
  175. Log.d("TESTI", item.location.toString())
  176. }
  177.  
  178. // luodaan adapteri ListViewille, voit korvata tämän RecyclerViewillä myös!
  179. // Huom: tämä ei toimi suoraan, johtuen ListViewin vaatimuksesta
  180. // käyttää vain Stringejä, ks. punainen kommentti alempaa
  181.  
  182. val adapter = ArrayAdapter(activity as Context, R.layout.simple_list_item_1, feedbacks)
  183.  
  184. // muista myös lisätä ListView fragmentin ulkoasuun (xml)
  185. // ListView löytyy Design-valikosta otsikon "Legacy" alta
  186. binding.listViewFeedbacks.adapter = adapter
  187.  
  188. }
  189.  
  190. // oletuksena ListView näyttää olion sisältä kaiken sisällön, koska ListView tukee vain String-muotoisia listoja.
  191. // helppoin tapa hoitaa tämä on yliajaa Feedback-luokan toString()-metodi, joka päättää mitä tulostetaan:
  192.  
  193. data class Feedback (
  194.  
  195. @SerializedName("id" ) var id : Int? = null,
  196. @SerializedName("name" ) var name : String? = null,
  197. @SerializedName("location" ) var location : String? = null,
  198. @SerializedName("value" ) var value : String? = null
  199.  
  200. )
  201. {
  202. // yliajetaan luokan toString-metodi
  203. // jotta ListView käyttää tätä Feedbackin tulostamiseen
  204. // muutoin ListView tulostaa kaikki sisällöt, mikä näyttää huonolta
  205. // ja saattaa muutenkin näyttää liikaa tietoa käyttöliittymässä
  206. override fun toString(): String {
  207. return "${name}: ${location}"
  208. }
  209. }
  210.  
  211.  
  212. // DATAN LÄHETTÄMINEN ANDROIDISSA DIRECTUSIIN
  213.  
  214. // testataan EditTextit läpi ensin:
  215.  
  216. class FeedbackSendFragment : Fragment() {
  217. private var _binding: FragmentFeedbackSendBinding? = null
  218. // This property is only valid between onCreateView and
  219. // onDestroyView.
  220. private val binding get() = _binding!!
  221. override fun onCreateView(
  222. inflater: LayoutInflater,
  223. container: ViewGroup?,
  224. savedInstanceState: Bundle?
  225. ): View? {
  226. _binding = FragmentFeedbackSendBinding.inflate(inflater, container, false)
  227. val root: View = binding.root
  228.  
  229. // kun nappia painetaan, haetaan jokainen EditTextin sisältö talteen muuttujiin
  230. binding.buttonSendFeedback.setOnClickListener {
  231. val name = binding.editTextFeedbackName.text.toString()
  232. val location = binding.editTextFeedbackLocation.text.toString()
  233. val value = binding.editTextFeedbackValue.text.toString()
  234.  
  235. // tulostetaan testimielessä lokiin kaikki
  236. Log.d("TESTI", "${name} - ${location} - ${value}")
  237. }
  238.  
  239. return root
  240. }
  241. override fun onDestroyView() {
  242. super.onDestroyView()
  243. _binding = null
  244. }
  245. }
  246.  
  247. // tehdään FeedbackSendFragment uusi apufunktio, jonka tehtävänä on lähettää uusi feedback Directusiin
  248.  
  249. // tehdään apufunktio, jonka avulla voidaan lähettää uusi Feedback Directusiin
  250. // käytännössä tämän sisälle tulee Volley-koodi, mutta POST-versio
  251. fun sendFeedback(name : String, location : String, value : String) {
  252.  
  253. }
  254.  
  255.  
  256. // tämän jälkeen pitää muistaa myös kutsua tätä funktiota Buttonin kautta kun tiedot on saatu haettua:
  257.  
  258. // kun nappia painetaan, haetaan jokainen EditTextin sisältö talteen muuttujiin
  259. binding.buttonSendFeedback.setOnClickListener {
  260. val name = binding.editTextFeedbackName.text.toString()
  261. val location = binding.editTextFeedbackLocation.text.toString()
  262. val value = binding.editTextFeedbackValue.text.toString()
  263.  
  264. // tulostetaan testimielessä lokiin kaikki
  265. Log.d("TESTI", "${name} - ${location} - ${value}")
  266.  
  267. sendFeedback(name, location, value)
  268. }
  269.  
  270.  
  271. // Volley-koodissa getBody() -metodi pitää ohjelmoida siten, että siinä rakennetaan uusi data Directusia varten
  272.  
  273. // let's build the new data here
  274. @Throws(AuthFailureError::class)
  275. override fun getBody(): ByteArray {
  276. // this function is only needed when sending data
  277. var body = ByteArray(0)
  278. try {
  279. // check the example "Converting a Kotlin object to JSON"
  280. // on how to create this newData -variable
  281.  
  282. // rakennetaan Feedback-olio lennosta, ja muutetaan se GSONin avulla tekstimuotoon, eli String
  283. var f : Feedback = Feedback()
  284. f.location = location
  285. f.name = name
  286. f.value = value
  287.  
  288. // muutetaan Feedback-olio -> JSONiksi
  289. var gson = GsonBuilder().create()
  290. var newData = gson.toJson(f)
  291.  
  292. body = newData.toByteArray(Charsets.UTF_8)
  293. } catch (e: UnsupportedEncodingException) {
  294. // problems with converting our data into UTF-8 bytes
  295. }
  296. return body
  297. }
  298.  
  299. // Jos halutaan käyttäjästä huolehtia sen jälkeen kuin uusi Feedback meni onnistuneesti perille, ks. Response-koodi FeedbackSendFragmentin Volley-koodissa:
  300.  
  301. Response.Listener { response ->
  302.  
  303. Log.d("TESTI", "Uusi feedback tallennettu!")
  304.  
  305. // idea 1: tyhjennetään EditTextit jotta käyttäjä huomaa että jotain tapahtui
  306. binding.editTextFeedbackLocation.setText("")
  307. binding.editTextFeedbackName.setText("")
  308. binding.editTextFeedbackValue.setText("")
  309.  
  310. // idea 2: näytetään ponnahdusviesti (Toast-viesti) että viesti on lähtenyt
  311. // yleensä jos context ei toimi, kokeile: activity as Context
  312. Toast.makeText(context, "Thank you for your feedback!", Toast.LENGTH_LONG).show()
  313.  
  314. // idea 3: siirretään käyttäjä automaattisesti FeedbackReadFragmentiin
  315. // jotta hän näkee oman uuden viestinsä
  316. // mobile_navigation -> tehdään action FeedbackSendFragmentista FeedbackReadFragmentiin
  317. // ei parametreja
  318. // ja tässä välissä ohjataan findNavControllerin avulla käyttäjä takaisin FeedbackReadFragmentiin
  319.  
  320. // Note: if you send data to API instead, this might not be needed
  321. },
  322.  
  323. // Basic Auth on hyvin yksinkertainen suojaus rajapintaan, mikä ei kuitenkaan tänä päivänä ole enää riittävä
  324. // siläl Base64-tekstin saa käännettyä molempiin suuntiin
  325.  
  326. // this is the url where we want to get our data
  327. // Note: if using a local server, use http://10.0.2.2 for localhost. this is a virtual address for Android emulators, since
  328. // localhost refers to the Android device instead of your computer
  329. val JSON_URL = "https://apingweb.com/api/auth/users"
  330.  
  331. // Request a string response from the provided URL.
  332. val stringRequest: StringRequest = object : StringRequest(
  333. Request.Method.GET, JSON_URL,
  334. Response.Listener { response ->
  335.  
  336. Log.d("TESTI", response)
  337. },
  338. Response.ErrorListener {
  339. // typically this is a connection error
  340. Log.d("TESTI", it.toString())
  341. })
  342. {
  343. @Throws(AuthFailureError::class)
  344. override fun getHeaders(): Map<String, String> {
  345. // we have to specify a proper header, otherwise Apigility will block our queries!
  346. // define we are after JSON data!
  347. val headers = HashMap<String, String>()
  348. headers["Accept"] = "application/json"
  349. headers["Content-Type"] = "application/json; charset=utf-8"
  350.  
  351. // replace with your own API's login info
  352. // basic authissa pitää rakentaa Authorization -teksti erikseen
  353. // muodosssa username:password , ja käännettynä Bsae64-formaattiin
  354. val authorizationString = "Basic " + Base64.encodeToString(
  355. ("admin" + ":" + "12345").toByteArray(), Base64.DEFAULT
  356. )
  357.  
  358. headers.put("Authorization", authorizationString)
  359.  
  360. return headers
  361. }
  362. }
  363.  
  364. // Add the request to the RequestQueue. This has to be done in both getting and sending new data.
  365. val requestQueue = Volley.newRequestQueue(context)
  366. requestQueue.add(stringRequest)
  367.  
  368.  
  369. // TEMP ACCESS TOKENIN KÄYTTÄMINEN
  370.  
  371. class TempAccessFragment : Fragment() {
  372. private var _binding: FragmentTempAccessBinding? = null
  373. // This property is only valid between onCreateView and
  374. // onDestroyView.
  375. private val binding get() = _binding!!
  376.  
  377. // HUOM! Tämä esimerkki on tehty hyvin pitkälle tyyliin "siitä mistä aita on matalin".
  378. // Jos haluat optimoida tätä rakennetta, ks. alla olevat kommentit
  379.  
  380. // tällä hetkellä koodin logiikka on tämä:
  381.  
  382. // jos datan hakemisessa tulee Auth-error -> kirjaudutaan kokonaan uudestaan rajapintaan.
  383. // tämäkin ratkaisu toimii (varsinkin pienillä käyttäjämäärillä), mutta tämän johdosta
  384. // Android-sovellus tekee paljon turhia kyselyjä Directusiin, koska kirjautuminen tehdään
  385. // aina virheen sattuessa tai fragmentin latautuessa uudelleen
  386.  
  387. // tämä voi muodostua ongelmaksi, mikäli sovelluksella on tuhansia aktiivisia käyttäjiä.
  388. // tällaisessa tilanteessa jokainen säästetty ja optimoitu kysely Directusin rajapintaan
  389. // säästää Androidin käyttämää suoritusaikaa, akkua sekä myös Directusista tulevaa käyttölaskua.
  390. // Mitä vähemmän Android-sovellus "rassaa" Directusin rajapintaa, sen halvempi ja energiatehokkaampi
  391. // oma Android-sovellus on.
  392.  
  393. // Parannusehdotus 1:
  394.  
  395. // hyödynnetään refresh tokenia access tokenin uusimisessa (kevyempi operaatio kuin uudestaan kirjautuminen)
  396. // refresh token tulee samassa datassa kuin access token myös. Access token on 15min voimassa, ja refresh
  397. // token on 7 päivää voimassa. Refresh tokenin avulla voi pyytää uuden access tokenin, mikäli refresh token
  398. // on vielä voimassa. Jos myös refresh token vanhenee -> kirjaudutaan uudestaan. (tämä logiikka pitää koodata itse)
  399.  
  400. // Parannusehdotus 2:
  401.  
  402. // Directusin kirjautumisdatassa tulee mukana myös tieto siitä, kuinka kauan access token on voimassa kirjautumishetkestä
  403. // alkaen, oletuksena 900000 millisekuntia -> 900 sekuntia -> 15min
  404. // Voidaan koodata Android-sovellus siten, että niin kauan kuin aikaa on jäljellä, Directusiin ei lähetetä
  405. // yhtään kirjautumispyyntöä. Tällä tavalla Android-sovellus ei turhaan ole yhteydessä Directusiin,
  406. // koska äppi pitää itse kirjaa siitä milloin pitää kirjautua uusiksi.
  407.  
  408. // Parannusehdotus 3:
  409.  
  410. // kaikki kirjautumiseen liittyvä Volley-logiikka on hyvä keskittää yhteen paikkaan, joko kustomoituun
  411. // Application -luokkaan, tai tehdä (suositellumpi tapa) Volley-kutsuille oma Singleton-luokka.
  412. // ks. Google ja Volleyn dokumentaatio esimerkistä miten tämä tehdään.
  413.  
  414. // seuraavat laitettu local.propertiesiin
  415. // muista käyttää ohjelmaa päällä jotta BuildConfig päivittyy
  416.  
  417. // DIRECTUS_HOST=http://10.0.2.2:8055
  418. // DIRECTUS_EMAIL=joku@jossain.com
  419. // DIRECTUS_PASSWORD=Password123!
  420.  
  421. // VARIABLES USED BY THE SESSION MANAGEMENT
  422. val LOGIN_URL = BuildConfig.DIRECTUS_HOST + "/auth/login"
  423.  
  424. // these should be placed in the local properties file and used by BuildConfig
  425. // JSON_URL should be WITHOUT a trailing slash (/)!
  426. val JSON_URL = BuildConfig.DIRECTUS_HOST
  427.  
  428. // if using username + password in the service (e.g. Directus), use these
  429. val username = BuildConfig.DIRECTUS_EMAIL
  430. val password = BuildConfig.DIRECTUS_PASSWORD
  431.  
  432. // request queues for requests
  433. var requestQueue: RequestQueue? = null
  434. var refreshRequestQueue: RequestQueue? = null
  435.  
  436. // state booleans to determine our session state
  437. var loggedIn: Boolean = false
  438. var needsRefresh: Boolean = false
  439.  
  440. // stored tokens. refresh is used when our session token has expired
  441. // access token in this case is the same as session token
  442. var refreshToken = ""
  443. var accessToken = ""
  444.  
  445. override fun onCreateView(
  446. inflater: LayoutInflater,
  447. container: ViewGroup?,
  448. savedInstanceState: Bundle?
  449. ): View? {
  450. _binding = FragmentTempAccessBinding.inflate(inflater, container, false)
  451. val root: View = binding.root
  452.  
  453. binding.buttonGetRawData.setOnClickListener {
  454. dataAction()
  455. }
  456.  
  457. return root
  458. }
  459.  
  460. // fragment entry point
  461. override fun onViewCreated(view: View, savedInstanceState: Bundle?)
  462. {
  463. super.onViewCreated(view, savedInstanceState);
  464.  
  465. requestQueue = Volley.newRequestQueue(context)
  466. refreshRequestQueue = Volley.newRequestQueue(context)
  467.  
  468. // start with login
  469. loginAction()
  470. }
  471.  
  472. // button methods
  473. fun loginAction()
  474. {
  475. Log.d("ADVTECH", "login")
  476. Log.d("ADVTECH", JSON_URL + " login")
  477. requestQueue?.add(loginRequest)
  478. }
  479.  
  480. fun refreshLogin() {
  481. if (needsRefresh) {
  482. loggedIn = false
  483. // use this if using refresh logic
  484. //refreshRequestQueue?.add(loginRefreshRequest)
  485.  
  486. // if using refresh logic, comment this line out
  487. loginAction()
  488. }
  489. }
  490.  
  491. fun dataAction() {
  492. if (loggedIn) {
  493. requestQueue?.add(dataRequest)
  494. }
  495. }
  496.  
  497. override fun onDestroyView() {
  498. super.onDestroyView()
  499. _binding = null
  500. }
  501.  
  502. // REQUEST OBJECTS
  503.  
  504. // REQUEST OBJECT 1: LOGIN
  505. var loginRequest: StringRequest = object : StringRequest(
  506. Request.Method.POST, LOGIN_URL,
  507. Response.Listener { response ->
  508.  
  509. var responseJSON: JSONObject = JSONObject(response)
  510.  
  511. // save the refresh token too if using refresh logic
  512. // refreshToken = responseJSON.get("refresh_token").toString()
  513.  
  514. // this part depends completely on the service that is used
  515. // Directus uses the data -> access_token -approach
  516. // IBM Cloud handles the version in comments
  517. // accessToken = responseJSON.get("access_token").toString()
  518. accessToken = responseJSON.getJSONObject("data").get("access_token").toString()
  519.  
  520. loggedIn = true
  521.  
  522. // after login's done, get data from API
  523. dataAction()
  524.  
  525. Log.d("ADVTECH", response)
  526. },
  527. Response.ErrorListener {
  528. // typically this is a connection error
  529. Log.d("ADVTECH", it.toString())
  530. }) {
  531. @Throws(AuthFailureError::class)
  532. override fun getHeaders(): Map<String, String> {
  533. // we have to provide the basic header info
  534. // + Bearer info => accessToken
  535. val headers = HashMap<String, String>()
  536. headers["Accept"] = "application/json"
  537.  
  538. // IBM Cloud expects the Content-Type to be the following:
  539. // headers["Content-Type"] = "application/x-www-form-urlencoded"
  540.  
  541. // for Directus, the typical approach works:
  542. headers["Content-Type"] = "application/json; charset=utf-8"
  543.  
  544. return headers
  545. }
  546.  
  547. // use this to build the needed JSON-object
  548. // this approach is used by Directus, IBM Cloud uses the commented version instead
  549. @Throws(AuthFailureError::class)
  550. override fun getBody(): ByteArray {
  551. // this function is only needed when sending data
  552. var body = ByteArray(0)
  553. try {
  554. // on how to create this newData -variable
  555. var newData = ""
  556.  
  557. // a very quick 'n dirty approach to creating the needed JSON body for login
  558. newData = "{\"email\":\"${username}\", \"password\": \"${password}\"}"
  559.  
  560. // JSON to bytes
  561. body = newData.toByteArray(Charsets.UTF_8)
  562. } catch (e: UnsupportedEncodingException) {
  563. // problems with converting our data into UTF-8 bytes
  564. }
  565. return body
  566. }
  567.  
  568. }
  569.  
  570. // REQUEST OBJECT 3 : ACTUAL DATA -> FEEDBACK
  571. var dataRequest: StringRequest = object : StringRequest(
  572. Request.Method.GET, JSON_URL+"/items/feedback",
  573. Response.Listener { response ->
  574. Log.d("ADVTECH", response)
  575.  
  576. binding.textViewTempFeedbackRaw.text = response
  577. },
  578. Response.ErrorListener {
  579. // typically this is a connection error
  580. Log.d("ADVTECH", it.toString())
  581.  
  582. if (it is AuthFailureError) {
  583. Log.d("ADVTECH", "EXPIRED start")
  584.  
  585. needsRefresh = true
  586. loggedIn = false
  587. refreshLogin()
  588.  
  589. Log.d("ADVTECH", "EXPIRED end")
  590. }
  591. }) {
  592. @Throws(AuthFailureError::class)
  593. override fun getHeaders(): Map<String, String> {
  594. // we have to provide the basic header info
  595. // + Bearer info => accessToken
  596. val headers = HashMap<String, String>()
  597. // headers["Accept"] = "application/json"
  598. // headers["Content-Type"] = "application/json; charset=utf-8"
  599. headers["Authorization"] = "Bearer " + accessToken
  600. return headers
  601. }
  602.  
  603. }
  604. }
  605.  
Add Comment
Please, Sign In to add comment