
이미지뷰의 속성 중
adjustViewBounds의 값을 true로 해주면 화면 꽉차게 채울 수 있다.
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
app:srcCompat="@mipmap/ic_launcher" />


AndroidManifest.xml에 권한 추가
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS"/>
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
val permissionList = arrayOf(
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.READ_SMS,
Manifest.permission.READ_PHONE_NUMBERS,
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
requestPermissions(permissionList,0)
// 전화 관련된 정보를 관리하는 객체를 추출한다.
val telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager
// 권한 확인이 필요한 일부 코드들은 권한 허용 여부를 검사해줘야 하는 것들이 있다.
// checkSelfPermission : 두 번째 매개변수에 넣어준 권한이 허용되어 있는지
// PERMISSION_GRANTED : 허용된 권한
// PERMISSION_DENIED : 거부된 권한
val a1 = ActivityCompat.checkSelfPermission(this@MainActivity, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED
val a2 = ActivityCompat.checkSelfPermission(this@MainActivity, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED
val a3 = ActivityCompat.checkSelfPermission(this@MainActivity, Manifest.permission.READ_PHONE_NUMBERS) == PackageManager.PERMISSION_GRANTED
// 권한이 모두 허용되어 있다면
if(a1 && a2 && a3){
activityMainBinding.apply {
textView.apply {
text = "전화번호 : ${telephonyManager.line1Number}\n"
append("SIM 국가 코드 : ${telephonyManager.simCountryIso}\n")
append("모바일 국가 코드 + 모바일 네트워크 코드 : ${telephonyManager.simOperator}\n") // 통신사에 따라 가능한 기능을 구현할때 체크
append("서비스 이름 : ${telephonyManager.simOperatorName}\n")
append("SIM 상태 (통신 가능 여부, Pin Lock 여부 등) : ${telephonyManager.simState}\n")
append("음성 메일 번호 : ${telephonyManager.voiceMailNumber}\n")
}
}
}
}
}



음성 메일 번호는 우리나라에는 없다
// 권한이 모두 허용되어 있다면
if(a1 && a2 && a3){
activityMainBinding.apply {
textView.apply {
text = "전화번호 : ${telephonyManager.line1Number}\n"
append("SIM 국가 코드 : ${telephonyManager.simCountryIso}\n")
append("모바일 국가 코드 + 모바일 네트워크 코드 : ${telephonyManager.simOperator}\n") // 통신사에 따라 가능한 기능을 구현할때 체크
append("서비스 이름 : ${telephonyManager.simOperatorName}\n")
append("SIM 상태 (통신 가능 여부, Pin Lock 여부 등) : ${telephonyManager.simState}\n")
append("음성 메일 번호 : ${telephonyManager.voiceMailNumber}\n")
append("보드 이름 : ${Build.BOARD}\n")
append("소프트웨어를 커스터마이징한 회사 : ${Build.BRAND}\n")
append("제조사 디자인 명 : ${Build.DEVICE}\n")
append("사용자에게 표시되는 빌드 ID : ${Build.DISPLAY}\n")
append("빌드 고유 ID : ${Build.FINGERPRINT}\n")
append("ChangeList 번호 : ${Build.ID}\n")
append("제품/하드웨어 제조업체 : ${Build.MANUFACTURER}\n")
append("제품 모델명 : ${Build.MODEL}\n")
append("제품명 : ${Build.PRODUCT}\n")
append("빌드 구분 : ${Build.TAGS}\n")
append("빌드 타입 : ${Build.TYPE}\n")
append("안드로이드 버전 : ${Build.VERSION.RELEASE}\n")
append("안드로이드 버전 코드네임 : ${Build.VERSION.CODENAME}\n")
append("안드로이드 API 레벨 : ${Build.VERSION.SDK_INT}\n")
}
}
}

// 화면에 관련된 정보를 가지고 있는 객체를 추출한다.
val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
// 안드로이드 11 이상 여부로 분기한다.
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
// 단말기 해상도의 가로길이를 가져온다.
val w = windowManager.currentWindowMetrics.bounds.width()
// 단말기 해상도의 세로길이를 가져온다.
val h = windowManager.currentWindowMetrics.bounds.height()
textView.append("가로길이 : ${w}\n")
textView.append("세로길이 : ${w}\n")
} else {
// 해상도 정보를 담을 객체를 추출한다.
val point = Point()
// 해상도 정보를 담는다.
windowManager.defaultDisplay.getSize(point)
textView.append("가로길이 : ${point.x}\n")
textView.append("세로길이 : ${point.y}\n")
}

class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
activityMainBinding.apply {
textView.apply {
// 센서를 관리하는 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 단말기에 있는 센서 목록을 가져온다.
val sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL)
text = ""
sensorList.forEach {
append("센서 이름 : ${it.name}\n")
append("센서 제조사 : ${it.vendor}\n")
append("센서 종류 : ${it.type}\n\n")
}
}
}
}
}

센서 당 받아올 수 있는 최대 값이 3개임(자이로 스코프 센서는 x,y,z축 값)
에뮬레이터 창의 메뉴 중 ... 버튼 선택하면 디바이스의 센서를 확인할 수 있다.


class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
// 조도 센서의 리스너를 담을 프로퍼티
var lightSensorListener:LightSensorListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
activityMainBinding.apply {
button.setOnClickListener {
// 리스너 연결이 되어 있지 않을 경우
if(lightSensorListener == null){
button.text = "조도 센서 해제"
// 리스너 객체를 생성
lightSensorListener = LightSensorListener()
// 센서들을 관리하는 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 조도 센서 객체를 가져온다.
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)
// 조도 센서와 리스너를 연결한다.
// 첫 번째 : 리스너
// 두 번째 : 연결할 센서 객체
// 세 번째 : 데이터를 받아올 주기
// 반환값 : 센서 연결에 성공했는지 여부
val chk = sensorManager.registerListener(lightSensorListener, sensor, SensorManager.SENSOR_DELAY_UI)
// 센서 연결에 실패했다면
if(chk==false){
lightSensorListener = null
textView.text = "조도 센서를 지원하지 않습니다."
}
}
// 리스너가 연결되어 있을 경우
else {
button.text = "조도 센서 연결"
// 센서들을 관리하는 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 조도 센서의 리스너를 해제한다.
sensorManager.unregisterListener(lightSensorListener)
lightSensorListener = null
}
}
}
}
// 조도 센서의 리스너
inner class LightSensorListener : SensorEventListener{
// 센서에 변화가 일어날 때 호출되는 메서드
// 이 메서드에서 측정된 값을 가져올 수 있다.
override fun onSensorChanged(event: SensorEvent?) {
if(event != null) {
// 조도 값을 가지고 온다.
val a1 = event.values[0]
activityMainBinding.textView.text = "주변 밝기 : $a1 lux"
}
}
// 센서의 감도가 변경되었을 때 호출되는 메서드
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
}
}
}


조도 센서를 조작하면 텍스트뷰값도 같이 바뀌는걸 확인할 수 있다.
실제 단말기에서 테스트를 할때에는 단말기 상단을 가려주면 된다.
class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
// 기압 센서의 리스너를 담을 프로퍼티
var pressureSensorListener:PressureSensorListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
activityMainBinding.apply {
button2.setOnClickListener {
// 리스너 연결이 되어 있지 않을 경우
if(pressureSensorListener == null){
button2.text = "기압 센서 해제"
// 리스너 객체를 생성
pressureSensorListener = PressureSensorListener()
// 센서들을 관리하는 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 기압 센서 객체를 가져온다.
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE)
// 기압 센서와 리스너를 연결한다.
// 첫 번째 : 리스너
// 두 번째 : 연결할 센서 객체
// 세 번째 : 데이터를 받아올 주기
// 반환값 : 센서 연결에 성공했는지 여부
val chk = sensorManager.registerListener(pressureSensorListener, sensor, SensorManager.SENSOR_DELAY_UI)
// 센서 연결에 실패했다면
if(chk==false){
pressureSensorListener = null
textView.text = "기압 센서를 지원하지 않습니다."
}
}
// 리스너가 연결되어 있을 경우
else {
button2.text = "기압 센서 연결"
// 센서들을 관리하는 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 기압 센서의 리스너를 해제한다.
sensorManager.unregisterListener(pressureSensorListener)
pressureSensorListener = null
}
}
}
}
// 공기압 센서의 리스너
inner class PressureSensorListener : SensorEventListener {
// 센서에 변화가 일어날 때 호출되는 메서드
// 이 메서드에서 측정된 값을 가져올 수 있다.
override fun onSensorChanged(event: SensorEvent?) {
if(event != null) {
// 공기압 값을 가지고 온다.
val a1 = event.values[0]
activityMainBinding.textView.text = "현재 기압 : $a1 millibar"
}
}
// 센서의 감도가 변경되었을 때 호출되는 메서드
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
}
}
}


class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
// 근접 센서의 리스너를 담을 프로퍼티
var proximitySensorListener:ProximitySensorListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
activityMainBinding.apply {
button3.setOnClickListener {
// 리스너 연결이 되어 있지 않을 경우
if(proximitySensorListener == null){
button3.text = "근접 센서 해제"
// 리스너 객체를 생성
proximitySensorListener = ProximitySensorListener()
// 센서들을 관리하는 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 근접 센서 객체를 가져온다.
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)
// 근접 센서와 리스너를 연결한다.
// 첫 번째 : 리스너
// 두 번째 : 연결할 센서 객체
// 세 번째 : 데이터를 받아올 주기
// 반환값 : 센서 연결에 성공했는지 여부
val chk = sensorManager.registerListener(proximitySensorListener, sensor, SensorManager.SENSOR_DELAY_UI)
// 센서 연결에 실패했다면
if(chk==false){
proximitySensorListener = null
textView.text = "근접 센서를 지원하지 않습니다."
}
}
// 리스너가 연결되어 있을 경우
else {
button3.text = "근접 센서 연결"
// 센서들을 관리하는 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 근접 센서의 리스너를 해제한다.
sensorManager.unregisterListener(proximitySensorListener)
proximitySensorListener = null
}
}
}
}
// 근접 센서의 리스너
inner class ProximitySensorListener : SensorEventListener {
// 센서에 변화가 일어날 때 호출되는 메서드
// 이 메서드에서 측정된 값을 가져올 수 있다.
override fun onSensorChanged(event: SensorEvent?) {
if(event != null) {
// 물체와의 거리를 가지고 온다.
val a1 = event.values[0]
activityMainBinding.textView.text = "물체와의 거리 : $a1 cm"
}
}
// 센서의 감도가 변경되었을 때 호출되는 메서드
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
}
}
}


class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
// 자이로 스코프 센서의 리스너를 담을 프로퍼티
var gyroscopeSensorListener:GyroscopeSensorListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
activityMainBinding.apply {
button4.setOnClickListener {
// 리스너 연결이 되어 있지 않을 경우
if(gyroscopeSensorListener == null){
button4.text = "자이로 스코프 센서 해제"
// 리스너 객체를 생성
gyroscopeSensorListener = GyroscopeSensorListener()
// 센서들을 관리하는 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 자이로 스코프 센서 객체를 가져온다.
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
// 자이로 스코프 센서와 리스너를 연결한다.
// 첫 번째 : 리스너
// 두 번째 : 연결할 센서 객체
// 세 번째 : 데이터를 받아올 주기
// 반환값 : 센서 연결에 성공했는지 여부
val chk = sensorManager.registerListener(gyroscopeSensorListener, sensor, SensorManager.SENSOR_DELAY_UI)
// 센서 연결에 실패했다면
if(chk==false){
gyroscopeSensorListener = null
textView.text = "자이로 스코프 센서를 지원하지 않습니다."
}
}
// 리스너가 연결되어 있을 경우
else {
button4.text = "자이로 스코프 센서 연결"
// 센서들을 관리하는 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 자이로 스코프 센서의 리스너를 해제한다.
sensorManager.unregisterListener(gyroscopeSensorListener)
gyroscopeSensorListener = null
}
}
}
}
// 자이로 스코프 센서의 리스너
inner class GyroscopeSensorListener : SensorEventListener{
// 센서에 변화가 일어날 때..
// 이 메서드에서 측정된 값을 가져올 수 있다
override fun onSensorChanged(event: SensorEvent?) {
if(event != null) {
// X 축의 각속도
val a1 = event.values[0]
// Y 축의 각속도
val a2 = event.values[1]
// Z 축의 각속도
val a3 = event.values[2]
activityMainBinding.textView.text = "X 축의 각속도 : $a1"
activityMainBinding.textView2.text = "Y 축의 각속도 : $a2"
activityMainBinding.textView3.text = "Z 축의 각속도 : $a3"
}
}
// 센서의 감도가 변경되었을 때...
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
}
}
}

Z-Rot, X-Rot, Y-Rot 값을 조정할 수 있다.

자이로 스코프는 얼마나 기울여졌냐가 아니라 얼마나 빠르게 움직여졌는지를 측정한다.
천천히 움직일때와 빠르게 움직일때의 측정값이 다르다.
움직인 후에는 값이 0으로 돌아온다.
class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
// 가속도 센서의 리스너를 담을 프로퍼티
var accelerometerSensorListener:AccelerometerSensorListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
activityMainBinding.apply {
button5.setOnClickListener {
// 리스너 연결이 되어 있지 않을 경우
if(accelerometerSensorListener == null){
button5.text = "가속도 센서 해제"
// 리스너 객체를 생성
accelerometerSensorListener = AccelerometerSensorListener()
// 센서들을 관리하는 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 가속도 센서 객체를 가져온다.
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
// 가속도 센서와 리스너를 연결한다.
// 첫 번째 : 리스너
// 두 번째 : 연결할 센서 객체
// 세 번째 : 데이터를 받아올 주기
// 반환값 : 센서 연결에 성공했는지 여부
val chk = sensorManager.registerListener(accelerometerSensorListener, sensor, SensorManager.SENSOR_DELAY_UI)
// 센서 연결에 실패했다면
if(chk==false){
accelerometerSensorListener = null
textView.text = "가속도 센서를 지원하지 않습니다."
}
}
// 리스너가 연결되어 있을 경우
else {
button5.text = "가속도 센서 연결"
// 센서들을 관리하는 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 가속도 센서의 리스너를 해제한다.
sensorManager.unregisterListener(accelerometerSensorListener)
accelerometerSensorListener = null
}
}
}
}
// 가속도 센서의 리스너
inner class AccelerometerSensorListener : SensorEventListener{
// 센서에 변화가 일어날 때..
// 이 메서드에서 측정된 값을 가져올 수 있다
override fun onSensorChanged(event: SensorEvent?) {
if(event != null) {
// X 축의 기울기
val a1 = event.values[0]
// Y 축의 기울기
val a2 = event.values[1]
// Z 축의 기울기
val a3 = event.values[2]
activityMainBinding.textView.text = "X 축의 기울기 : $a1"
activityMainBinding.textView2.text = "Y 축의 기울기 : $a2"
activityMainBinding.textView3.text = "Z 축의 기울기 : $a3"
}
}
// 센서의 감도가 변경되었을 때...
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
}
}
}

빠르기(자이로 스코프)와 상관없이 기울기에따라 값이 변한다.
class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
// 마그네틱 센서의 리스너를 담을 프로퍼티
var magneticSensorListener:MagneticSensorListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
activityMainBinding.apply {
button6.setOnClickListener {
// 리스너 연결이 되어 있지 않을 경우
if(magneticSensorListener == null){
button6.text = "마그네틱 센서 해제"
// 리스너 객체를 생성
magneticSensorListener = MagneticSensorListener()
// 센서들을 관리하는 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 마그네틱 센서 객체를 가져온다.
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)
// 마그네틱 센서와 리스너를 연결한다.
// 첫 번째 : 리스너
// 두 번째 : 연결할 센서 객체
// 세 번째 : 데이터를 받아올 주기
// 반환값 : 센서 연결에 성공했는지 여부
val chk = sensorManager.registerListener(magneticSensorListener, sensor, SensorManager.SENSOR_DELAY_UI)
// 센서 연결에 실패했다면
if(chk==false){
magneticSensorListener = null
textView.text = "마그네틱 센서를 지원하지 않습니다."
}
}
// 리스너가 연결되어 있을 경우
else {
button6.text = "마그네틱 센서 연결"
// 센서들을 관리하는 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 마그네틱 센서의 리스너를 해제한다.
sensorManager.unregisterListener(magneticSensorListener)
magneticSensorListener = null
}
}
}
}
// 마그네틱 센서의 리스너
inner class MagneticSensorListener : SensorEventListener{
// 센서에 변화가 일어날 때..
// 이 메서드에서 측정된 값을 가져올 수 있다
override fun onSensorChanged(event: SensorEvent?) {
if(event != null) {
// X 축 주변 자기장
val a1 = event.values[0]
// Y 축 주변 자기장
val a2 = event.values[1]
// Z 축 주변 자기장
val a3 = event.values[2]
activityMainBinding.textView.text = "X 축의 주변 자기장 : $a1"
activityMainBinding.textView2.text = "Y 축의 주변 자기장 : $a2"
activityMainBinding.textView3.text = "Z 축의 주변 자기장 : $a3"
}
}
// 센서의 감도가 변경되었을 때...
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
}
}
}


// 가속도 센서로 측정한 값을 담을 배열을 담을 프로퍼티
val accValues = floatArrayOf(0.0f, 0.0f, 0.0f)
// 자기장 센서로 측정한 값을 담을 배열을 담을 프로퍼티
val magValues = floatArrayOf(0.0f, 0.0f, 0.0f)
// 센서로부터 값이 측정된 적이 있는지
var isGetAcc = false
var isGetMag = false
// 가속도 센서의 리스너
inner class AccelerometerSensorListener : SensorEventListener{
override fun onSensorChanged(event: SensorEvent?) {
if(event != null){
// 측정된 값이 담긴 배열을 담아준다.
accValues[0] = event.values[0]
accValues[1] = event.values[1]
accValues[2] = event.values[2]
isGetAcc = true
}
}
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {
TODO("Not yet implemented")
}
}
// 자기장 센서의 리스너
inner class MagneticSensorListener : SensorEventListener{
override fun onSensorChanged(event: SensorEvent?) {
if(event != null){
// 측정된 값이 담긴 배열을 담아준다.
magValues[0] = event.values[0]
magValues[1] = event.values[1]
magValues[2] = event.values[2]
isGetMag = true
}
}
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {
TODO("Not yet implemented")
}
}
이전에는 방위값을 계산하는 가이드만 알려주었지만 지금은 메서드도 제공하고 있다.
// 방위값을 계산하는 메서드
fun getAzimuth(){
// 두 센서 모두 값이 측정된 적이 있을 경우에만
if(isGetAcc && isGetMag){
// 방위값 등을 계싼하기 위한 계산 행렬
val R = FloatArray(9)
val I = FloatArray(9)
// 계산 행렬을 구한다.
SensorManager.getRotationMatrix(R, I, accValues, magValues)
// 방위값을 추출한다.
val values = FloatArray(3)
SensorManager.getOrientation(R, values)
// 결과가 라디언 값으로 나오기 때문에 각도 값으로 변환한다.
var azimuth = Math.toDegrees(values[0].toDouble()) // 방위
var pitch = Math.toDegrees(values[1].toDouble()) // 좌우 기울기 값
var roll = Math.toDegrees(values[2].toDouble()) // 앞뒤 기울기 값
// 만약 방위값이 음수가 나온다면 360을 더해준다.
if(azimuth<0){
azimuth += 360
}
activityMainBinding.apply {
textView.text = "방위값 : $azimuth"
textView2.text = "좌우 기울기 값 : $pitch"
textView3.text = "앞뒤 기울기 값 : $roll"
// 이미지 뷰 회전
imageView.rotation = (360 - azimuth).toFloat()
}
}
}
// 가속도 센서의 리스너
inner class AccelerometerSensorListener : SensorEventListener{
override fun onSensorChanged(event: SensorEvent?) {
if(event != null){
// 측정된 값이 담긴 배열을 담아준다.
accValues[0] = event.values[0]
accValues[1] = event.values[1]
accValues[2] = event.values[2]
isGetAcc = true
getAzimuth()
}
}
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {
}
}
// 자기장 센서의 리스너
inner class MagneticSensorListener : SensorEventListener{
override fun onSensorChanged(event: SensorEvent?) {
if(event != null){
// 측정된 값이 담긴 배열을 담아준다.
magValues[0] = event.values[0]
magValues[1] = event.values[1]
magValues[2] = event.values[2]
isGetMag = true
getAzimuth()
}
}
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {
}
}
// 각 센서들의 리스너
var accelerometerSensorListener:AccelerometerSensorListener? = null
var magneticSensorListener:MagneticSensorListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
activityMainBinding.apply {
button.setOnClickListener {
if(accelerometerSensorListener == null && magneticSensorListener == null){
// 센서 관리 객체를 추출한다.
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 센서 객체를 가져온다.
val accSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
val magSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)
// 리스너 생성
accelerometerSensorListener = AccelerometerSensorListener()
magneticSensorListener = MagneticSensorListener()
// 센서에 리스너를 연결한다.
sensorManager.registerListener(accelerometerSensorListener, accSensor, SensorManager.SENSOR_DELAY_UI)
sensorManager.registerListener(magneticSensorListener, magSensor, SensorManager.SENSOR_DELAY_UI)
}
}
button2.setOnClickListener {
if(accelerometerSensorListener != null && magneticSensorListener != null){
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
// 센서 리스너를 해제한다.
sensorManager.unregisterListener(accelerometerSensorListener)
sensorManager.unregisterListener(magneticSensorListener)
accelerometerSensorListener = null
magneticSensorListener = null
}
}
}
}

※ 출처 : 멋쟁이사자 앱스쿨 2기, 소프트캠퍼스