@@ -11,15 +11,21 @@ The code below compiles, but may not execute successfully. Please join
11
11
our [ mailing list] ( /community/mailing-lists.html ) for updates.
12
12
{{/ helpers.warning }}
13
13
14
+ {{# helpers.hidden }}
15
+ <!-- @setupEnvironment @test -->
16
+ ```
17
+ export PROJECT_DIR=$(mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX")
18
+ cp -r $JIRI_ROOT/website/tools/android_project_stubs/example/* $PROJECT_DIR
19
+ ```
20
+ {{/ helpers.hidden }}
21
+
14
22
# Introduction
15
23
16
24
In this quick tutorial, we will build a * Dice Roller* Android app where
17
25
one can simply generate a random number between 1-6 and have it sync
18
26
across multiple devices peer-to-peer, even with Wi-Fi turned off!
19
27
20
- <div class =" rows " >
21
- <img style =" width :250px " src =" /images/syncbase-dice-device-1.gif " >
22
- </div >
28
+ <img style =" width :250px " src =" /images/syncbase-dice-device-1.gif " >
23
29
24
30
# Setup
25
31
This tutorial uses Android Studio, but feel free to use your IDE of choice.
@@ -33,10 +39,13 @@ template.
33
39
## Install Syncbase
34
40
Add the following to your ` build.gradle ` file.
35
41
42
+ <!-- @addSyncbaseDependency @test -->
36
43
```
44
+ cat - <<EOF >> $PROJECT_DIR/app/build.gradle
37
45
dependencies {
38
- compile 'io.v:vanadium-android:2 .1.3+ '
46
+ compile 'io.v:syncbase:0 .1.4 '
39
47
}
48
+ EOF
40
49
```
41
50
42
51
## Setup Cloud Syncbase
@@ -55,9 +64,11 @@ used without a cloud Syncbase very soon.
55
64
## Initialize Syncbase
56
65
57
66
** MainActivity.java**
67
+ <!-- @generateMainActivity @test -->
58
68
```
69
+ cat - <<EOF | sed 's/{{.*}}//' > $PROJECT_DIR/app/src/main/java/io/v/syncbase/example/MainActivity.java
59
70
{{# helpers.codedim }}
60
- package io.v.myfirstsyncbaseapp ;
71
+ package io.v.syncbase.example ;
61
72
62
73
import android.support.v7.app.AppCompatActivity;
63
74
@@ -74,23 +85,31 @@ public class MainActivity extends AppCompatActivity {
74
85
75
86
super.onCreate(savedInstanceState);
76
87
{{/ helpers.codedim }}
77
- User currUser = Users.loginWithDefaultAccount();
78
88
79
- DatabaseOptions dbOpt = new DatabaseOptions();
80
- dbOpt.cloudSyncbaseAddress = "<Your Cloud Syncbase Address>"
81
- dbOpt.cloudSyncbaseBlessing = "<Your Cloud Syncbase Blessing>"
89
+ Syncbase. DatabaseOptions options = new Syncbase. DatabaseOptions();
90
+ // dbOpt.cloudSyncbaseAddress = "<Your Cloud Syncbase Address>";
91
+ // dbOpt.cloudSyncbaseBlessing = "<Your Cloud Syncbase Blessing>";
82
92
83
- Database db = Syncbase.getDatabase();
93
+ Syncbase.database(new Syncbase.DatabaseCallback() {
94
+ @Override
95
+ public void onSuccess(final Database db) {
96
+
97
+ // Use database to interact with Syncbase.
98
+
99
+ Log.i("info", "Syncbase is ready");
100
+ }
101
+ }, options);
84
102
85
- Log.i("info", "Welcome: " + currUser.getEmail());
86
103
{{# helpers.codedim }}
87
104
setContentView(R.layout.activity_main);
88
105
}
89
106
}
90
107
{{/ helpers.codedim }}
108
+ EOF
91
109
```
110
+
92
111
Now, let's run the app to make sure login and Syncbase initialization are working.
93
- After running, you should see ` Welcome <email> ` in logcat under Android Monitor
112
+ After running, you should see ` Syncbase is ready ` in logcat under Android Monitor
94
113
or in the console.
95
114
96
115
# UI Code
@@ -99,9 +118,11 @@ result and a `Button`s to roll the dice.
99
118
Here is the UI code
100
119
101
120
** activity_main.xml**
121
+
122
+ <!-- @generateMainActivityXML @test -->
102
123
```
103
- {{# helpers.codedim }}
104
- <?xml version="1.0" encoding="utf-8"?>
124
+ cat - <<EOF | sed 's/{{.*}}//' > $PROJECT_DIR/app/src/main/res/layout/activity_main.xml
125
+ {{# helpers.codedim }} <?xml version="1.0" encoding="utf-8"?>
105
126
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
106
127
xmlns:tools="http://schemas.android.com/tools"
107
128
android:layout_width="match_parent"
@@ -110,7 +131,7 @@ Here is the UI code
110
131
android:paddingLeft="@dimen/activity_horizontal_margin"
111
132
android:paddingRight="@dimen/activity_horizontal_margin"
112
133
android:paddingTop="@dimen/activity_vertical_margin"
113
- tools:context="io.v.myfirstsyncbaseapp .MainActivity">
134
+ tools:context="io.v.syncbase.example .MainActivity">
114
135
{{/ helpers.codedim }}
115
136
<TextView
116
137
{{# helpers.codedim }}
@@ -139,11 +160,20 @@ Here is the UI code
139
160
android:layout_centerHorizontal="true" />
140
161
</RelativeLayout>
141
162
{{/ helpers.codedim }}
163
+ EOF
142
164
```
165
+
143
166
Running the project at this point should result in the following UI:
144
167
145
168
<img style =" width :250px " src =" /images/syncbase-dice-1.png " alt =" Screenshot of the Dice Roll app " >
146
169
170
+ {{# helpers.hidden }}
171
+ <!-- @firstStepCompile_mayTakeMinutes @test -->
172
+ ```
173
+ cd $PROJECT_DIR && ./gradlew assembleRelease
174
+ ```
175
+ {{/ helpers.hidden }}
176
+
147
177
# Data Binding
148
178
The data model for this app is simple. We just need a single collection (` dice ` )
149
179
and a single key/value pair (` 'result' ` , ` int ` ) to store the result of the dice
@@ -162,9 +192,11 @@ from a remote device.
162
192
163
193
Now let's hook up this model to our code.
164
194
195
+ <!-- @updateMainActivity @test -->
165
196
```
197
+ cat - <<EOF | sed 's/{{.*}}//' > $PROJECT_DIR/app/src/main/java/io/v/syncbase/example/MainActivity.java
166
198
{{# helpers.codedim }}
167
- package io.v.myfirstsyncbaseapp ;
199
+ package io.v.syncbase.example ;
168
200
169
201
import android.support.v7.app.AppCompatActivity;
170
202
import android.os.Bundle;
@@ -182,70 +214,77 @@ public class MainActivity extends AppCompatActivity {
182
214
183
215
@Override
184
216
protected void onCreate(Bundle savedInstanceState) {
185
- super.onCreate(savedInstanceState);
186
-
187
- User currUser = Users.loginWithDefaultAccount();
188
-
189
- DatabaseOptions dbOpt = new DatabaseOptions();
190
- dbOpt.cloudSyncbaseAddress = "<Your Cloud Syncbase Address>"
191
- dbOpt.cloudSyncbaseBlessing = "<Your Cloud Syncbase Blessing>"
192
-
193
- Database db = Syncbase.getDatabase();
194
-
195
- Log.i("info", "Welcome: " + currUser.getEmail());
196
217
197
- setContentView(R.layout.activity_main);
198
-
199
- {{/ helpers.codedim }}
200
-
201
- // On dice roll, put a new random number under key "result"
202
- // in the "dice" collection.
203
- final Button button = (Button) findViewById(R.id.buttonRoll);
204
- button.setOnClickListener(new View.OnClickListener() {
205
- public void onClick(View v) {
206
- int randomNumber = new Random().nextInt(6) + 1;
207
-
208
- Collection diceCollection = db.collection("dice");
209
- diceCollection.put("result", randomNumber);
210
- }
211
- });
212
-
213
- // Watch the database and update the UI whenever a new value
214
- // is encountered.
215
- db.removeWatchChangeHandler(new Database.WatchChangeHandler() {
216
-
217
- void onInitialState(Iterator<WatchChange> values) {
218
- // onInitialState is called with any existing data in Syncbase.
219
- // Since we only have a single collection, single key/value,
220
- // there can only be 0 or 1 values.
221
- if (values.hasNext()) {
222
- int result = (int) values.next().getValue(int.class);
223
- updateResult(result);
224
- }
225
- }
218
+ super.onCreate(savedInstanceState);
226
219
227
- void onChangeBatch(Iterator<WatchChange> changes) {
228
- // onChangeBatch is called with any updates to the data.
229
- // Since we only have a single collection, single key/value.
230
- // there can only be 1 WatchChange whenever the value is mutated
231
- // and the type of change would always be `put` in our case.
232
- int result = (int) changes.next().getValue(int.class);
233
- updateResult(result);
220
+ Syncbase.DatabaseOptions options = new Syncbase.DatabaseOptions();
221
+ // dbOpt.cloudSyncbaseAddress = "<Your Cloud Syncbase Address>";
222
+ // dbOpt.cloudSyncbaseBlessing = "<Your Cloud Syncbase Blessing>";
223
+
224
+ Syncbase.database(new Syncbase.DatabaseCallback() {
225
+ @Override
226
+ public void onSuccess(final Database db) {
227
+
228
+ // Use database to interact with Syncbase.
229
+
230
+ Log.i("info", "Syncbase is ready");
231
+ {{/ helpers.codedim }}
232
+
233
+ // On dice roll, put a new random number under key "result"
234
+ // in the "dice" collection.
235
+ final Button button = (Button) findViewById(R.id.buttonRoll);
236
+ button.setOnClickListener(new View.OnClickListener() {
237
+ public void onClick(View v) {
238
+ int randomNumber = new Random().nextInt(6) + 1;
239
+
240
+ Collection diceCollection = db.collection("dice");
241
+ diceCollection.put("result", randomNumber);
242
+ }
243
+ });
244
+
245
+ // Watch the database and update the UI whenever a new value
246
+ // is encountered.
247
+ db.addWatchChangeHandler(new Database.WatchChangeHandler() {
248
+ @Override
249
+ public void onInitialState(Iterator<WatchChange> values) {
250
+ // onInitialState is called with any existing data in Syncbase.
251
+ // Since we only have a single collection, single key/value,
252
+ // there can only be 0 or 1 values.
253
+ if (values.hasNext()) {
254
+ int result = (int) values.next().getValue();
255
+ updateResult(result);
256
+ }
257
+ }
258
+
259
+ @Override
260
+ public void onChangeBatch(Iterator<WatchChange> changes) {
261
+ // onChangeBatch is called with any updates to the data.
262
+ // Since we only have a single collection, single key/value.
263
+ // there can only be 1 WatchChange whenever the value is mutated
264
+ // and the type of change would always be `put` in our case.
265
+ int result = (int) changes.next().getValue();
266
+ updateResult(result);
267
+ }
268
+
269
+ @Override
270
+ public void onError(Throwable e) {
271
+ // Something went wrong. Watch is no longer active.
272
+ }
273
+ }, new Database.AddWatchChangeHandlerOptions());
274
+ {{# helpers.codedim }}
234
275
}
276
+ }, new Syncbase.DatabaseOptions());
235
277
236
- void onError(Exception e) {
237
- // Something went wrong. Watch is no longer active.
238
- }
239
- });
278
+ setContentView(R.layout.activity_main);
240
279
}
241
280
281
+ {{/ helpers.codedim }}
242
282
private void updateResult(int newValue) {
243
283
final TextView result = (TextView) findViewById(R.id.textViewResult);
244
284
result.setText(String.valueOf(newValue));
245
285
}
246
- {{# helpers.codedim }}
247
286
}
248
- {{/ helpers.codedim }}
287
+ EOF
249
288
```
250
289
251
290
# Running The App
@@ -271,9 +310,14 @@ After running the application on 2 or more devices with Internet connectivity,
271
310
ensure Bluetooth is enabled on both devices and turn off Wi-Fi, the dice rolls
272
311
should still sync between the devices just fine!
273
312
274
- <div class =" rows " >
275
- <img style =" width :250px " src =" /images/syncbase-dice-device-1.gif " >
276
- </div >
313
+ <img style =" width :250px " src =" /images/syncbase-dice-device-1.gif " >
314
+
315
+ {{# helpers.hidden }}
316
+ <!-- @secondStepCompile_mayTakeMinutes @test -->
317
+ ```
318
+ cd $PROJECT_DIR && ./gradlew assembleRelease
319
+ ```
320
+ {{/ helpers.hidden }}
277
321
278
322
# Want to dive deeper?
279
323
Checkout the [ Tutorial] to build a full-fledged Todo app and learn more Syncbase
0 commit comments