Android Wearable Data Layer



안드로이드 앱이 Wear기기를 지원하기 위해서는 두가지방식이 있다. 첫번째는 Notification을 이용해서 메세지를 보여주거나 간단한 액션으로 명령을 내려 처리하는 방법. 두번째는 Wear기기에 직접 앱을 올려 동작시키는 방법이 있다. 두번째 방법은 전혀다른 두개의 기기에 동시에 데이터를 동기화를 해야하는데, Google Play Service 5.0에 포함된 Wearable Message API를 사용하면된다.

 

data-layer-stack

 

 

 

 

 

 

 

 

 

 

 

Wearable Message API로 한쪽에서 메세지를 전송하고 다른 한쪽에서는 WearableListenerSevice를 통해 메시지를 수신하면 된다. 실제로 블루투스를 통해서 메시지를 주고 받는것은 Google Play Service에서 담달하기 때문에  우리는 단순히 API를 통해서 snedMessage, onMessageReceived로 메시지를 송/수신할 수 있다.

 

그럼 간단한 예제를 통해 메세지를 주고받은 예제를 구현해보자.

Android Studio에서 간단하게 Phone용과 Wear용으로 하나의 프로젝트로 만들수 있다. (프로젝트 생성 부분은 생략.)

 

Phone에서 메세지 전송

 

  1. GoogleApiClient 초기화
public class Handheld extends Activity implements
  GoogleApiClient.ConnectionCallbacks,
  GoogleApiClient.OnConnectionFailedListener {

  GoogleApiClient googleClient;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_handheld);

  // Build a new GoogleApiClient
  googleClient = new GoogleApiClient.Builder(this)
    .addApi(Wearable.API)
    .addConnectionCallbacks(this)
    .addOnConnectionFailedListener(this)
    .build();
  }
      // Data layer and lifecycle implementation (Step 2)
      ...
}

 

  1. 콜백 메소드 추가및 라이프 사이클에 따른 연결 설정
// Connect to the data layer when the Activity starts
@Override
protected void onStart() {
      super.onStart();
  googleClient.connect();
}

// Send a message when the data layer connection is successful.
@Override
public void onConnected(Bundle connectionHint) {
      sendDataLayerMessage();
}

// Disconnect from the data layer when the Activity stops
@Override
protected void onStop() {
  if (null != googleClient && googleClient.isConnected()) {
    googleClient.disconnect();
    }
    super.onStop();
}

 

  1. 메시지 전송
private void sendDataLayerMessage() {
  new Thread(new Runnable() {
    @Override
    public void run() {
      // Get the connected nodes and wait for results
      NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleClient).await();
      for (Node node : nodes.getNodes()) {
        // Send a message and wait for result
        SendMessageResult result =
          Wearable.MessageApi.sendMessage(googleClient, node.getId(),
          MESSAGE_RECEIVED_PATH, MESSAGE.getBytes()).await();
          if (result.getStatus().isSuccess()) {
            Log.v("myTag", "Message sent to : " + node.getDisplayName());
          }
          else {
            // Log an error
            Log.v("myTag", "MESSAGE ERROR: failed to send Message");
          }
       }
    }
  }).start();
}

 

 

Wear에서 메시지 수신

 

메시지 수신은 WearableListenerService를 통해 수신을 받을 수 있다. Service를 통해 받은 메시지를 Activity화면에 보여 주기 위해서 Broadcast로 처리한다.

 

  1. WearableListenerService와 Wear기기를 사용하기위해 다음과 같이 Android Manifest에 추가한다.
<uses-feature android:name="android.hardware.type.watch" />

<application
  ...
  <service android:name=".ListenerService">
    <intent-filter>
      <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
    </intent-filter>
  </service>
</application>

 

  1. WearableListenerService 구현
public class ListenerService extends WearableListenerService {

  @Override
  public void onMessageReceived(MessageEvent messageEvent) {

    if (messageEvent.getPath().equals(MESSAGE_RECEIVED_PATH)) {
      final String message = new String(messageEvent.getData());
      Log.v("myTag", "Message path received on watch is: " + messageEvent.getPath());
      Log.v("myTag", "Message received on watch is: " + message);

      // Broadcast message to wearable activity for display
      Intent messageIntent = new Intent();
      messageIntent.setAction("message-forwarded-from-data-layer");
      messageIntent.putExtra("message", message);
      LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
    
    }
    else {
      super.onMessageReceived(messageEvent);
    }
  }
}

 

  1. Activity에서 Broadcast Receiver를 등록.
@Override
protected void onCreate(Bundle savedInstanceState) {
  // Basic UI code, generated by New Project wizard.
          ...

  // Register a local broadcast receiver, defined is Step 3.
  IntentFilter messageFilter = new IntentFilter("message-forwarded-from-data-layer");
  MessageReceiver messageReceiver= new MessageReceiver();
  LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, messageFilter);
}

 

  1. 전송받은 메세지를 UI처리
 public class MessageReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
      String message = intent.getStringExtra("message");
              // Display message in UI
      mTextView.setText(message);
    }
  }
}

 
 
이제 Phone과 Wear기기가 연결 된 상태에서 Phone용으로 만든 앱을 실행 하면 Wear기기에 전달받은 메시지가 출력된다.

wear-message
 

 

 

 

 

 

 

 

 

 

참고: https://github.com/LarkspurCA/androidweardocs/blob/master/sync.rst

 
 
 




안드로이드 웨어 앱 개발에서 출시 후기

안드로이드 웨어 OS다 탑제된 GWatch를 구입한지 벌써 3주째에 접어들면서 이것저것 사용해보았다. 일단 Wear만 가지고 뭘 할 수 있게끔 만드는 것은 손에 꼭힐 정도로 폰과 밀접하게 엮어 있다. 구글 안드로이드 컨퍼런스에서 발표자가 노티피케이션 셔틀이라고 그러던데 이런말이 괸히 나온게 아니다.

 

어쨌든 뭘 만들어 볼까 고민 하다가 요즘 기타를 배우고 있는데, 기타 튜닝을 한번씩 해줘야 한다. 그래서 폰에도 훌륭한 앱들이 많지만 시계는 왠지 매일 차고 있으니까 좀더 쉽고 빠르게 사용가능하지 않을까 라는 생각으로 튜닝앱 개발 시작!

prom

다운로드: https://play.google.com/store/apps/details?id=com.kmshack.wear.guitartuner

 

 

보통 이클립스로 작업 하는데 이번 Wear앱 만들면서 Android Studio로 개발했다. 왜냐면 Eclipse는 멀티 APK빌드를 제공하지 않기 때문이다. 처음써보는 툴에 단축키도 말썽이고 끙끙 되면서 개발했다. xml레이아웃 편집은 Eclipse보다 훨씬 빠르고 좋았다. 몇몇 단축키가 Eclipse로 맵핑을 해도 안되는거빼곤 쓸만 하다.

 

오디오 레코딩을 통해 주파수 읽어 와서 기타의 등정 코드와 비슷한가를 퍼센테이지로 화면에 보여주게 목표였다. 인터넷에 기타 음역대 주파수도 검색해보고 나름 흥미로웠다.

 

Wear를 바로 USB디버깅을 통해 폰과 같이 바로바로 실행해볼 수 있다. Wear단말 설정에서 빌드버전을 마구 터치 하면 개발자 옵션이 열리면서 디버깅이 가능하다.

 

결국 개발은 끝! Wear를 APK로 뽑아서 폰에 설치!!

뭔가 이상하다.  INSTALL_FAILED_OLDER_SDK  뜨면서 설치 안됨. 그렇지!! Wear은 API LEVEL20이니까 당연히 내폰은 18인데 설치가 안된다.

 

폰앱에 Wear앱을 심어서 앱이 깔리면 폰에서 Wear에서 apk를 넘겨주는 구조이다. Android Studio에서 프롭젝트 만들때 Wear만 체크를 해서 폰용 프로젝트가 만들어 지지 않았다. 그래서 폰용 프로젝트를 추가 해서 새롭게 빌드하고 설치!!

 

그런데 Wear기기로 앱이 넘어 오지 않는것이다.

 

검색 해봤더니 넘어 가지 않는 경우는 두가지.

Phone, Wear 의 매니페스트 퍼미션이 같아야 하며, Wear관련 퍼미션이 추가 되어야 한다.

 

<uses-feature android:name="android.hardware.type.watch" android:required="false"/>

 
Android Studio의 경우 빌드시 Wear  APK파일을 raw Resource폴더에 복사되며 관련 메타 테그도 매니페스트에도 자동으로 추가된다.  하지만 Eclipse의 경우 수동으로 작업을 해줘야 하는데, https://medium.com/@tangtungai/how-to-develop-and-package-android-wear-app-using-eclipse-ef1b34126a5d여기에 자세히 있으니 참고하면 된다.

그리고 유료앱일 경우에도 자동으로 Wear에 넘어 가지 않는 버그(보안상의 문제로)가 있어서 위와 같은 방법을 써야한다.

 

 

 

Google Android Wear 개발환경 설정

구글 I/O 2014를 발표를 기점으로 기존의 Wear Preview에서 정식으로 발표되었다. LG  G Watch와 삼성 Gear Live도 함께 출시되었다. 이로 인해 Wear Device를 처음으로 발을 내딧게 되었다. 기존의 Wear Preview 버전은 Eclipse를 지원하였으나, 이번 정식 버전에는 Eclipse에서는 지원하지 않고, Android Studio에서만 확인 가능하다.

 

구글은 Wear은 API 20 버전으로 Android 4.4W라는 네임을 가진다. Preview 버전에 비해 개발툴에서 많은 지원이 이루어졌으며, 구글 플레이서비스 5.0과 Anroid Wear 앱과 Google Search앱들도 대거 업데이트되어 이를 기반으로 Wear이 작동된다.

 

wear sdk

기존의 Preview버전을 사용한 개발자라면 모두 제거하고 정식버전을 설치 해야한다.

 

Wear 에뮬레이터와 폰간의 연결하기.

 

  1. 아직 Wear관련 해서 앱들이 정식 출시 되지 않았기때문에 Testing을 등록 해서 구글 플레이 서비스 5.0과 Adnroid Wear, Google Search 앱을 내려받아야 한다.

1) Android Play Service 5.0

2) Android Wear Compaion

3) Google Search

 

  1. AVD 에서 Waer용 애물레이터를 만든다.

wear emulator

  1. 1번에서 설치한 Android Wear을 실행 후에 Notification Access 설정에서 Android Waer을 선택한다. Android Wear은 Android Notification을 이용하기때문에 액세스할 수 있는 권한을 주는 것이다. 안드로이드 폰에서 문자가 오거나 음악을 들을때 Notofication이 뜨는것을 볼 수 있는데 이것이 그래도 Wear에도 표시된다.

wearapp

 

  1. 에뮬레이터와 폰간의 연결을 위해 다음과 같이 adb명령을 내린다.
$ adb -d forward tcp:5601 tcp:5601

 

wear screen