본문 바로가기
Projects/센서 모니터링 시스템

[센서 모니터링 시스템] 12. Android Request 구현

by DevJaewoo 2022. 8. 19.
반응형

Intro

시간이 조금 남아서 간단하게라도 안드로이드 앱을 만들어볼 예정이다.

우선 서버로 센서 데이터 Request를 보내고, Response를 받는 것부터 해보자.

언어는 Kotlin을 사용했다. Kotlin에 편한 함수들이 많다.

 

HTTP 라이브러리로는 Volley를 사용했다.

https://developer.android.com/training/volley?hl=ko 

 

Volley 개요  |  Android 개발자  |  Android Developers

Volley 개요 Volley는 Android 앱의 네트워킹을 더 쉽고, 무엇보다도 더 빠르게 하는 HTTP 라이브러리입니다. Volley는 GitHub에서 사용할 수 있습니다. Volley를 사용하면 다음과 같은 이점이 있습니다. 네트

developer.android.com


환경설정

우선 Gradle에 Volley를 추가한다.

dependencies {
    implementation 'com.android.volley:volley:1.2.1'
}

 

그리고 HTTP 요청을 보내기 위해 AndroidManifest를 수정해야 한다.

android.permission.INTERNETandroid:useCleartextTraffic='true"를 추가하면 된다.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.devjaewoo.sensormonitoringapp">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        ...
        android:usesCleartextTraffic="true">
        ...
    </application>

</manifest>

 

그리고 필요한 상수들을 선언한다.

Any.TAG는 선언해두면 Log.d 사용 시 첫번째 인자로 넣을 수 있다. 있으면 많이 편리하다.

Constants.kt

package com.devjaewoo.sensormonitoringapp

val Any.TAG: String
    get()  = if(javaClass.simpleName.length <= 23) javaClass.simpleName else javaClass.simpleName.substring(0, 23)

const val CHART_SIZE: Int = 6

const val SERVER_URL: String = "http://192.165.90.32:8080"

Request용 Object 생성

아래의 코드를 복사해 새로운 Object를 만든다.

다른 프로젝트에서 만들어둔 모듈인데 이렇게 사용될줄은 몰랐다.

지금처럼 시간이 얼마 없는 상황에서 복사해올게 있어 참 다행이다.

범용성 좋게 만들길 잘한것 같다.

RequestHandler.kt

package com.devjaewoo.sensormonitoringapp.request

import android.util.Log
import android.widget.Toast
import com.android.volley.*
import com.android.volley.toolbox.JsonObjectRequest
import com.android.volley.toolbox.Volley
import com.devjaewoo.sensormonitoringapp.ApplicationManager
import com.devjaewoo.sensormonitoringapp.SERVER_URL
import com.devjaewoo.sensormonitoringapp.TAG
import org.json.JSONObject


object RequestHandler {
    var accessToken: String = ""
    private val requestQueue = Volley.newRequestQueue(ApplicationManager.applicationContext)

    private val defaultErrorListener = Response.ErrorListener { error ->
        Log.d(TAG, "error: $error")
        val body = JSONObject(String(error.networkResponse.data))
        val errorMessage = body.getString("message")
        Log.e(TAG, "defaultErrorListener: code: ${error.networkResponse.statusCode} message: $errorMessage")
        Toast.makeText(ApplicationManager.applicationContext, errorMessage, Toast.LENGTH_SHORT).show()
    }

    fun request(url: String, jsonObject: JSONObject?, responseListener: Response.Listener<JSONObject>, errorListener: Response.ErrorListener?, requestWithToken: Boolean, method: Int) {

        val requestURL = SERVER_URL + url
        Log.d(TAG, "request: $requestURL with data $jsonObject")

        val jsonObjectRequest = object : JsonObjectRequest(
            method,
            requestURL,
            jsonObject,
            responseListener,
            errorListener ?: defaultErrorListener
        ) {

            override fun getHeaders(): MutableMap<String, String> {
                return if(requestWithToken) HashMap<String, String>().apply { put("Authorization", "Bearer $accessToken") } else super.getHeaders()
            }
        }

        requestQueue.add(jsonObjectRequest)
    }
}

Request 테스트

이제 간단한 버튼을 만들고 JSON 응답을 잘 받아오는지 테스트 해보자.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    
</androidx.constraintlayout.widget.ConstraintLayout>

 

MainActivity.kt

package com.devjaewoo.sensormonitoringapp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.android.volley.Request
import com.devjaewoo.sensormonitoringapp.databinding.ActivityMainBinding
import com.devjaewoo.sensormonitoringapp.request.RequestHandler

class MainActivity : AppCompatActivity() {

    private var _binding: ActivityMainBinding? = null
    private val binding: ActivityMainBinding get() = _binding!!

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        _binding = ActivityMainBinding.inflate(layoutInflater)

        binding.button.setOnClickListener {
            RequestHandler.request("/api/1/sensor", null, {jsonObject -> Log.d(TAG, "onCreate: $jsonObject")}, null, false, Request.Method.GET)
        }

        setContentView(binding.root)
    }
}

 

앱을 실행하고 버튼을 누르면 데이터가 잘 들어오는것을 확인할 수 있다.

측정 결과

사진이 잘려서 터미널에서 텍스트를 복사해왔다.

2022-08-19 17:05:11.910 14876-14876/com.devjaewoo.sensormonitoringapp D/RequestHandler: request: http://192.165.90.32:8080/api/1/sensor with data null
2022-08-19 17:05:11.966 14876-14876/com.devjaewoo.sensormonitoringapp D/MainActivity: onCreate: {"sensorData":[{"eco2":436,"tvoc":5,"temp":29.28,"accel":{"x":-1.2977,"y":-0.0168,"z":9.8809},"createdDate":"2022-08-19T16:43:05.297205"},{"eco2":436,"tvoc":5,"temp":29.38,"accel":{"x":-1.3024,"y":-0.0455,"z":9.6989},"createdDate":"2022-08-19T16:43:04.151059"},{"eco2":432,"tvoc":4,"temp":29.33,"accel":{"x":-1.3048,"y":-0.0503,"z":9.7947},"createdDate":"2022-08-19T16:43:03.009536"},{"eco2":442,"tvoc":6,"temp":29.38,"accel":{"x":-1.3551,"y":-0.0311,"z":9.7396},"createdDate":"2022-08-19T16:43:01.872407"},{"eco2":436,"tvoc":5,"temp":29.42,"accel":{"x":-1.3479,"y":-0.0479,"z":9.8114},"createdDate":"2022-08-19T16:43:00.736431"},{"eco2":432,"tvoc":4,"temp":29.42,"accel":{"x":-1.3024,"y":-0.0575,"z":9.7396},"createdDate":"2022-08-19T16:42:59.585145"},{"eco2":436,"tvoc":5,"temp":29.38,"accel":{"x":-1.3982,"y":-0.0144,"z":9.7229},"createdDate":"2022-08-19T16:42:58.447736"},{"eco2":442,"tvoc":6,"temp":29.33,"accel":{"x":-1.3408,"y":0.0263,"z":9.7803},"createdDate":"2022-08-19T16:42:56.228591"},{"eco2":442,"tvoc":6,"temp":29.33,"accel":{"x":-1.3192,"y":-0.067,"z":9.7636},"createdDate":"2022-08-19T16:42:55.090591"},{"eco2":439,"tvoc":5,"temp":29.28,"accel":{"x":-1.2857,"y":-0.0503,"z":9.8162},"createdDate":"2022-08-19T16:42:53.952317"},{"eco2":444,"tvoc":6,"temp":29.42,"accel":{"x":-1.2689,"y":-0.0431,"z":9.7133},"createdDate":"2022-08-19T16:42:51.791102"},{"eco2":439,"tvoc":5,"temp":29.38,"accel":{"x":-1.3216,"y":-0.0838,"z":9.7995},"createdDate":"2022-08-19T16:42:50.62493"},{"eco2":439,"tvoc":5,"temp":29.38,"accel":{"x":-1.3024,"y":-0.012,"z":9.6462},"createdDate":"2022-08-19T16:42:49.488359"},{"eco2":439,"tvoc":5,"temp":29.42,"accel":{"x":-1.3048,"y":-0.012,"z":9.7372},"createdDate":"2022-08-19T16:42:48.344005"},{"eco2":439,"tvoc":5,"temp":29.42,"accel":{"x":-1.2617,"y":-0.0239,"z":9.7636},"createdDate":"2022-08-19T16:42:47.204543"},{"eco2":439,"tvoc":5,"temp":29.38,"accel":{"x":-1.2546,"y":-0.012,"z":9.7372},"createdDate":"2022-08-19T16:42:45.885326"},{"eco2":439,"tvoc":5,"temp":29.33,"accel":{"x":-1.3862,"y":-0.0575,"z":9.7516},"createdDate":"2022-08-19T16:42:44.751449"},{"eco2":439,"tvoc":5,"temp":29.47,"accel":{"x":-1.324,"y":0.0359,"z":9.754},"createdDate":"2022-08-19T16:42:43.403443"},{"eco2":439,"tvoc":5,"temp":29.38,"accel":{"x":-1.391,"y":-0.0479,"z":9.7899},"createdDate":"2022-08-19T16:42:42.268446"},{"eco2":439,"tvoc":133,"temp":29.42,"accel":{"x":-1.3384,"y":-0.0527,"z":9.7803},"createdDate":"2022-08-19T16:42:40.083918"}]}

 

다음번엔 차트 라이브러리를 이용해 받아온 센서 데이터를 출력해보도록 하겠다.

반응형