티스토리 뷰

아이폰의 경우에는 CoreMotion을 사용하면 비교적 쉽게 가져올수있지만 

안드로이드는 좀 많이 달라서 천천히 기초적인 것을 먼저 공부해볼까 합니다.

 

그래서 이번 포스트에서는 앱을 킨 상태에서 걸음수를 측정해볼께요.

(레이아웃은 최소한만 잡고 할께요.)

 

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">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/step_detector_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="아직 걷기전" />

        <TextView
            android:id="@+id/step_count_tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="아직 걷기전" />
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

 

안드로이드는 걸음수를 측정할때 

센서를 거의 반드시 사용해야하기 때문에 권한이 필요합니다.  

AndroidManifest.xml 에 반드시 추가해주세요.

<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"
    tools:remove="android:maxSdkVerSion"/>
<!-- 센서 권한 입니다. -->

 

MainActivity.kt

그럼 이제 본격적으로 시작해볼까요?

그전에 사전 준비를 위해 몇가지를 미리 정의하고 시작할께요. 

 

0. 필요한  재료들 미리 선언해주세요.

// UI
var dectTextView : TextView? = null // 걸음 센서 작동용
var countTextView : TextView? = null // 총괄 걸음수 작동용
// FUNCTION
var stepDetector : Int = 0 // 걸음 센서 작동 카운터
var stepCounter : Int = 0 // 시작시 총괄 걸음수 카운터
//Sensor
var stepDetectorSensor : Sensor? = null// 걸음 센서 작동 센서
var stepCounterSensor : Sensor? = null// 시작시 총괄 걸음수 센서

private lateinit var sensorManager: SensorManager // 전체 센서 작동

 

이제 순서대로 필요한 걸 추가해봅시다.  

 

1. 추가해준 권한을 요구하는 함수부터 만들어 줍시다. 

fun checkPermission(){
    if(ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_DENIED){
        // 권한이 거절된 경우
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(arrayOf(
                Manifest.permission.ACTIVITY_RECOGNITION),0)
        }
    }
}

2. 센서를 작동시킬 준비를 해주세요. 

fun startSensorWork(){
    sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
    stepDetectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR) // 걸음수
    stepCounterSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER) // 카운터
}

2-1 Sensor.TYPE_STEP_DETECTOR 랑 Sensor.TYPE_STEP_COUNTER 가 뭔가요?

- 둘다 걸음수를 측정할때 사용되는 센서입니다. 저는 둘다 사용해 볼께요.

- 상황에 따라 더 적합한걸 사용하시면 됩니다.

  • 둘 다 사용자가 걸었다고 인지하면 작동합니다.
  • TYPE_STEP_DETECTOR :  작동시 1.0의값을 줍니다. COUNTER에 비해 속도가 빠릅니다.  
  • TYPE_STEP_COUNTER : 사용자가 걸을때 휴대폰이 켜진 상태에서 걸은 총 누적 걸음수를 돌려줍니다. 
  • COUNTER의 경우 휴대폰을 재시작하시면 0 부터 다시 시작합니다. 

2-2 센서 이벤트를 감지해주는 부분을 만들어줍니다.

- 아래처럼 SensorEventListener 먼저 추가해주시고 

class MainActivity : AppCompatActivity(),SensorEventListener {

- 센서가 작동시 작동시킬 함수를 같이 만들어주세요.

// 센서에서 값을 받아오는 속도 조절
override fun onStart() {
        super.onStart()
        if(stepDetectorSensor != null && stepCounterSensor != null){
            sensorManager.registerListener(this,stepDetectorSensor,SensorManager.SENSOR_DELAY_FASTEST)
            sensorManager.registerListener(this,stepCounterSensor,SensorManager.SENSOR_DELAY_FASTEST)
        }
    }
//Dect 용
    fun dectMotion(){
        stepDetector += 1
        dectTextView?.text = "감지 횟수 : $stepDetector"
    }
    //Counter 용
    fun countMotion(nowValue : Int){
        val getStep = nowValue - this.stepCounter
        countTextView?.text = "걸음수 : $getStep"
    }
// 센서 감지 및
    override fun onSensorChanged(event: SensorEvent?) {
        if(event?.sensor?.type == Sensor.TYPE_STEP_DETECTOR){
            if(event.values.first() == 1.0f){ // 걸었다는 신호
                this.dectMotion() // 1씩증가
            }
        }
        if(event?.sensor?.type == Sensor.TYPE_STEP_COUNTER){
            if (this.stepCounter <= 0){ // 맨처음 시작인 경우
                this.stepCounter = event.values.first().toInt()
            }else{ // 현재 누적값에서 지금 누적값을 빼서 구하는 방법 
                this.countMotion(event.values.first().toInt())
            }
        }
    }

    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
//        TODO("Not yet implemented")
    }

 - TYPE_STEP_DETECTOR는 1씩 증가 / TYPE_STEP_COUNTER는 총걸음수의 차이량을 표시하게 만들어 둘께요.

 

3. onCreate 에 여태까지 만들걸 넣고 실행해주세요.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    dectTextView = findViewById<TextView>(R.id.step_detector_tv)
    countTextView = findViewById<TextView>(R.id.step_count_tv)

    checkPermission()
    startSensorWork()
}

4. 실행하고 권한을 수락해주세요.

허용해주셔야 센서를 사용할수있어요!

5. 실제로 열심히 걷거나 흔드시면(?) 숫자가 바뀌는걸 알 수 있습니다.

- 자세히 보시면 둘의 숫자 차이가 있다는 걸 알 수 있습니다.

- 걸음수의 경우 느리긴하지만 Counter 가 더 정확하다고 합니다. 

열심히 흔들어주세요.

* MainActivity.kt 전체 코드 

class MainActivity : AppCompatActivity(),SensorEventListener {

    // UI
    var dectTextView : TextView? = null // 걸음 센서 작동용
    var countTextView : TextView? = null // 총괄 걸음수 작동용
    // FUNCTION
    var stepDetector : Int = 0 // 걸음 센서 작동 카운터
    var stepCounter : Int = 0 // 시작시 총괄 걸음수 카운터
    //Sensor
    var stepDetectorSensor : Sensor? = null// 걸음 센서 작동 센서
    var stepCounterSensor : Sensor? = null// 시작시 총괄 걸음수 센서

    private lateinit var sensorManager: SensorManager // 전체 센서 작동

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        dectTextView = findViewById<TextView>(R.id.step_detector_tv)
        countTextView = findViewById<TextView>(R.id.step_count_tv)
        checkPermission()
        startSensorWork()
    }
    override fun onStart() {
        super.onStart()
        if(stepDetectorSensor != null && stepCounterSensor != null){
            sensorManager.registerListener(this,stepDetectorSensor,SensorManager.SENSOR_DELAY_FASTEST)
            sensorManager.registerListener(this,stepCounterSensor,SensorManager.SENSOR_DELAY_FASTEST)
        }
    }
    fun checkPermission(){
        if(ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_DENIED){
            // 권한이 거절된 경우
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                requestPermissions(arrayOf(
                    Manifest.permission.ACTIVITY_RECOGNITION),0)
            }
        }
    }

    fun startSensorWork(){
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        stepDetectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR) // 걸음수
        stepCounterSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER) // 카운터
    }
    //Dect 용
    fun dectMotion(){
        stepDetector += 1
        dectTextView?.text = "감지 횟수 : $stepDetector"

    }
    //Counter 용
    fun countMotion(nowValue : Int){
        val getStep = nowValue - this.stepCounter
        countTextView?.text = "걸음수 : $getStep"
    }

    // 센서 감지 및
    override fun onSensorChanged(event: SensorEvent?) {
        if(event?.sensor?.type == Sensor.TYPE_STEP_DETECTOR){
            if(event.values.first() == 1.0f){ // 걸었다는 신호
                this.dectMotion() // 1씩증가
            }
        }
        if(event?.sensor?.type == Sensor.TYPE_STEP_COUNTER){
            if (this.stepCounter <= 0){ // 맨처음 시작인 경우
                this.stepCounter = event.values.first().toInt()
            }else{ // 현재 누적값에서 지금 누적값을 빼서 구하는 방법
                this.countMotion(event.values.first().toInt())
            }
        }
    }

    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
//        TODO("Not yet implemented")
    }
}

 

여기까지 드디어 걸음수 측정의 기초를 다루어 봤는데요

이 원리를 응용하면 만보기앱도 쉽게 만들 수 있겠죠?

 

도움이 되시길 바라며

오늘도 파이팅입니다~

댓글