
도시 비행선 는 인기 있는 메시징 및 알림 서비스입니다. 이 글의 1부에서는 도시 비행선 푸시 알림을 설정하는 방법을 살펴봅니다. 2부에서는 이러한 알림을 사용하여 다음과 같은 작업을 수행합니다. 에서 복제를 트리거합니다. 카우치베이스 모바일.
준비물
UA(Urban Airship)는 무료로 이용할 수 있습니다. (현재 가격 정보는 UA 웹사이트를 참조하세요.) 단, 계정을 등록해야 합니다.
- 도시 비행선 계정
- Firebase 계정(Google 로그인 계정 필요)
- 안드로이드 스튜디오(또는 Xcode)
1부 - 도시 비행선 설정하기
IDE에서 기존 Android 또는 iOS 프로젝트를 불러오거나 새 프로젝트를 만듭니다. 여기서는 Android를 사용해서 설명하겠습니다.
UA 계정에 로그인합니다. 새 앱 페이지로 이동합니다. 앱 이름을 입력합니다. 사용하려는 플랫폼을 선택합니다. (이 예에서는 Android와 iOS를 선택합니다.) '저장'을 누르면 빠른 시작 퀴드로 이동합니다. (이미 빠른 시작을 진행했지만 설정에 대한 복습이 필요한 경우 Android용 단계를 찾을 수 있습니다. 여기 및 iOS용 여기.)

UA 빠른 시작
여기에서 선택한 각 플랫폼에 대한 탭이 제공됩니다. 앞서 언급했듯이 이번에는 Android용 빌드에 중점을 두겠습니다.
도시 비행선 빠른 시작 단계를 따르세요. 제가 겪은 문제에 대한 몇 가지 팁이 있습니다.
도시 비행선 빠른 시작의 1, 2단계
UA 가이드는 프로젝트의 build.gradle 스크립트를 참조하지만 모듈 build.gradle 스크립트 수정을 보여줍니다. 프로젝트의 gradle 스크립트에 UA 리포지토리를 추가하고 모듈 gradle 스크립트에 UA 종속성을 추가했습니다. 잘 작동했습니다.
모듈 gradle 스크립트에서 applicationID를 찾습니다.
도시 비행선 빠른 시작 5단계
나만의 애플리케이션 클래스를 만들려면 프로젝트 탐색 창의 앱 영역을 마우스 오른쪽 버튼으로 클릭하고 새로 만들기 > 자바 클래스를 선택합니다. 팝업에서 클래스 이름을 설정합니다. 그런 다음 수퍼클래스에 android.app.Application을 입력합니다.

매니페스트 파일을 업데이트하는 것을 잊지 마세요. 클래스의 정규화된 이름을 사용하거나 UA가 표시하는 짧은 양식을 사용할 수 있습니다. 정규화된 양식은 다음과 같습니다:
|
1 2 |
<application android:name="com.couchbase.cblite.android.cbpushsync.MyApplication" |
도시 비행선 퀵스타트 6단계
UA는 FCM(파이어베이스 클라우드 메시징)을 사용합니다. 6단계에는 UA의 추가 문서로 연결되는 링크가 있습니다. 이 새 페이지에는 앱의 API 키 생성에 대한 자세한 지침이 있습니다.
해당 페이지의 '도시 비행선으로 FCM/GCM 서비스 구성하기' 제목 아래의 지침이 약간 오래되었습니다. 이제 빠른 시작 가이드의 마지막 부분에 API 키와 패키지를 입력하는 영역이 문서에 나와 있는 위치 대신에 있습니다.
한 곳에서 UA 문서는 "Google API 프로젝트 번호"를 참조합니다. 이 번호를 FCM에서는 발신자 ID라고 부릅니다.
테스트
퀵스타트는 별다른 설명 없이 테스트 영역으로 끝납니다. 애플리케이션 서브클래스에 포함된 코드를 다시 살펴보면 사용자 알림을 활성화하는 것을 볼 수 있습니다. 테스트하려면 앱을 빌드하고 에뮬레이터나 기기에 설치하세요. (두 가지 모두 시도해 보았지만 모두 잘 작동했습니다.)

텍스트 필드에 내용을 입력하고 '테스트 보내기'를 클릭합니다. Android 알림 영역에 아이콘이 표시되어야 합니다. 이상하게도 여기에는 테스트 영역에 입력한 텍스트가 포함되지 않습니다.
문제 해결을 위해 UA는 문서 페이지의 오른쪽 하단에 있는 모호한 '오류 콘솔' 링크로 안내합니다. 안타깝게도 이 링크를 클릭하면 빠른 시작 가이드로 돌아갔습니다.
1부 마무리
이전 단계에서 보셨듯이 도시 비행선 설정은 매우 간단합니다. 퀵스타트는 알림 알림을 보내는 방법을 보여줍니다. Couchbase Lite 클라이언트에서 데이터 동기화를 트리거하려면 대신 무음 알림을 보내야 하는데, 이 글의 2부에서는 이에 대해 다룹니다.
2부 - 클라우드에서 데이터 동기화 트리거하기
이 게시물의 1부에서는 도시 비행선을 설정하고, 2부에서는 다음을 보여드리겠습니다. 로 빌드된 샘플 안드로이드 애플리케이션 카우치베이스 라이트 도시 비행선 푸시 알림을 사용하여 클라우드에서 모바일 장치로 데이터 동기화를 트리거합니다. 여기서 '클라우드'는 동기화 게이트웨이 인스턴스 설정을 테스트 구성에 적용했습니다. (Couchbase Lite 및 동기화 게이트웨이는 모두 Couchbase Mobile 스택의 일부입니다. Couchbase Mobile에 대해 읽어볼 수 있습니다. 여기.)
배경
카우치베이스 모바일은 단방향 복제를 사용하여 데이터를 동기화합니다. 로컬 데이터가 최신 상태가 되면 복제를 실행하고 즉시 종료하도록 설정하거나("원샷"), 새로운 변경 사항을 무기한 수신하도록 설정할 수 있습니다("연속").
연속 복제를 설정하는 대신에 동기화를 트리거하기 위해 Urban Airship과 같은 서비스를 사용하려는 몇 가지 이유가 있습니다. 예를 들어, 연속 '풀' 복제(클라우드에서 데이터를 검색하는 복제)는 네트워크 연결을 계속 열어 두어야 합니다. 연결이 열려 있으면 비활성 상태에서도 장치 배터리가 어느 정도 소모될 수밖에 없습니다. 애플리케이션은 전송할 변경 사항이 있을 때만 연결을 여는 것이 이상적입니다.
그 외에도, 어반 에어십과 같은 푸시 알림 서비스에는 일반적으로 여러 디바이스 그룹을 대상으로 하는 다양한 고급 기능이 있습니다. UA를 사용하면 작업 발생 시기를 유연하게 관리할 수 있습니다. 또한 앱에서 이미 푸시 서비스를 사용하고 있다면 이미 자체 개방형 네트워크 연결이 필요합니다. 네트워킹을 두 배로 늘리는 대신 이를 사용하여 Couchbase Lite를 트리거하는 것이 좋습니다.
이 예제에서는 도시 비행선을 통합하는 방법을 보여드리겠습니다. 완전히 작동하는 애플리케이션을 구축할 수 있도록 필요한 모든 부분을 안내해 드리겠습니다.
애플리케이션
다음은 애플리케이션이 실제로 작동하는 모습입니다. 이미지의 위쪽은 앱이 실행 중인 모습을 보여줍니다. 아래 부분은 명령줄에서 전송된 푸시 알림을 보여줍니다. 앱이 푸시 알림을 받으면 진행률 스피너를 띄우고 원샷 풀 복제를 실행한 다음 수신된 문서 변경 내용을 텍스트 보기에 표시합니다.
이 예제를 이해하기 위해 네 가지 클래스와 이를 하나로 묶는 '접착제'를 살펴보고 결과를 테스트하는 방법을 보여드리겠습니다.
도시 비행선에 필요한 클래스
도시 비행선(UA)을 사용하려면 두 개의 클래스, 즉 Autopilot의 서브클래스와 AirshipReceiver의 서브클래스를 구현해야 합니다.
자동 조종 장치
UA는 사용하기 전에 초기화해야 합니다. 두 가지 방법으로 초기화할 수 있습니다. takeOff 애플리케이션의 onCreate 메서드를 사용하거나 오토파일럿의 서브클래스를 생성할 수 있습니다. 저는 후자를 선택했습니다. 앞으로 살펴보겠지만 UA에는 서브클래스를 자동으로 사용하는 흥미로운 방법이 있습니다.
수업은 간단합니다. 알림 표시줄에 아무것도 표시하고 싶지 않습니다. 이 클래스를 사용하여 사용자 알림을 끄기만 하면 됩니다.
다음은 CBAutoPilot.java의 전체 목록입니다.
|
1 2 3 4 5 6 7 8 9 10 11 |
package com.couchbase.cblite.android.cbpushsync; import com.urbanairship.Autopilot; import com.urbanairship.UAirship; public class CBAutoPilot extends Autopilot { @Override public void onAirshipReady(UAirship airship) { airship.getPushManager().setUserNotificationsEnabled(false); } } |
이 클래스를 사용하기 위해 UA는 안드로이드에 고유한 기술을 사용합니다. Android 매니페스트 파일에서 항목에 사용할 클래스를 지정합니다. 필자의 경우 항목은 다음과 같습니다( 애플리케이션 섹션):
|
1 2 |
<meta-data android:name="com.urbanairship.autopilot" android:value="com.couchbase.cblite.android.cbpushsync.CBAutoPilot"/> |
여기서 약간의 안드로이드 마법이 일어납니다. UA에는 초기화를 자동화하는 콘텐츠 프로바이더 클래스가 포함되어 있습니다. 콘텐츠 프로바이더는 애플리케이션의 onCreate 메서드가 호출됩니다. UA는 이를 사용하여 이 메타데이터 항목을 읽고, 하위 클래스를 인스턴스화하며, 이 메타데이터 항목을 읽는 코드를 포함하기 위해 onAirshipReady 메서드를 사용합니다.
비행선 수신기
UA가 초기화되고 사용할 준비가 되었으면 알림을 캡처하고 처리하는 훅을 제공해야 합니다. 이를 위해 AirshipReceiver의 서브클래스를 구현합니다. 다시 말하지만, 클래스는 간단합니다.
다음은 CBAirshipReceiver.java의 전체 목록입니다.
|
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
package com.couchbase.cblite.android.cbpushsync; import android.content.Context; import android.support.annotation.NonNull; import android.util.Log; import com.urbanairship.AirshipReceiver; import com.urbanairship.push.PushMessage; public class CBAirshipReceiver extends AirshipReceiver { private static final String TAG = "CBAirshipReceiver"; @Override protected void onPushReceived(Context context, PushMessage message, boolean notificationPosted) { Log.i(TAG, "Received push message. Alert: " + message.getAlert() + ". posted notification: " + notificationPosted); switch(message.getAlert()) { case "start": CBLHelper.getInstance().startReplication(); break; case "stop": CBLHelper.getInstance().stopReplication(); break; case "reset": CBLHelper.getInstance().reset(); break; default: break; } } @Override protected void onChannelCreated(@NonNull Context context, @NonNull String channelId) { Log.i(TAG, "Channel created. Channel Id:" + channelId + "."); } @Override protected void onChannelUpdated(@NonNull Context context, @NonNull String channelId) { Log.i(TAG, "Channel updated. Channel Id:" + channelId + "."); } @Override protected void onChannelRegistrationFailed(Context context) { Log.i(TAG, "Channel registration failed."); } } |
앱 테스트에 들어가면 UA를 통해 알림 문구를 설정하는 방법을 살펴보겠습니다. 여기서는 몇 가지 다른 원격 작업을 제공하는 데 사용했습니다. 알림은 복제를 시작하고 중지할 수 있습니다. 또한 '재설정'을 전송하여 데이터베이스를 삭제하는 기능도 포함했습니다. 이렇게 한 이유는 데이터를 복제하면 기기에서 영구적으로 유지되기 때문입니다. 앱을 종료해도 로컬 데이터베이스는 초기화되지 않습니다. 동기화 게이트웨이를 통해 항상 새 문서를 추가해야만 복제가 작동하는 것을 보여주는 대신 장치 데이터베이스를 지우고 다시 시작하는 기능을 추가했습니다.
위에서 재정의된 몇 가지 다른 메서드를 볼 수 있습니다. 이러한 메서드는 모두 AirshipReceiver 클래스에서 추상적으로 선언되어 있으므로 최소한의 구현만 포함해야 합니다. 하지만 메시지를 보내려면 디바이스 채널 ID를 알아야 합니다. 이 채널 ID는 자주 변경됩니다. 다음 글에서는 서버 측 애플리케이션이 디바이스에 메시지를 보낼 수 있도록 ID를 등록하는 방법을 보여드리겠습니다. 지금은 ID를 추출하여 테스트에 사용할 수 있도록 ID를 기록해 두는 것이 유용합니다.
애플리케이션 클래스
위의 훅은 UA를 실행하고, 알림을 트래핑하고, 콘텐츠에 따라 액션을 트리거합니다. 이제 애플리케이션 자체를 살펴보겠습니다.
이 앱은 문서가 가져올 때 문서 내용을 볼 수 있도록 설정된 하나의 활동으로 구성됩니다. 다른 클래스는 일부 Couchbase Lite 기능을 헬퍼로 래핑합니다.
주요 활동
기본 활동에서 복제가 진행되는 동안 진행률 표시줄을 표시한 다음 전송된 문서 집합을 표시하고 싶습니다.
MainActivity.java의 전체 목록은 다음과 같습니다.
|
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
package com.couchbase.cblite.android.cbpushsync; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.View; import android.widget.ProgressBar; import android.widget.TextView; import com.couchbase.lite.Database; import com.couchbase.lite.Document; import com.couchbase.lite.DocumentChange; import com.couchbase.lite.replicator.Replication; import com.couchbase.lite.replicator.ReplicationState; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; public class MainActivity extends AppCompatActivity { private static String TAG = MainActivity.class.getSimpleName(); private static final ObjectMapper mapper = new ObjectMapper(); private CBLHelper cblHelper = CBLHelper.getInstance(); private TextView documentView; private ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); documentView = (TextView) findViewById(R.id.documentView); progressBar = (ProgressBar) findViewById(R.id.progressBar); cblHelper.initialize( new Database.ChangeListener() { @Override public void changed(Database.ChangeEvent event) { Log.i(TAG, "Database change called: count - " + event.getChanges().size()); if (!event.isExternal()) { return; } String json = ""; for (final DocumentChange change : event.getChanges()) { if (!change.isCurrentRevision()) { continue; } Document changedDoc = cblHelper.getExistingDocument(change.getDocumentId()); if (changedDoc == null) continue; try { json += mapper.writeValueAsString(changedDoc.getProperties()); } catch (IOException e) { e.printStackTrace(); } } final String text = json; runOnUiThread(new Runnable() { @Override public void run() { documentView.setText(text); } }); } }, new Replication.ChangeListener() { @Override public void changed(Replication.ChangeEvent event) { Log.i(TAG, "Replication change called: " + event.toString()); if (event.getError() != null) return; if (event.getTransition() == null) return; ReplicationState dest = event.getTransition().getDestination(); final int replicationProgress = ((dest == ReplicationState.STOPPING || dest == ReplicationState.STOPPED) ? View.INVISIBLE : View.VISIBLE); runOnUiThread(new Runnable() { @Override public void run() { progressBar.setVisibility(replicationProgress); } }); } } ); } } |
여기 코드의 핵심은 데이터베이스용과 복제용 두 개의 변경 리스너로 구성되어 있습니다. 각 리스너 인터페이스는 하나의 메서드를 정의합니다. 변경됨.
문서 변경 리스너를 사용하면 실제 문서 업데이트를 추적할 수 있습니다. 복제는 한 번에 두 개 이상의 문서를 변경할 수 있습니다. 변경 이벤트는 문서 ID 목록을 반환합니다. 문서 ID를 반복하여 각 문서를 직접 검색하고 JSON 내용을 문자열로 변환한 다음 표시할 텍스트에 추가합니다. 변경 리스너는 백그라운드 스레드에서 호출됩니다. 마무리하려면 메인 스레드에서 UI 요소를 조작해야 합니다. 이 작업은 런온유아이스레드 활동의 메서드입니다.
다른 리스너를 사용하면 복제 상태에 따라 바쁘게 대기 중인 스피너(무기한 진행률 표시줄)를 표시할 수 있습니다. 복제 상태 모니터링에 대해 자세히 알아보세요. 여기.
데이터베이스 도우미 클래스
저는 종종 데이터베이스 함수를 헬퍼 클래스로 래핑합니다. 헬퍼의 인스턴스가 하나만 필요하기 때문에 싱글톤 패턴을 사용합니다. UA와 마찬가지로 메인 애플리케이션이 시작되기 전에 헬퍼를 사용할 수 있기를 원합니다. 저는 콘텐츠 공급자에 코드를 넣는 동일한 기술을 사용합니다.
다음은 CBLHelper.java의 전체 목록입니다.
|
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
package com.couchbase.cblite.android.cbpushsync; import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Log; import com.couchbase.lite.CouchbaseLiteException; import com.couchbase.lite.Database; import com.couchbase.lite.Document; import com.couchbase.lite.Manager; import com.couchbase.lite.android.AndroidContext; import com.couchbase.lite.replicator.Replication; import java.io.IOException; import java.net.URL; public class CBLHelper extends ContentProvider { public static final String TAG = "Push Sync"; private static String DB = "db"; //private static String syncGateway = "https://localhost:4984"; private static String syncGateway = "https://10.0.2.2:4984"; private static URL syncGatewayURL; private Manager manager; private Database database; private Replication puller; private Database.ChangeListener databaseChangeListener; private Replication.ChangeListener replicationChangeListener; private static CBLHelper instance; public static CBLHelper getInstance() { return instance; } @Override public boolean onCreate() { instance = this; enableLogging(); try { syncGatewayURL = new URL(syncGateway + "/" + DB); manager = new Manager(new AndroidContext(getContext()), Manager.DEFAULT_OPTIONS); } catch (IOException ex) { ex.printStackTrace(); } return true; } public void closeDatabase() { database.close(); } public void startReplication() { puller.start(); } public void stopReplication() { puller.stop(); } public void reset() { stopReplication(); try { database.delete(); } catch (CouchbaseLiteException ex) { ex.printStackTrace(); } initialize(databaseChangeListener, replicationChangeListener); } public void initialize(Database.ChangeListener dbl, Replication.ChangeListener rl) { try { database = manager.getDatabase(DB); } catch (CouchbaseLiteException ex) { ex.printStackTrace(); } database.addChangeListener(dbl); databaseChangeListener = dbl; puller = database.createPullReplication(syncGatewayURL); puller.addChangeListener(rl); replicationChangeListener = rl; } public Document getExistingDocument(String documentID) { return database.getExistingDocument(documentID); } // Logging private void enableLogging() { Manager.enableLogging(TAG, Log.VERBOSE); Manager.enableLogging(com.couchbase.lite.util.Log.TAG, Log.VERBOSE); Manager.enableLogging(com.couchbase.lite.util.Log.TAG_SYNC_ASYNC_TASK, Log.VERBOSE); Manager.enableLogging(com.couchbase.lite.util.Log.TAG_SYNC, Log.VERBOSE); Manager.enableLogging(com.couchbase.lite.util.Log.TAG_QUERY, Log.VERBOSE); Manager.enableLogging(com.couchbase.lite.util.Log.TAG_VIEW, Log.VERBOSE); Manager.enableLogging(com.couchbase.lite.util.Log.TAG_DATABASE, Log.VERBOSE); } // Helper function to dispatch on UI thread private void runOnUiThread(Runnable runnable) { new Handler(Looper.getMainLooper()).post(runnable); } // Required overrides @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { return null; } @Nullable @Override public String getType(@NonNull Uri uri) { return null; } @Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { return null; } @Override public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } @Override public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } } |
이 클래스는 얇은 래퍼를 형성하는 것을 볼 수 있습니다. 클래스의 인스턴스는 onCreate 싱글톤이 됩니다. 로깅 활성화 및 데이터베이스 관리자 생성과 같은 다른 기본 설정도 수행합니다. 저는 초기화 메서드를 사용하여 실제로 데이터베이스를 열고, 풀 복제를 준비하고, 두 개의 변경 리스너를 연결합니다. 이 메서드는 Activity 클래스에서 호출된다는 점을 기억하세요. (참고: 각 유형에 대해 변경 리스너를 두 개 이상 가질 수 있습니다. 카우치베이스는 최신 리스너뿐만 아니라 추가된 모든 리스너의 목록을 유지합니다.) 다른 데이터베이스 메서드는 간단한 단축키만 제공합니다.
콘텐츠 공급자는 구현해야 하는 몇 가지 필수 메소드가 있습니다. 이러한 메소드에 대한 스텁을 제공해야 하며, 마지막 다섯 가지 메소드에서 볼 수 있습니다.
안드로이드 매니페스트
마지막으로, 이것이 어떻게 서로 연결되고 다양한 부분이 노출되는지 보여드리기 위해 프로젝트의 안드로이드 매니페스트 파일을 포함했습니다.
다음은 AndroidManifest.xml의 전체 목록입니다.
|
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 32 33 34 35 36 37 38 39 40 41 42 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="https://schemas.android.com/apk/res/android" package="com.couchbase.cblite.android.cbpushsync"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <meta-data android:name="com.urbanairship.autopilot" android:value="com.couchbase.cblite.android.cbpushsync.CBAutoPilot"/> <activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".CBAirshipReceiver" android:exported="false"> <intent-filter> <action android:name="com.urbanairship.push.CHANNEL_UPDATED" /> <action android:name="com.urbanairship.push.OPENED" /> <action android:name="com.urbanairship.push.RECEIVED" /> <action android:name="com.urbanairship.push.DISMISSED" /> <category android:name="${applicationId}" /> </intent-filter> </receiver> <provider android:authorities="${applicationId}.dbhelper" android:exported="false" android:enabled="true" android:name=".CBLHelper" /> </application> </manifest> |
UA 라이브러리는 자체 매니페스트 파일과 함께 제공됩니다. 안드로이드 빌드 시스템은 모든 다른 매니페스트 파일을 통합하여 최종 파일을 생성합니다. UA 라이브러리 매니페스트 파일에는 라이브러리를 부트스트랩하는 콘텐츠 공급자에 대한 항목이 있습니다.
동기화 게이트웨이
앱을 사용해보기 위해 저는 동기화 게이트웨이와 내장된 왈러스 데이터베이스를 사용했습니다. Walrus는 인메모리 데이터베이스 일반적으로 테스트용으로만 사용됩니다. 이렇게 하면 백엔드 카우치베이스 서버 인스턴스를 설정하는 수고를 덜 수 있습니다.
다음은 동기화 게이트웨이 구성 파일의 전체 목록입니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "log": ["HTTP+"], "adminInterface": "127.0.0.1:4985", "interface": "127.0.0.1:4984", "CORS": { "origin":["*"], "loginorigin":["*"], "headers":["Content-Type"], "maxAge": 1728000 }, "databases": { "db": { "server": "walrus:", "users": { "GUEST": {"disabled": false, "admin_channels": ["*"] } } } } } |
이렇게 하면 동기화 게이트웨이가 동기화 게이트웨이의 localhost 인터페이스에 연결하고, 모든 교차 출처 요청을 수락하고, 모든 채널에 액세스할 수 있는 특수 GUEST를 활성화합니다. 모든 것이 제대로 작동하는지 확인하기 위해 시작하기에 매우 좋은 범용 구성입니다.
Android 앱에서 동기화 게이트웨이의 IP 주소로 10.0.2.2를 사용하는 것을 보셨을 것입니다. Android Studio와 함께 제공되는 표준 에뮬레이터는 이 주소를 호스팅 머신의 localhost. 다른 에뮬레이터(Genymotion도 인기 있는 에뮬레이터 중 하나)를 사용하는 경우, 사용할 IP 주소가 다르므로 반드시 찾아보세요.
개발 머신에서 동기화 게이트웨이를 설정하는 방법이나 명령줄에서 작업하는 방법에 대해 자세히 알아보려면 다음을 참조하세요. 블로그 시리즈.
테스트
모든 것을 테스트하고 블로그의 시작 부분에 표시된 애니메이션을 녹화하기 위해 Android 에뮬레이터와 동기화 게이트웨이를 한 컴퓨터에서 모두 실행합니다. 그런 다음 REST API를 통해 UA에 푸시 알림을 게시합니다.
흥미로운 것을 준비하기 위해 먼저 동기화 게이트웨이에 문서를 추가합니다. 다음은 이를 위한 셸 명령어입니다.
|
1 |
$ curl -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{ "test" : "UA", "channels": "public" }' https://localhost:4984/db/doc |
(자세히 알아보기 여기).
동기화 게이트웨이의 데이터베이스에 새 문서가 있고 앱이 실행 중이므로 이제 남은 것은 풀 복제를 트리거하여 작업을 확인하는 것뿐입니다.
다음은 curl 명령을 사용하여 "시작" 신호를 보냅니다. 알림의 "알림" 부분에서 값을 가져와 작업을 트리거하는 것을 기억하세요.
|
1 |
$ curl https://go.urbanairship.com/api/push -u 'appKey:appMasterSecret' -X POST -H 'Content-Type: application/json' -H 'Accept: application/vnd.urbanairship+json; version=3;' -d '{ "audience": { "android_channel": "3110bc81-1c7b-4ef8-a7a3-7c56aab19f08" }, "notification" : { "alert": "start" }, "device_types": "all" }' |
위에 애플리케이션 키와 애플리케이션 마스터 비밀번호를 제공해야 합니다. 또한 로그 파일을 확인하여 "android_channel"에 입력할 채널 값을 확인해야 합니다. 이는 상당히 정기적으로 변경됩니다. 안타깝게도 UA는 이를 표시하기 위해 많은 작업을 수행하지 않습니다. 푸시 알림이 아무런 효과가 없는 것 같다면 채널 값을 확인하세요.
UA에 게시하면 다음과 같은 응답이 표시됩니다.
|
1 |
{"ok":true,"operation_id":"2a6c0edf-e5d0-4b4d-b762-ad5c4478c291","push_ids":["1951019a-2b7f-4f1b-8888-e87047a1feec"],"message_ids":[],"content_urls":[]} |
마지막으로 빈 데이터베이스로 재설정하여 다시 시도하려면 이 글을 게시하면 됩니다.
|
1 |
$ curl https://go.urbanairship.com/api/push -u 'appKey:appMasterSecret' -X POST -H 'Content-Type: application/json' -H 'Accept: application/vnd.urbanairship+json; version=3;' -d '{ "audience": { "android_channel": "3110bc81-1c7b-4ef8-a7a3-7c56aab19f08" }, "notification" : { "alert": "reset" }, "device_types": "all" }' |
결론
여기까지 푸시 알림을 기반으로 복제를 수행할 수 있도록 Android 앱을 준비했습니다. 다음 사항을 꼭 확인하세요. 이 게시물 동기화 게이트웨이 변경 피드 모니터링에 대해 설명합니다.
포스트 스크립트
카우치베이스 및 동기화 게이트웨이 다운로드 여기. 를 참조하십시오. 문서 를 참조하여 프로젝트에 Couchbase Lite를 추가하는 방법을 확인하세요.
더 많은 리소스를 확인하세요. 개발자 포털 트위터에서 팔로우하세요 카우치베이스 개발.
질문에 대한 답변을 게시할 수 있습니다. 포럼. 그리고 다음에도 적극적으로 참여합니다. 스택 오버플로.
질문, 의견, 보고 싶은 주제 등이 있으면 트위터에서 저에게 연락해 주세요. 호드그릴리.
[...] 참고: 이 블로그 게시물에서 도시 비행선 설정에 대한 자세한 내용을 확인할 수 있습니다. [...]