안드로이드의 가속도 센서를 이용하여, 핸드폰이 흔들리는 것(Shaking)을 감지해보겠습니다. 즉, 핸드폰이 위에서 아래로, 아래에서 위로 가면, 이벤트가 발생하는 것입니다. 간단한 예로 들자면, 만보계를 위한 이벤트 인식정도라고 생각하시면 되겠습니다. 한번 흔드는 것을 감지하는 소스입니다. How to detect shake motion on Android phone 사이트를 통해 샘플 코드를 가져왔으며, SDK가 업그레이드 되면서, 바뀐 부분이 많이 있어 수정한 소스입니다.
Shaking 이미지 출처 : China Grabber
STEP 1 Java Source Code
핸드폰이 흔들리는 것을 감지하려면, 당연히 가속도 센서를 이용해야겠죠? 가속도 센서는 핸드폰을 기준으로 x, y, z 방향으로의 가속도만 측정이 가능합니다. 즉, 이 방향성을 가지는 가속도를 가지고 제대로된 움직임을 감지해야하는 것이죠. 센서를 사용하기 위해 SensorListener를 상속받는 엑티비티를 생성합니다. 차례차례 코드를 보며 설명해드리겠습니다.
import android.app.Activity; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; public class ShakeActivity extends Activity implements SensorEventListener { private long lastTime; private float speed; private float lastX; private float lastY; private float lastZ; private float x, y, z; private static final int SHAKE_THRESHOLD = 800; private static final int DATA_X = SensorManager.DATA_X; private static final int DATA_Y = SensorManager.DATA_Y; private static final int DATA_Z = SensorManager.DATA_Z; private SensorManager sensorManager; private Sensor accelerormeterSensor; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); accelerormeterSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); } @Override public void onStart() { super.onStart(); if (accelerormeterSensor != null) sensorManager.registerListener(this, accelerormeterSensor, SensorManager.SENSOR_DELAY_GAME); } @Override public void onStop() { super.onStop(); if (sensorManager != null) sensorManager.unregisterListener(this); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { long currentTime = System.currentTimeMillis(); long gabOfTime = (currentTime - lastTime); if (gabOfTime > 100) { lastTime = currentTime; x = event.values[SensorManager.DATA_X]; y = event.values[SensorManager.DATA_Y]; z = event.values[SensorManager.DATA_Z]; speed = Math.abs(x + y + z - lastX - lastY - lastZ) / gabOfTime * 10000; if (speed > SHAKE_THRESHOLD) { // 이벤트발생!! } lastX = event.values[DATA_X]; lastY = event.values[DATA_Y]; lastZ = event.values[DATA_Z]; } } } }
onCreate 부분에서는 센서를 사용하기 위해서 시스템 서비스를 가져와서 SensorManager 타입으로 저장해둡니다. onAccuracyChanged와 onSensorChanged를 오버라이딩 해줘야 합니다. 함수 이름에서 보시듯 정확도와 센서 정보가 변하면 발생하는 함수입니다. 흔드는 것을 감지하는 핵심적인 소스는 onSensorChanged 함수에 있습니다. 센서가 변함에 따라 이 함수가 실행됩니다. 센서 종류가 가속도 센서일 때, 이벤트를 처리해줘야합니다. 최근 측정한 시간과 현재 시간을 비교하여 0.1초 이상되었을 때, 흔듬을 감지합니다. 이 흔듬을 감지하는 함수는 조금씩 수정이 가능합니다. 자신의 프로그램에 맞게 설정할 해줄 수 있습니다. 기본적으로는 위의 소스코드에서 보이는 것처럼, 가속도의 벡터값을 이용하여 대략적으로 측정합니다. 정확도면에서는 약간 떨어지겠죠. SHAKE_THRESHOLD 또한 잘 설정을 해줘야 합니다. 속도가 얼마 이상일 때, 흔듬을 감지하겠다는 것을 설정해주는 부분입니다. 기기에 따라 약간씩 다를 수 있으니, 실제로 테스트를 해보면서 값을 조절해야합니다. 나머지 코드 부분은 쉽게 알 수 있는 부분이라 생략하겠습니다.
STEP 2 Xml Code
Xml코드는 생략하겠습니다.
간단히 흔들리는 횟수를 출력하는 것으로 제대로 동작하고 있는지 확인할 수 있습니다.
STEP 3 AndroidManifest.xml Code
가속도 센서를 이용하기 위해, AndroidManifest.xml 에 추가적으로 권한 설정은 필요치 않습니다.
<마무리> 가속도 센서를 이용한 흔듬(Shake) 감지
가속도 센서를 이용하여 다양한 방법으로 어플리케이션을 구성할 수 있습니다. 여러 용도로 쓸 수 있겠지만, 여기에서는 가장 간단한 흔듬(shake) 감지를 위한 소스코드에 대해서 알아보았습니다. SensorEventListener를 상속받고, SensorManager를 이용하여 센서를 사용할 수 있도록 등록시킵니다. 그리고 onAccuracyChanged와 onSensorChanged를 오버라이딩을 해줌으로써, 가속도 센서 변화값에 따라 흔듬을 감지할 수 있도록 구성하였습니다. 가속도 센서의 값과 속도, 거리에 따라 다양하게 활용할 수 있습니다. 오늘의 핵심은 가속도 센서를 사용하는 방법입니다.
[ 참고자료 ]
Google Developer
Detecting "Shake" with Accelerometer
How to detect shake motion on Android phone