[기술정보] Awareness API로 사용자 상황에 반응하는 개인맞춤형 앱 개발하기

반갑습니다, SPH입니다!

지난 포스팅 I/O 2016에서 발표한 Awareness API 기술 A to Z(이하 지난 포스팅)에서

사용자 Context의 종류와 Context 인지의 필요성
Awareness API 등장 배경 및 사용 방법 개요

에 대한 내용을 공유했습니다. 이번에는 지난 포스팅에서 했던 약속, Awareness API 출시 후 구체적인 활용방안과 사용 방법을 알려드리기 위해 Awareness API로 sample 앱을 만들었던 경험 및 실제 사용 방법에 대한 내용을 가지고 돌아왔습니다.

 

사용자 상황에 반응해서 맞춤 정보를 제공하는 개인맞춤형 앱 개발
수능을 본지 오래된 여러분에게 수험생 할인 이벤트 광고 알람이 왔다고 상상해 보세요! 온디맨드 시대에 스마트폰의 특정 애플리케이션이 내게 필요 없고 의미 없는 광고알람을 보내면, 그것만큼 스트레스받는 일도 없을 겁니다.

귀찮고 쓸모없는 Notification들

사용자의 위치, 움직임 등을 인지해서 사용자가 필요한 순간, 필요한 장소에 있을 때 서비스를 이용할 수 있도록 애플리케이션을 개발해야 합니다. Google Awareness API는 이를 위한 최선의 방법 중 하나입니다. GPS나 자이로센서 등, 사용자 행동 인지를 위해 필요한 센서 데이터를 목적에 맞게끔 제공해 주니까요. 한 가지 예를 들어보겠습니다.

 

 환자가 병원에서 업무를 본 후, 맞춤 보험 정보를 제공해주는 애플리케이션
최근 타 기업과 기술 논의 과정에서 한 가지 Sample 앱을 만들게 되었습니다. 이 앱은 사용자에게 교통사고가 났다고 가정하고, 운송수단을 이용해 병원으로 이동 후 병원 업무를 본다고 가정합니다. 병원 업무를 보고 나면, 이를 인지해서 최종적으로 알림을 주는 Sample 앱입니다.

사용자 행동과 위치를 파악하여, 필요한 순간 적절한 알림을 주는 애플리케이션

3~5초마다 GPS 신호를 읽어서 위의 앱을 구현한다면 의미 없이 배터리가 소모될 것이고, 최악의 경우 앱은 삭제될 것입니다. 또한, 이미지상의 프로세스는 간단해 보이나 실제로는 Geofencing API, Fused Location API, Detected Activity API 등 사용해야 할 것들이 많아, 복합적으로 이용할 때 고려해야 할 사항이 많습니다.

그러나 저희는 Awareness API를 이용하여 기존보다 더 빠르게, 코드는 더 심플하게 구현할 수 있었습니다. 여기서는,

  • 지하철, 구급차, 버스 등 운송수단을 이용 중인지 판단
  • 운송수단 이용을 중지한 상태인지 판단
  • 내 위치의 위도, 경도 값 받기
  • 내 위치가 설정해둔 특정 건물 근처에 있는지 판단

과 같은 사용자 행동 판단 필요 부분을 Awareness API로 해결하였습니다. Awesome! 한 가지 API로 Geofencing, Fused Location, Detected Activity 등 많은 API를 대체한 것입니다.

 

 여러분이 구상하는 앱에도 Awareness API가 필요한지 알아보세요!
Awareness API를 이용해 가능한 애플리케이션을 몇 개 더 생각해 보겠습니다. 예시에서 초록 색깔의 글씨는, 쉼표(comma) 기준으로 모두 Awareness API로 검출이 가능한 상황들입니다.

case

다양한 Awareness API 사용 예시들

어떠신가요? Awareness API가 여러분의 Application에 적용할 수 있다고 생각되거나, 사용 방법에 대해 더 자세히 알아볼 필요가 있으신가요? 그렇다면 Awareness API의 개요에 대해 상세히 설명되어 있는 ‘I/O 2016에서 발표한 Awareness API 기술 A to Z‘ 과, 쉽게 사용할 수 있도록 정리한 아래의 구현 방법 및 tip을 참고하시기 바랍니다.

 

Awareness API를 이용하기 위한 사전 세팅
다른 Google Android API와 마찬가지로, Awareness API를 사용하기 위해서는 몇 가지 세팅이 필요합니다.

1. Google Play services 사용 설정하기
안드로이드 스튜디오->프로젝트 생성-> build.gradle 에서 dependencies 에

compile ‘com.google.android.gms:play-services:9.4.0’

를 추가하고 Gradle Sync를 맞춰줍니다.

 

2. API 키 등록
console.developers.google.com에 접속하여 API Key를 발급받고, Awareness API 사용 설정합니다. 이후 안드로이드 스튜디오-> AndroidManifest.xml 파일에서 다음을 추가합니다.

<application>

<meta-data
android:name=”com.google.android.awareness.API_KEY”
android:value=”YOUR_API_KEY”/>
</application>

Awareness API으로 장소나 비콘 등의 값을 받기 위해서는 다음 내용도 추가해 줍니다.

<meta-data
android:name=”com.google.android.geo.API_KEY”
android:value=”YOUR_API_KEY” />

 

3. GoogleApiClient로 Awareness API 연결
실제 사용을 위해서 onCreate() 메소드 내에 다음과 같이 GoogleApiClient를 생성하고, Awareness API 사용 설정을 해 줍니다.

android.content.Context context;
GoogleApiClient client = new GoogleApiClient.Builder(context)
.addApi(Awareness.API)
.build();
client.connect();

이제 모든 사전 세팅이 끝났습니다. Awareness API 중에서도 어떤 센서 데이터를 이용하느냐 따라서 권한 설정이 필요할 수도 있는데요. 이 부분에 관해서는 여기서 따로 다루지 않겠습니다. 지난 포스팅에서 이미 언급했지만, Awareness API는 크게 SnapshotFence로 나누어서 사용합니다. Snapshot은 날씨, 위치와 같은 실제 값을 알 수 있게 해주며, Fence는 특정 시간 동안 특정 위치에 머물렀는지, 운전과 같은 특정 상황에 있는지를 검출해서 True, False로 알려줍니다.

Awareness API를 이용하기 위한 사전 세팅도 끝났으니, 지금부터는 Snapshot 과 Fence 사용 방법에 대해서 각각 알아보겠습니다.

 

Awareness API – Snapshot API 사용 방법

Snapshot 으로 필요한 데이터를 가져와보자
Snapshot API를 사용해서 위치, 장소, 비콘 상태, 사용자 행동(걷는 중, 뛰는 중, 자전거 타는 중, 운송수단 이용 중, 멈춤 등), 이어폰 연결 상태, 날씨 등의 값을 받아올 수 있습니다.

예를 들어, Snapshot API로 사용자 행동에 대해서 알고 싶다면, 다음과 같은 함수를 구현해서 사용할 수 있습니다.

private void printSnapshot() {
        Awareness.SnapshotApi.getDetectedActivity(mApiClient)
            .setResultCallback(new ResultCallback<DetectedActivityResult>() {
                @Override
                public void onResult(@NonNull DetectedActivityResult dar) {
                    ActivityRecognitionResult arr = dar.getActivityRecognitionResult();

                    DetectedActivity probableActivity = arr.getMostProbableActivity();

                    // Confidence is an int between 0 and 100.
                    int confidence = probableActivity.getConfidence();
                    String activityStr = probableActivity.toString();
                    Log.d("상태검출", "Activity: " + activityStr + ", Confidence: " + confidence + "/100");
                }
            });
}

이외에도 Awareness.SnapshotApi.get~의 형태로 위에서 언급한 상태들을 받아올 수 있습니다.

Snapshot API 응용 예, 사용자 위치 전송 애플리케이션
Snapshot API를 사용처를 생각해보면, 인적 자원을 Tracking 하는 앱 등을 만들 때 편리할 겁니다. 예를 들어 어떤 지역구의 매장을 관리하는 매니저의 동선을 파악할 수 있을 겁니다. Snapshot을 이용해 매니저의 위치와 매니저의 움직임을 쉽게 알 수 있으니까요.

 

Awareness API – Fence API 사용 방법
기존의 GeoFencing(지오펜싱)을 기억하시나요? 사용자가 특정 위치에 대한 바운더리에 들어갈 때, 머무를 때, 나올 때의 상태를 검출하는 것을 지오펜싱이라 합니다. Fence API는 GeoFencing의 확장 개념입니다. 기존 GeoFencing이 단순히 위치에 대한 바운더리만 Fence만 설정할 수 있었다면, Fence API는 사용자의 위치나 행동 상태, 스마트폰의 특정 상태(예를 들어 헤드폰을 꽂는다거나)와 같이 다양한 인지 신호에 대해 펜스를 설정할 수 있습니다. 설명을 위해 스마트폰에 헤드폰을 꽂았는지 여부를 예로 들겠습니다.

Fence 생성하기
먼저 이어폰이 꽂혔는지 여부에 대한 Awareness API 펜스를 만듭니다.

AwarenessFence headphoneFence = HeadphoneFence.during(HeadphoneState.PLUGGED_IN);

위의 소스코드에서는 헤드폰이 꽂혀 있는 상태를 펜스로 설정한 겁니다.

 

콜백을 받기 위한 Fence 등록하기
만들어진 headphoneFence를 등록하기 위해서 FenceApi.updateFences()메소드를 호출하고, ‘펜스 업데이트 요청’ 을 만들기 위해 FenceUpdateRequest.Builder() 를 사용합니다.

// Declare variable for PendingIntent
private PendingIntent mPendingIntent;

protected void registerFence(final String fenceKey, final AwarenessFence fence) {
        Awareness.FenceApi.updateFences(
        mGoogleApiClient,
        new FenceUpdateRequest.Builder()
        .addFence(fenceKey, fence, mPendingIntent)
        .build())
        .setResultCallback(new ResultCallback<Status>() {
            @Override
            public void onResult(@NonNull Status status) {
                if(status.isSuccess()) {
                    Log.i(TAG, "Fence was successfully registered.");
                    queryFence(fenceKey);
                } else {
                    Log.e(TAG, "Fence could not be registered: " + status);
                }
            }
        });
}

 

Fence 상황에 따른 콜백 구현하기
펜스를 등록하고 나면, 펜스가 트리거될 때(상태가 변할 때, 즉 값이 검출될 때) 응답할 수 있는 콜백을 구현해야 합니다. 지금은 헤드폰이 꽂혀있는지를 예로 들고 있으므로, 여기서 펜스의 트리거란 헤드폰이 꽂혀있는지 여부에 따라 True 나 False 같은 boolean 형태의 콜백을 받을 것입니다. 콜백 구현 방법은 브로드캐스트 리시버의 서브클래스를 만들어 인텐트를 처리하는 것인데요. 자세한 건 다음 소스코드로 설명하겠습니다.

// Declare variable for MyFenceReceiver class.
private MyFenceReceiver mMyFenceReceiver;

// Initialize fence variables in onCreate().
protected void onCreate(Bundle savedInstanceState) {
        ...
        Intent intent = new Intent(FENCE_RECEIVER_ACTION);
        mMyFenceReceiver = new MyFenceReceiver();
        registerReceiver(mMyFenceReceiver, new IntentFilter(FENCE_RECEIVER_ACTION));
        ...
        }

// Extend the BroadcastReceiver class.
public class MyFenceReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        FenceState fenceState = FenceState.extract(intent);

        if (TextUtils.equals(fenceState.getFenceKey(), "headphoneFence")) {
            switch(fenceState.getCurrentState()) {
                case FenceState.TRUE:
                    Log.i(TAG, "Headphones are plugged in.");
                    break;
                case FenceState.FALSE:
                    Log.i(TAG, "Headphones are NOT plugged in.");
                    break;
                case FenceState.UNKNOWN:
                    Log.i(TAG, "The headphone fence is in an unknown state.");
                    break;
            }
        }
    }
}

위의 코드는 브로드캐스트 리시버를 확장한 MyFenceReceiver 클래스를 보여줍니다. 이 클래스에서 Fence에서 발생되는 모든 인텐트를 처리하기 위해 BroadcastReceiver.onReceive() 콜백 메소드를 구현했습니다. onReceive()에서 Intent를 받게 되면, FenceState.extract() 메서드를 통해 Fence의 상태 콜백을 받을 수 있습니다.

 

Awareness API는 Place API와 함께할 때 더 큰 빛을 발한다

combination

Awareness API와 Place API를 결합하면 더 많은 것들이 가능하다.

지금까지 Awareness API 사용 방법에 대해 비교적 구체적으로 설명하였습니다. 개인적으로 Awareness API를 테스트해보며 느낀 것은, 활용할 때 Place API와 함께 사용하면 더 좋을 것 같다는 점입니다. Awareness API는 결국 사용자의 상황을 인지하는 것이고, 이를 추가적으로 더 활용하기 위해서는 Place API를 이용해 주변 검색을 통하여 정보를 알아낼 필요가 있기 때문입니다.

 

여전히 알고리즘과 UX 고려가 필요
추가로, sample app을 개발하고 테스트하며 개인적으로 느꼈던 내용을 공유하겠습니다.

happy-user-experience-design

Awareness API를 이용하더라도, 다양한 사용자의 상황을 제대로 인지하기 위해서는 잘 설계된 알고리즘이 필요할 것입니다. 예를 들어서 이동 중인 상태를 Awareness API로 검출하는 경우를 생각해 보겠습니다. 대중교통을 이용한다면, 사용자가 대중교통을 갈아타기 위해 걷는 상황이나 버스가 잠시 멈춘 상황 등을 예외처리하기 위한 알고리즘이 필요할 것입니다.

그런데 UX를 잘 파악할 수 있다면, 알고리즘 설계가 더 간단해지는 경우도 있는 것 같습니다. 예를 들어서 내 위치 주변 병원에 대해 지오펜싱을 설정해서, 병원 업무를 보았는지 여부를 판단할 때를 생각해 볼 수 있습니다. 개발자 입장에서는 한 장소 근처에 병원이 너무 많은 경우를 생각해서, 한 장소에 병원이 1개 있을 때와 2개 이상 일 때를 구분하여 두 개의 Flow를 작성할 수도 있을 겁니다. 하지만 사용자 입장에서 생각해보면 한 장소에 병원이 몇 개가 됐든 간에, 병원 업무를 완료했을 때 알림만 제대로 받으면 됩니다. 그렇다면 하나의 Flow에서 처리할 수 있는 방법도 있을 겁니다. 물론 어떤 병원인지 구분해야 한다면 얘기가 다르겠지만요.

지금까지 Awareness API 사용 방법과 테스트 경험을 공유 드렸습니다. 도움이 되셨길 바라며, Awareness API 사용에서 어려움이 있다거나 Awareness API와 Place API를 함께 쓰는 방안에 대한 더 자세한 방법 등, 기타 질문이 있으시면 언제든 support@sphinfo.co.kr로 문의하시기 바랍니다. 감사합니다.