google play api는 google play service의 하나의 파트 임.

google fit api는 안드로이드 4.1 이상부터 호환.

Google Fit API 장점

  • 거의 실시간의 히스토리 데이터를 적은 에너지의 블루투스 디바이스로부터 가져옴
  • 활동들을 기록 할 수 있음
  • 데이터를 세션과 연관시킬 수 있음
  • 피트니스 목표를 설정 할 수 있음

sensor data

  • 유저의 하루 활동 관련한 정보들을 앱에서 제공한다면 (예를 들어 하루동안의 걸음수), sensor data는 사용자의 행동을 거의 실시간으로 보여주는데 사용이 가능함.

record data

  • 앱이 꺼져있는 상황에서도 계속해서 데이터를 적재 할 수 있는 subscribe 메서드를 제공함

historical data

  • 만약 유저가 과거의 활동들로부터 피트니스 데이터를 보여주기를 원한다면 history api를 사용하면 됨
  • 데이터 subscribe가 선행 되어야 historical data를 읽을 수 있음 ( 도큐먼트가 친절하지 않아서 테스트 후에 알게 됨), 데이터가 없으면 빈 리스트로 응답이 옴.

session data

  • 개발자가 일정한 시간의 세션을 설정하고 그 설정안에 들어가는 범위의 데이터를 가져올 수 있음

내가 하고자 하는 것

  1. subscribe를 통해 앱 사용자의 활동내역(현재는 걸음 수, 이후에 추가할 예정)들을 클라우드 형태의 google fit store에 앱을 종료했을 때도 마찬가지로 계속해서 저장해야 함.
  2. 데이터가 있는 날부터 일(00시~24시) 기준으로 걸음 수 데이터를 보여줄 수 있어야 함
  3. 배터리 최적화, 잠자기 모드 등 예기치 못한 상황에서도 정상적으로 데이터를 가져와야 함
  4. 데이터는 자정 기준으로 새로 시작함

사전 준비

  1. google fit api 는 Google API Console 에 프로젝트를 등록 및 client ID 를 발급 받은 후 사용해야함.
  2. client ID 발급 후 사용할 library에서 google fit api 를 사용 설정 해야 함.
  3. 테스트를 위해서 OAuth 동의 화면 탭의 테스트 사용자에 테스트를 수행 할 사용자 정보를 등록해야 함.
  4. 모듈 범위의 gradle 에
plugin {
    id("com.android.application")
}

...

dependencies {
        implementation("com.google.android.gms:play-services-fitness:21.1.0")
        implementation("com.google.android.gms:play-services-auth:20.2.0")
}

다음 과 같이 dependency를 추가하여 필요한 라이브러리를 다운로드 함

  1. https://developers.google.com/fit/android/get-started 를 참고하면 더 자세히 setup에 관해 나와 있음

구현 방법

  1. fitness option 객체를 만들어 내가 사용하고자 하는 data들을 추가함
funcreateFitnessStepOptions() : FitnessOptions{
	val fitnessOptions = FitnessOptions.builder()
        .addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
        .addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
        .addDataType(DataType.TYPE_DISTANCE_DELTA, FitnessOptions.ACCESS_READ)
        .addDataType(DataType.AGGREGATE_DISTANCE_DELTA, FitnessOptions.ACCESS_READ)
        .build()
	return fitnessOptions
}

걸음수와 지금까지 걸은 거리에 대한 데이터를 얻기 위해 위처럼 4개의 fitness data type을 추가함.

  1. google account를 가져옴
fun getAccount(fitnessOptions: FitnessOptions) : GoogleSignInAccount{
	val account = GoogleSignIn.getAccountForExtension(GlobalApplication.getApplicationContext(),fitnessOptions)
	return account
}

getAccountForExtension 메서드를 이용하여 추가한 데이터에 대한 인증을 사용하는 google signin account를 얻음.

  1. google fit api를 사용하기 위한 권한 요청
fun checkHasGrantedDataAccess(account: GoogleSignInAccount, fitnessOptions: FitnessOptions, callback: () -> Unit){
    Log.i(TAG,"checkHasGrantedDataAccess${account.id}, fitnessOptions${fitnessOptions}")
if(!GoogleSignIn.hasPermissions(account, fitnessOptions)){
	//해당 google id가 permission이 허용되었는지 체크함.
	Log.d(TAG,"!GoogleSignIn.hasPermissions")
	GoogleSignIn.requestPermissions(mActivity,GOOGLE_FIT_PERMISSIONS_REQUEST_CODE, account, fitnessOptions)
  }else{
	  callback()
  }
}

account 가 접근하고자 하는 google fit api data에 대한 권한이 있는지 체크하고, 권한이 있다면 callback함수를 실행함. 없다면 권한을 요청함.

  1. 걸음 수 / 걸은 거리 데이터 구독 시작
//피트니스 데이터(걸음 수)구독셋팅
fun subscribeStepCountData(successCallback: () -> Unit?, failureCallback: () -> Unit?){
    Fitness.getRecordingClient(GlobalApplication.getApplicationContext(),mGoogleSignInAccount)
  .subscribe(DataType.TYPE_STEP_COUNT_DELTA)// no scopes are specified.
	.addOnSuccessListener{
	Log.i(TAG,"successfully subscribe step count data!!")
	  successCallback()
	}.addOnFailureListener{
	Log.w(TAG,"there was a problem subscribing step count data${it}")
	  failureCallback()
	}
}

  1. 걸음 수를 원하는 날짜부터 가져옴 (수정 중)
fun getStepCountForDays(days : Int){

	val cal = Calendar.getInstance()
	val now = Date()
	    cal.time= now
	val endTime = cal.timeInMillis
	
	cal.set(Calendar.HOUR_OF_DAY, -days)
	    cal.set(Calendar.MINUTE, 0)
	    cal.set(Calendar.SECOND, 0)
	    cal.set(Calendar.MILLISECOND, 0)
	
	val startTime = cal.timeInMillis
	
	val readRequest = DataReadRequest.Builder()
	        .aggregate(DataType.TYPE_STEP_COUNT_DELTA, DataType.AGGREGATE_STEP_COUNT_DELTA)
	        .bucketByTime(1, TimeUnit.DAYS)
	        .setTimeRange(startTime, endTime, TimeUnit.SECONDS)
	        .build()
	
	    Fitness.getHistoryClient(mActivity,mGoogleSignInAccount)
	    .readData(readRequest)
	    .addOnSuccessListener{
	response->
	for(dataSetinresponse.buckets.flatMap{ it.dataSets}) {
	  Log.i(TAG,"dataSet ==${dataSet}")
		//원하는 로직 추가 }
	}.addOnFailureListener{
		//실패 처리로직 추가
	}
}

원하는 날부터 현재까지 일 단위의 걸음 수 데이터를 가져오는 로직

결과

테스트를 해보려고 구글 피트니스 앱과 데이터를 비교한 결과 데이터가 잘 조회 되는 것을 확인하였음. 이 과정에서 한번 더 고민하고 액션을 취했던 부분은 혹시나 하는 마음에 매일 자정이 되기 찰나의 순간에 하루동안의 데이터를 조회해 오는 메서드 readDailyTotal 를 호출하여 데이터를 저장하는 방법과, DataReadRequest 객체에 startTime과 endTime을 설정해 그 기간동안의 data를 가져와 사용하는 방법 간 데이터 결과에 차이가 있는가에 대한 테스트를 했고 데이터간 차이가 없는 것을 확인하고 후자의 방식으로 채택했음. 그러나 startTime과 endTime을 잘못 설정하면 자정이 기준이 아니고 현재 시간을 기준으로 하루가 책정되기 때문에 startTime과 endTime을 설정을 자신이 필요한 데이터에 따라 정확히 할 필요가 있음.

Chronometer를 이용한 스톱워치 구현

<Chronometer
android:id="@+id/timer"
android:layout_width="200dp"
android:layout_height="40dp"
android:textSize="16sp"/>

xml파일에 다음과 같이 Chronometer 를 추가함.

나는 start, pause, stop 버튼에 각각 시작, 일시정지, 중지 기능을 추가해 넣었음.

전역변수로는 일시 정지를 누른 시간을 저장함

fun startTimer(){
	timer.base= SystemClock.elapsedRealtime() +pauseTime
  timer.start()
}

fun pauseTimer() {
	pauseTime=timer.base- SystemClock.elapsedRealtime()
	timer.stop()
}

fun resetTimer(){
	pauseTime= 0L
	timer.stop()
}

각각 버튼의 클릭리스너에 기능에 맞는 함수를 호출하면 됨.

여기서 timer는 Chronometer 임**.**

1. 하고자 하는 기능?

사용자가 자신이 갔던 경로를 트랙킹하여 지도에 표시해 타 사용자들에게 공유하는 기능

2. 프로세스

  1. 해당 화면 접근 시 런타임에 위치 권한 체크
  2. 위치 권한 허용 시 (3)으로 이동, 거부시 (5)로이동
  3. start 버튼 선택 시 현재 내 위치로 이동 및 tracking시작
  4. 설정한 시간 간격으로 위치를 얻어와 지도 위에 선으로 표시
  5. stop버튼 선택 시 tracking 종료
  6. 위치 권한 재 요청, 2번 거부 시 수동으로 앱 설정에 가서 허용하라는 다이얼로그 표시

3. 구현 방법

3-1) 런타임 위치 권한 체크

** 위치 권한 체크 시 유의할 점

내가 구현하고자 했던 기능은 앱이 백그라운드 상태에 가 있을 때에도 사용자의 위치를 추적해야 했다. 안드로이드 6부터는 앱에서 필요한 권한이 있을 때 런타임에서 권한을 받게 되었는데, 위치 권한은

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

manifest.xml

ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION 두개의 권한을 받아 사용하였다. 첫번째 줄에 선언한 권한은 네트워크 만을 이용하여 대략적인 위치 정보를 요청하는 권한이고 두번째 줄에 선언한 권한은 GPS와 네트워크를 이용하여 정확한 위치 정보를 요청하는 권한이다. ACCESS_FINE_LOCATION 권한은 반드시 ACCESS_COARSE_LOCATION권한이 허용되어야 한다.

백그라운드에서의 위치 권한은 안드로이드 10 미만으로는 따로 선언하지 않고 사용할 수 있다.

안드로이드 10 이상 부터는 위치 정보 사용이 포그라운드/ 백그라운드로 나누어지게 되는데 백그라운드에서 위치 권한을 사용하려면

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

manifest.xml

ACCESS_BACKGROUND_LOCATION 권한을 따로 요청해야한다.

안드로이드 11이상 부터는 백그라운드에서 위치정보 사용 시 런타임 권한을 두 번 요청 해야한다.

포그라운드/ 백그라운드 위치 권한을 동시에 받으면 제대로 권한 체크가 되지 않고 무시하게 된다.

백그라운드 위치 권한은 왜 백그라운드 위치 권한을 받는지에 대한 다이얼로그와 함께 백그라운드 위치 권한을 사용자가 허용으로 설정할 수 있도록 설정 페이지로 보내주어야 하며 사용자 선택에 따른 결과 처리도 알맞게 따로 해주어야 한다.

3-2) 좌표 값 얻기

나는 Google Play 서비스 Location API를 사용하여 일정한 시간 주기로 좌표 값을 가져왔다. FusedLocationProviderClient가 제공하는 getCurrentLocation 메서드를 이용하여 현재 위치 값을 가져왔다. 문서에는 getLastLocation메서드를 사용해 좌표값을 가져오는 것을 권장한다고 적혀있지만 이전 프로젝트에서 사용했을 때 위치 설정을 막아 놓았다가 막 켠 상태라면 저장되어 있는 좌표 값이 없어 좌표가 null로 반환되는 오류가 있었다. 이 때문에 지속적으로 위치 정보를 가져오지 않고 한번만 가져와도 무방하다면 getCurrentLocation 메서드를 사용하는게 더 좋다고 생각한다.

계속해서 업데이트 되는 좌표를 얻기 위해서는 requestLocationUpdates 메서드를 사용하여 지속적으로 위치를 업데이트 할 수 있다. 위치 정보를 가져올 시간 간격, 정확도를 설정해 LocationRequest객체를 생성하여 설정한 간격으로 좌표값을 가져온다.

다음은 카카오 로그인 릴리즈 해시키를 등록해보겠습니다.

 

일단 윈도우에서 릴리즈 해시키를 쉽게 얻으려면 크롬에서 제공해주는 리눅스 터미널 TermLinux를 사용해야합니다.

https://chrome.google.com/webstore/detail/termlinux-terminal-for-co/hlgjjjociconbkooaggfmjhalogadcee

 

TermLinux 명령 행을위한 터미널

소형 온라인 리눅스 가상 머신에 명령 행 콘솔을 제공하는 웹 터미널

chrome.google.com

1편에서 얻었던 SHA-1키를 복사한후 TermLinux 터미널에 

echo <SHA-1 키 입력> | xxd -r -p | openssl base64

명령어를 입력합니다.

 

명령어 입력후 나온 해시키를 복사하여

카카오 개발자 홈페이지 앱설정 -> 플랫폼 -> 키 해시에 복사한 해시키를 붙여 넣습니다.

 

플랫폼 선택
키 해시 추가

이제 완료되었으니 릴리즈로 테스트 해봅니다!

안드로이드에서 애플 로그인을 구현하려면 파이어베이스와 연동이 필요합니다.

★진행하기에 앞서서 파이어베이스에 프로젝트를 추가 해주세요!!★

 

1. 애플 개발자 사이트에 앱 설정하기

1-1. 앱 등록

위와 같은 순서로 진행 해주세요

 

 

1-2. 키 등록

로그인을 체크하고 configure 버튼을 눌러주세요

 

앞서 만든 앱 ID를 선택하고 configure를 save 해주세요
키를 만들고 다운로드 해주세요, 비공개키는 안전하게 프로젝트 디렉토리안에 옮겨둡시다

 

1-3. 서비스 ID 등록

 

순서대로 진행하여 service id를 생성해주세요

 

2. 파이어베이스 연동하기

authentication -> apple 로그인을 사용설정 해줍시다.

앞서 등록한 service id, key, 앱의 id를 각각 입력해주시고, 다운받은 비공개 키를 열어 복사 붙여넣기 해줍니다!

그리고 스위치를 on 으로 변경한 후 저장을 눌러주세요

 

구현 코드는 아래 사이트를 참고 해주세요.

https://firebase.google.com/docs/auth/android/apple?hl=ko 

 

Android에서 Apple을 통해 인증  |  Firebase

Firebase SDK를 사용하여 엔드 투 엔드 OAuth 2.0 로그인 과정을 실행하면 사용자가 Apple ID를 사용해 Firebase에 인증하도록 할 수 있습니다. 중요: Apple로 로그인하려면 사용자는 다음을 충족해야 합니다

firebase.google.com

 

1. 네이버 안드로이드 플랫폼 등록하기 

네이버 개발자 사이트 접속 https://developers.naver.com/ -> 내 애플리케이션 등록 선택

제공받을 정보를 선택하고 애플리케이션 등록하기
패키지명과 다운로드 URL을 입력해줍시다!!

2. Gradle에 라이브러리 추가하기

SDK를 다운로드 합시다!!

SDK 다운로드 후 .arr 파일을 프로젝트 libs 폴더 아래 추가 해주세요!

그 이후 module gradle 파일 dependency에


implementation files('libs/naveridlogin_android_sdk_4.2.6.aar')를 추가해줍시다!

 

3. 난독화 설정 제외

proguard-project.txt 파일에 

keep public class com.nhn.android.naverlogin.** { public protected *; } 코드를 추가하여 난독화 설정을 제외 해주세요

 

네이버 로그인 개발 가이드는 아래 링크를 참고해주세요!

https://developers.naver.com/docs/login/devguide/devguide.md#%EB%84%A4%EC%9D%B4%EB%B2%84%EC%95%84%EC%9D%B4%EB%94%94%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B0%9C%EB%B0%9C%EA%B0%80%EC%9D%B4%EB%93%9C

1. 카카오 안드로이드 플랫폼 등록하기

 

꼼꼼히 빈칸을 채워준다. 

마켓 URL은 마켓에 등록 되었을 때 차후에 입력해도 된다.키해시를 얻는 방법은 여러가지 인데여기서는 간단하게 코드로 얻는 방식으로 소개한다.

 

키 해시 얻는 코드 (코틀린)

 

private fun getAppKeyHash() {

        try {

            val info =

                packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)

            for (signature in info.signatures) {

                var md: MessageDigest

                md = MessageDigest.getInstance("SHA")

                md.update(signature.toByteArray())

                val something = String(Base64.encode(md.digest(), 0))

                Log.e("Hash key", something)

            }

        } catch (e: Exception) {

            Log.e("name not found", e.toString())

        }

    }

 

 

2. Gradle에 라이브러리 추가 하기

project 수준의 gradle에 코드 추가
module 수준 gradle에 dependency 추가

3. 기타 설정

난독화 제외를 위해 proguard-rules.pro 파일에 코드 추가
kakao 로그인 api 사용을 위해 초기화, 글쓴이는 Globalapplication의 onCreate 에 작성하였고, 앱키는 Config파일에 따로 관리하였다.

 

카카오 로그인 구현 샘플코드는 아래 링크 참고.

 

https://developers.kakao.com/docs/latest/ko/kakaologin/android

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

 

1. Firebase 에 앱 등록하기

1. Gradle -> android -> signingReport 선택 후 SHA-1를 복사

 

2. 꼼꼼히 빈칸을 채워주자. 디버그 서명인증서 칸에는 복사해둔 SHA-1 키 붙여넣기

2. Gradle 추가

3. google-service.json 파일 다운로드 후 프로젝트 내 app 폴더로 이동
4. 프로젝트 수준의 gradle에 google-services 파일을 추가 해준다.
5. 모듈 수준의 gradle에 dependencies 추가
6. 모듈 수준의 gradle 에 apply 추가

3. 기타 설정

7. 콘솔에서 구글 로그인 사용 허용

 

로그인 샘플코드는 https://firebase.google.com/docs/auth/android/google-signin?hl=ko

 

Android에서 Google 로그인을 사용하여 인증  |  Firebase

Google 로그인을 앱에 통합하여 사용자가 Google 계정으로 Firebase에 인증하도록 설정할 수 있습니다. 시작하기 전에 아직 추가하지 않았다면 Android 프로젝트에 Firebase를 추가합니다. Firebase Android BoM

firebase.google.com

를 참고 하면 정확하다.

+ Recent posts