일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 키스토어
- #리사이클러뷰
- 빗버킷 #bitbucket #authorization failed #깃
- #안드로이드
- retrofit2
- #리사이클러뷰 어댑터
- 안드로이드 익명클래스
- 메모리릭
- retrofi
- #android #안드로이드 #glide #gif #이미지다운로드
- 안드로이드
- 안드로이드 메모리릭
- #안드로이드 개발자 #안드로이드 신입 #개발자 이직 #안드로이드 면접 #신입 개발자
- 구글맵안돼요
- #ContentProvider #App DataShare
- zeplin
- #SMS API #안드로이드 SMS #SMS Retriever
- retrofit
- 레트로핏
- MVVM
- 제플린
- 리사이클러뷰 체크박스
- 클린아키텍쳐
- 사용법
- 안드로이드 아키텍쳐
- 안드로이드해상도
- Today
- Total
땀이 삐질삐질 나는 개발 일기
안드로이드 Service Binding과 StepCount 만보기 본문
안녕하세요. 삐질삐질 개발하는 개발자 삐질입니다.
오늘은 서비스와 만보계 센서를 이용해 바인딩하는 과정을 알아보도록 하겠습니다.
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private StepService stepService; // 서비스 클래스 객체를 선언
boolean isService = false; // 서비스 중인 확인용
private TextView textCount, statusService;
private Button startBtn, endBtn;
private Intent intent; //서비스 객체를 가지고 있는 인텐트 객체
private StepCallback stepCallback = new StepCallback() { //서비스 내부로 Set되어 스텝카운트의 변화와 Unbind의 결과를 전달하는 콜백 객체의 구현체
@Override
public void onStepCallback(int step) {
textCount.setText("" + step);
}
@Override
public void onUnbindService() {
isService = false;
statusService.setText("해제됨");
Toast.makeText(MainActivity.this, "디스바인딩", Toast.LENGTH_SHORT).show();
}
};
private ServiceConnection serviceConnection = new ServiceConnection() { //서비스 바인드를 담당하는 객체의 구현체
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Toast.makeText(MainActivity.this, "예스바인딩", Toast.LENGTH_SHORT).show();
StepService.MyBinder mb = (StepService.MyBinder) service;
stepService = mb.getService(); //
stepService.setCallback(stepCallback);
isService = true;
statusService.setText("연결됨");
}
@Override
public void onServiceDisconnected(ComponentName name) { //요거는 사실상 서비스가 킬되거나 아예 죽임 당했을 때만 호출된다고 보시면 됨// stopService 또는 unBindService때 호출되지 않음.
isService = false;
statusService.setText("해제됨");
Toast.makeText(MainActivity.this, "디스바인딩", Toast.LENGTH_SHORT).show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
stepService = new StepService();
startBtn = findViewById(R.id.startBtn);
endBtn = findViewById(R.id.endBtn);
textCount = findViewById(R.id.textCount);
statusService = findViewById(R.id.textStatusService);
setListener();
}
public void setListener() {
startBtn.setOnClickListener(this);
endBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.startBtn:
intent = new Intent(this, StepService.class);
startService(intent);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
break;
case R.id.endBtn:
try {
stopService(intent);
unbindService(serviceConnection);
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
@Override
protected void onStop() {//액티비티를 벗어났을 땐 서비스와 액티비티의 바인드를 끊어줌 : 백그라운드에서 UI를 건들지 않게 하기 위함
super.onStop();
unbindService(serviceConnection);
}
}
-
StepCallback.Java
public interface StepCallback {
void onStepCallback(int step); //서비스에서 스텝 변화 시 액티비티로 전달하는 콜백 함수
void onUnbindService(); // 서비스 언바인드 시 액티비티로 전달하는 콜백 함수
}
StepService.Java
public class StepService extends Service implements SensorEventListener {
private MyBinder mMyBinder = new MyBinder();
class MyBinder extends Binder { //바인드 클래스를 생성
StepService getService() { // 서비스 객체를 리턴
return StepService.this;
}
}
private int mStepDetector;
private StepCallback callback;
public void setCallback(StepCallback callback) {
this.callback = callback;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mMyBinder;
}
private SensorManager sensorManager;
private Sensor stepDetectorSensor;
private Sensor stepCountSensor;
@Override
public void onCreate() {
super.onCreate();
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
stepDetectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
if (stepDetectorSensor == null) {
} else {
sensorManager.registerListener(this, stepCountSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
// COUNTER
stepCountSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
if (stepCountSensor == null) {
} else {
sensorManager.registerListener(this, stepDetectorSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
stepDetectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
if (stepDetectorSensor == null) {
} else {
sensorManager.registerListener(this, stepCountSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
// COUNTER
stepCountSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
if (stepCountSensor == null) {
} else {
sensorManager.registerListener(this, stepDetectorSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean onUnbind(Intent intent) {
unRegistManager();
if (callback != null)
callback.onUnbindService();
return super.onUnbind(intent);
}
public void unRegistManager() { //혹시 모를 에러상황에 트라이 캐치
try {
sensorManager.unregisterListener(this);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_STEP_DETECTOR) {
if (event.values[0] == 1.0f) {
mStepDetector += event.values[0];
if (callback != null)
callback.onStepCallback(mStepDetector);
Log.e("스텝 디텍터", "" + event.values[0]);
}
} else if (event.sensor.getType() == Sensor.TYPE_STEP_COUNTER) {
Log.e("스텝 카운트", "" + event.values[0]);
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/textStatusService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="서비스상태" />
<Button
android:id="@+id/startBtn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="시작" />
<Button
android:id="@+id/endBtn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="스탑" />
<TextView
android:id="@+id/textCount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="스텝카운트" />
</LinearLayout>
설명이 필요하다면 단톡방으로 고고씽!
----2020.5/29 추가내용 -----------
-안드로이드 10 (Target SDK 29 )가 빌드업 되면서 센서를 사용하려면 권한을 인가 받아야 합니다.
- 권한을 인가 받는 쉬운 방법으로는 : TedPermission Or 직접 리퀘스트 코드
- TedP는 검색해보시면 라이브러리 Github공홈이 사용법에 더 자세히 나와있으니 참고해주시고
- 직접 작성한다면 아래와 같은 양식으로 작성할 수 있습니다.
- 예시를 위해 권한을 요청하고 onRequestPermissionsResult 에서 권한 거절 / 승인 분기하지 않고 무조건 승인받은 것을 전제로 깔았으니, 실제 코딩할 땐 권한이 거절되었을때 분기 처리도 하셔야 합니다.
- 아래는 예시 입니다.
순서대로
1. Member Variables Field
2. Activity or Fragment 일때는 onCreate() / Service일때는 onCreate / OnstartCommand() 양쪽 내부에 넣어주는 것이 좋습니다.
3. onRequestPermissionsResult
4. Manifest.xml
lateinit var sensorManager :SensorManager
lateinit var sensor:Sensor
if(ContextCompat.checkSelfPermission(this,
Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_DENIED){
//ask for permission
requestPermissions(arrayOf(Manifest.permission.ACTIVITY_RECOGNITION), 0);
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
sensorManager.registerListener(this,sensor,Sensor.TYPE_STEP_COUNTER)
}
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
'개발 Tip' 카테고리의 다른 글
Recyclerview의 아이템 클릭을 CallbackListener를 통해 Activity까지 가져오기 (0) | 2019.07.08 |
---|---|
리사이클러뷰 아이템 액티비티로 전달하기 (0) | 2019.07.06 |
Utils Log 클래스로 간편하게 Log처리하기 (0) | 2019.06.30 |
안드로이드 Zeplin Resolution 팁 알아보기 (0) | 2019.06.22 |
BuildConfig 이용해서 Debug와 Release 모드의 같은 변수 다른 값 사용하기 (0) | 2019.06.14 |