2010년 8월 17일 화요일

안드로이드 센서 시뮬레이터 (Sensor Simulator in Android)

안드로이드에서 센서를 사용하는 어플리케이션을 개발할 때 에뮬레이터는 센서를 지원하지 않기 때문에 동작을 테스트 할 방법이 없다. 그래서 인터넷을 뒤져 본 결과 에뮬레이터에서 센서 입력을 시뮬레이션 해 줄수있는 툴을 발견했다. OpenIntents가 개발한 SensorSimulator로 별도 프로그램에서 에뮬레이터에서 실행되고 있는 어플리케이션에 센서 값을 보내줄 수 있다.


먼저 SensorSimulator 를 다운받는다. 다운받은 압축을 풀어보면 다음과 같은 파일이 들어있다.


이 중 bin 디렉토리를 보면 다음과 같은 파일이 들어있다.


이 파일중 SensorSimulatorSettings.apk 파일은 에뮬레이터에 인스톨 해 줘야 하고 sensorsimulator.jar는 pc에서 실행할 바이너리 파일이다.


먼저 커맨드 라인에서 adb를 사용해서 SensorSimulatorSettings.apk를 에뮬레이터에 설치해준다.


설치가 끝났으면 PC에서 sensorsimulator.jar를 실행시킨다. 프로그램이 실행되면 위와 같은 화면이 나온다.


에뮬레이터를 실행해보면 SensorSimulatorSettings가 설치된 걸 볼 수 있다. 에뮬레이터에 설치된 앱을 실행한다.


sensorsimulator 화면을 보고 적절한 IP주소와 포트번호를 에뮬레이터의 앱에 넣어준다.


에뮬레이터에서 Testing 탭을 선택한 다음 Connect 버튼을 누른다.


IP 주소와 포트번호가 제대로 설정되었다면 sensorsimulator에 연결되었다는 메시지가 나오고 에뮬레이터에도 위와 같은 화면이 나온다.


초기 연결되었을 때는 모든 센서가 disable상태이기 때문에 에뮬레이터에서 테스트하려는 센서를 선택해서 활성화 시켜주면 된다. 그리고 sensorsimulator의 휴대폰 그림을 클릭하고 움직여보면 그에 따른 센서값의 변화가 에뮬레이터로 전달되어 센서 값이 업데이트 되는걸 볼 수 있다.

-----------------------------------------------------------------------

자신의 앱을 센서 시뮬레이터를 사용해서 테스트 하는 법

1. SensorSimulatorSettings를 실행해서 위와 같이 필요한 설정을 해 준다.

2. 프로젝트 루트에 lib 디렉토리를 만든다.


3. sensorsimulator-xxx/lib/sensorsimulator-lib.jar 파일을 lib 디렉토리에 넣어 준다.


4. 프로젝트의 Properties 메뉴를 선택한다.


5. Java Build Path -> Libraries -> Add JARs...를 선택한다.


6. 방금전에 넣어 준 sensorsimulator-lib.jar를 선택해 추가해준다.


7. sensorsimulator-lib.jar가 Java Build Path의 Libraries에 추가된 걸 확인할 수 있다.


8. Java 소스코드에서 SensorManager를 SensorManagerSimulator로 변경해줘야 한다. 아래와 같이 SensorManager 인스턴스를 가져오는 방법을 변경하고 시뮬레이터에 연결하도록 변경해 주면 된다.


9. 센서 시뮬레이터가 앱에 시뮬레이션 되는 센서 데이터는 소켓을 통해 통신하기 때문에 INTERNET permission이 필요하다. AndroidManifest.xml에 아래와 같이 추가해 주면 된다.


10. PC에 sensorsimulator를 실행한 다음 에뮬레이터에서 앱을 실행하면 앱이 시뮬레이터에 자동으로 연결된다.


11. 시뮬레이터의 휴대폰 그림을 움직이면 에뮬레이터 화면에서 센서값이 변화되는걸 볼 수 있다.


* 센서 인터페이스가 API level 3(Android SDK 1.5)부터 SensorListener에서 SensorEventListener로 바뀌면서 센서 관련 API가 변경되었는데 아쉽게도 SensorSimulator는 SensorListener를 사용하는 API만 지원한다. 그래서 이전 포스트의 코드를 바로 사용할 수는 없고 이전 API에 맞게 조금 변형해 줘야 한다. res/layout/main.xml은 동일한 코드를 사용하면 된다.

/src/.../SensorSimTest.java

...
import org.openintents.sensorsimulator.hardware.SensorManagerSimulator;
...
public class SensorSimTest extends Activity {
    SensorManagerSimulator sm;
    SensorListener sl;
    TextView ax, ay, az;
    TextView ox, oy, oz;
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        sm = SensorManagerSimulator.getSystemService(this, SENSOR_SERVICE);
        sm.connectSimulator();

        sl = new SL();
       
        ax = (TextView)findViewById(R.id.acc_x);
        ay = (TextView)findViewById(R.id.acc_y);
        az = (TextView)findViewById(R.id.acc_z);
        ox = (TextView)findViewById(R.id.ori_x);
        oy = (TextView)findViewById(R.id.ori_y);
        oz = (TextView)findViewById(R.id.ori_z);
    }
   
    @Override
    public void onResume() {
        super.onResume();
       
        sm.registerListener(sl, SensorManager.SENSOR_ACCELEROMETER | SensorManager.SENSOR_ORIENTATION,
                SensorManager.SENSOR_DELAY_NORMAL);
    }
   
    @Override
    public void onPause() {
        super.onPause();
       
        sm.unregisterListener(sl);
    }
   
    private class SL implements SensorListener {
        public void onSensorChanged(int sensor, float[] values) {
            if (sensor == SensorManager.SENSOR_ACCELEROMETER) {
                ax.setText(Float.toString(values[0]));
                ay.setText(Float.toString(values[1]));
                az.setText(Float.toString(values[2]));
            } else if (sensor == SensorManager.SENSOR_ORIENTATION) {
                ox.setText(Float.toString(values[0]));
                oy.setText(Float.toString(values[1]));
                oz.setText(Float.toString(values[2]));
            }
        }
       
        public void onAccuracyChanged(int sensor, int accuracy) {
        }
    }

}





댓글 1개:

  1. 질문입니다



    Sensor_Orientaiton값으로 SeekBar를 조정 하려 합니다.



    소스는

    public void onSensorChanged(int sensor, float[] values) {

    seekVol.setProgress((int) values[1]);

    }

    이렇게 했는데..



    센서움직임에 따라서 seek값이 변하기는 합니다



    문제는... 센서로 70이란 값으로 설정해 놓고





    터치로 그 값을 변경하면....Seek가 움직이기는 하나



    터치를 놓는 순간 다시 센서값을 읽어어서 70으로 설정되는데..



    왜 그런지 모르겠습니다.onSensorChanged() 메소드는 센서값이



    변화가 았을때만 호출되는게 아닌가요?

    답글삭제