[ 이번 단원 핵심 포인트 ]
# 가속도 센서 사용방법
- 센서 관리자 구하기
ex) SensorManager mSensorMgr = (SensorManager)getSystemService(Context.SENSOR_SERVICE );
- 가속도 센서 지정하기
ex) mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- SensorEventListener sensorListener : 센서 이벤트 리스너
- onSensorChanged(SensorEvent event) : 센서 이벤트 함수
(1) 새로운 소스 프로젝트를 생성하고 이름을 MagicBall 라고 지정합니다. 소스 프로젝트를 생성하는 방법은 먼저번 시간에 했던것과 동일합니다.
소스 프로젝트가 생성되면 이미지 파일을 소스 프로젝트로 복사하겠습니다. [ 부록 /Sample Image ] 폴더에서 아래 5개 파일을 [ 소스 프로젝트 /res /drawable ] 폴더로 복사합니다.
- btn_orange_n.png / magic_ball1.png / magic_ball2.png / magic_ball3.png / magic_ball4.png
(2) 레이아웃 정보파일에 (/res/layout/activity_main.xml) 1개의 ImageView 와 1개의 Button 위젯을 추가해 보겠습니다. 레이아웃 파일에 아래와 같이 코드를 추가합니다.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#777">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:layout_centerHorizontal="true"
android:textColor="#fff"
android:textSize="25sp"
android:text="Ask me anything!" />
<ImageView
android:id="@+id/imageBall"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:scaleType="fitCenter"
android:src="@drawable/magic_ball1"/>
<Button
android:layout_width="160dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:onClick="onClick"
android:background="@drawable/btn_orange_n"
android:textColor="#fff"
android:text="Shake Me~~"/>
</RelativeLayout>
- TextView 를 화면 위쪽 중앙에 생성하였습니다.
- ImageView 를 화면 정중앙에 생성하였습니다.
- Button 을 화면 아래쪽 중앙에 생성하였습니다.
(1) 위젯 변수 초기화
ImageView 위젯 변수를 생성하겠습니다. 자바 소스파일 (MainActivity.java) 로 이동해서 아래와 같이 멤버변수를 추가합니다. 그리고 onCreate() 함수에서 초기화 해줍니다.
public class MainActivity extends AppCompatActivity {
ImageView imageBall;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageBall = findViewById(R.id.imageBall);
}
(2) 랜덤으로 볼 이미지 변경
Button 을 누르면 랜덤으로 볼 이미지가 변경되는 기능을 구현해 보겠습니다. 소스 파일에 아래와 같이 2개의 함수를 생성합니다.
void onClick(View v) {
int[] imageId = {R.drawable.magic_ball1, R.drawable.magic_ball2
, R.drawable.magic_ball3, R.drawable.magic_ball4};
int rand = getRandom(4, 0);
imageBall.setImageResource( imageId[rand] );
}
int getRandom(int range, int min) {
return (int)(Math.random() * range) + min;
}
- onClick() : Button 클릭 이벤트 함수.
아래는 4개의 볼 이미지 ID 를 정수형 배열에 저장하는 코드 입니다.
int[] imageId = {R.drawable.magic_ball1, R.drawable.magic_ball2
, R.drawable.magic_ball3, R.drawable.magic_ball4};
아래는 난수에 해당하는 이미지를 ImageView 에 표시하는 코드 입니다.
imageBall.setImageResource( imageId[rand] );
- getRandom() : 난수를 생성하는 함수.
예제를 실행하고 Button 을 누르면 매직 볼 이미지가 변경됩니다.
(1) 가속도 센서
핸드폰을 흔들면 매직 볼 이미지가 변경되는 기능을 구현해 보겠습니다. 아래와 같이 새로운 멤버변수를 생성하고, onCreate() 함수에서 초기화 해줍니다.
public class MainActivity extends AppCompatActivity {
ImageView imageBall;
SensorManager mSensorMgr = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageBall = findViewById(R.id.imageBall);
mSensorMgr = (SensorManager)getSystemService(Context.SENSOR_SERVICE );
Sensor sensorAcceler =
mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if( sensorAcceler != null )
mSensorMgr.registerListener(sensorListener, sensorAcceler,
SensorManager.SENSOR_DELAY_UI);
}
- SensorManager : 모든 센서를 관리하는 클래스. 이미 생성되어 있기 때문에 getsystemService() 함수로 가져오면 됩니다.
- SensorManager.getDefaultSensor() : 특정 센서 객체를 반환하는 함수. TYPE_ACCELEROMETER 를 파라미터로 전달하면 가속도 센서가 반환됩니다. null 이 반환되면 핸드폰에 가속도 센서가 없다는 의미입니다.
- SensorManager.registerListener() : 센서 이벤트를 수신하는 리스너를 지정하는 함수. 리스너 객체는 지금부터 만들어 보겠습니다.
소스파일 내부에 아래와 같이 새로운 코드를 입력합니다. 센서 이벤트를 수신하는 리스너 객체를 생성하고 이벤트 함수를 정의하는 코드입니다.
SensorEventListener sensorListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float v[] = event.values;
double sum = Math.abs(v[0]) + Math.abs(v[1]) + Math.abs(v[2]);
if( sum > 30 ) {
onClick(null);
}
}
}
};
- SensorEventListener : 센서 이벤트를 수신하는 리스너. 리스너를 정의할 때는 가상 함수를 모두 생성해 주어야 합니다.
- onAccuracyChanged() : 센서 정확도가 변경될 때 실행되는 이벤트 함수. 이번 예제에서는 사용하지 않지만 헤더부분은 만들어 주어야 합니다.
- onSendorChanged() : 센서 값이 변경될 때 실행되는 이벤트 함수.
- SensorEvent : 센서 값을 저장하는 클래스.
- SensorEvent.sensor.getType() : 센서의 종류를 반환하는 함수. TYPE_ACCELEROMETER 이면 가속도 센서를 의미합니다.
- SensorEvent.values : X축, Y축, Z축 센서 값이 저장된 배열.
- Math.abs() : 음수를 양수로 변경해서 절대값을 반환하는 수학 함수.
아래는 X축, Y축, Z축 가속도 값의 합계를 구하는 코드입니다. 중력이 존재하기 때문에 항상 기본값은 9.8 입니다. 약하게 흔들때의 가속도 합계는 20, 강하게 흔들때의 가속도 합계는 30 정도입니다. 사용자가 폰을 흔들면 버튼 클릭 이벤트 함수를 실행합니다.
double sum = Math.abs(v[0]) + Math.abs(v[1]) + Math.abs(v[2]);
if( sum > 30 ) {
onClick(null);
}
예제를 핸드폰에 설치하고, 폰을 흔들어 봅시다. Button 을 누르지 않아도 매직 볼 이미지가 변경됩니다.
매직 볼 예제가 완성되었습니다. 전체 소스코드는 다음과 같습니다.
public class MainActivity extends AppCompatActivity {
ImageView imageBall;
SensorManager mSensorMgr = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageBall = findViewById(R.id.imageBall);
mSensorMgr = (SensorManager)getSystemService( Context.SENSOR_SERVICE );
Sensor sensorAcceler = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if( sensorAcceler != null )
mSensorMgr.registerListener(sensorListener, sensorAcceler,
SensorManager.SENSOR_DELAY_UI);
}
SensorEventListener sensorListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float v[] = event.values;
double sum = Math.abs(v[0]) + Math.abs(v[1]) + Math.abs(v[2]);
if( sum > 30 ) {
onClick(null);
}
}
}
};
void onClick(View v) {
int[] imageId = {R.drawable.magic_ball1
, R.drawable.magic_ball2
, R.drawable.magic_ball3
, R.drawable.magic_ball4};
int rand = getRandom(4, 0);
imageBall.setImageResource( imageId[rand] );
}
int getRandom(int range, int min) {
return (int)(Math.random() * range) + min;
}
}
[연습문제] 매직 볼 확률 변경
매직 볼 예제에서 답변의 확률을 변경해 봅시다. 세게 흔들면 2번 중에서 1번 ‘YES’ 가 나오고, 약하게 흔들면 2번 중에서 1번 ‘NO’ 가 나오게 합니다.