diff --git a/Dockerfile b/Dockerfile index ddcc4b4c7e..2b66ca9912 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,16 +46,23 @@ RUN cd /opt && \ rm -f android-tools-linux.zip # Grab what's needed in the SDK -RUN mkdir "${ANDROID_HOME}/licenses" && \ - echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > "${ANDROID_HOME}/licenses/android-sdk-license" RUN sdkmanager --update -# Accept all licenses -RUN yes y | sdkmanager --licenses -RUN sdkmanager 'platform-tools' -RUN sdkmanager 'build-tools;28.0.3' -RUN sdkmanager 'extras;android;m2repository' -RUN sdkmanager 'platforms;android-27' -RUN sdkmanager 'cmake;3.6.4111459' + +# Accept licenses before installing components, no need to echo y for each component +# License is valid for all the standard components in versions installed from this file +# Non-standard components: MIPS system images, preview versions, GDK (Google Glass) and Android Google TV require separate licenses, not accepted there +RUN yes | sdkmanager --licenses + +# SDKs +# Please keep these in descending order! +# The `yes` is for accepting all non-standard tool licenses. +# Please keep all sections in descending order! +RUN yes | sdkmanager \ + 'platform-tools' \ + 'build-tools;28.0.3' \ + 'extras;android;m2repository' \ + 'platforms;android-27' \ + 'cmake;3.6.4111459' # Install the NDK RUN mkdir /opt/android-ndk-tmp && \ diff --git a/examples/objectServerExample/README.md b/examples/objectServerExample/README.md index d3c8558940..f6630def1b 100644 --- a/examples/objectServerExample/README.md +++ b/examples/objectServerExample/README.md @@ -10,11 +10,15 @@ injected into the build configuration. To use a different ObjectServer, simply put the server IP Address into the `build.gradle`, as indicated in the comments, on the lines like this: - buildConfigField "String", "OBJECT_SERVER_IP", "\"${host}\"" + def rosUrl = "" For instance: - buildConfigField "String", "OBJECT_SERVER_IP", "192.168.0.1" + def rosUrl = "https://myinstance.us1.cloud.realm.io" + +or: + + def rosUrl = "http://127.0.0.1:9080" To read more about the Realm Object Server and how to deploy it, see https://realm.io/news/introducing-realm-mobile-platform/ diff --git a/examples/objectServerExample/build.gradle b/examples/objectServerExample/build.gradle index ff0d0d5ccd..44535c85a7 100644 --- a/examples/objectServerExample/build.gradle +++ b/examples/objectServerExample/build.gradle @@ -1,4 +1,19 @@ +buildscript { + ext.kotlin_version = '1.3.20' + repositories { + google() + jcenter() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + apply plugin: 'com.android.application' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' apply plugin: 'realm-android' android { @@ -13,6 +28,10 @@ android { versionName "1.0" } + dataBinding { + enabled = true + } + buildTypes { // Go to https://cloud.realm.io and copy the URL to your instance. Insert it below. // It will look something like "https://test.us1.cloud.realm.io" @@ -45,6 +64,5 @@ dependencies { implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support:design:27.1.1' implementation 'me.zhanghai.android.materialprogressbar:library:1.3.0' - implementation 'com.jakewharton:butterknife:8.8.1'//TODO:Can be refactored with Native Android Data Binding - annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'//TODO:Can be refactored with Native Android Data Binding + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" } diff --git a/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/CounterActivity.java b/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/CounterActivity.java deleted file mode 100644 index 26d129cd2d..0000000000 --- a/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/CounterActivity.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2016 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.realm.examples.objectserver; - -import android.content.Intent; -import android.graphics.PorterDuff; -import android.os.Bundle; -import android.support.annotation.ColorRes; -import android.support.v7.app.AppCompatActivity; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.TextView; - -import java.util.Locale; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.annotation.Nonnull; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import io.realm.OrderedCollectionChangeSet; -import io.realm.OrderedRealmCollectionChangeListener; -import io.realm.Progress; -import io.realm.ProgressListener; -import io.realm.ProgressMode; -import io.realm.Realm; -import io.realm.RealmResults; -import io.realm.SyncConfiguration; -import io.realm.SyncManager; -import io.realm.SyncSession; -import io.realm.SyncUser; -import io.realm.examples.objectserver.model.CRDTCounter; -import me.zhanghai.android.materialprogressbar.MaterialProgressBar; - -public class CounterActivity extends AppCompatActivity { - - private final ProgressListener downloadListener = new ProgressListener() { - @Override - public void onChange(@Nonnull Progress progress) { - downloadingChanges.set(!progress.isTransferComplete()); - runOnUiThread(updateProgressBar); - } - }; - private final ProgressListener uploadListener = new ProgressListener() { - @Override - public void onChange(@Nonnull Progress progress) { - uploadingChanges.set(!progress.isTransferComplete()); - runOnUiThread(updateProgressBar); - } - }; - private final Runnable updateProgressBar = new Runnable() { - @Override - public void run() { - updateProgressBar(downloadingChanges.get(), uploadingChanges.get()); - } - }; - - private final AtomicBoolean downloadingChanges = new AtomicBoolean(false); - private final AtomicBoolean uploadingChanges = new AtomicBoolean(false); - - private Realm realm; - private SyncSession session; - private SyncUser user; - - @BindView(R.id.text_counter) TextView counterView; - @BindView(R.id.progressbar) MaterialProgressBar progressBar; - private RealmResults counters; // Keep strong reference to counter to keep change listeners alive. - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_counter); - ButterKnife.bind(this); - } - - @Override - protected void onStart() { - super.onStart(); - user = getLoggedInUser(); - if (user == null) { return; } - - // Create a RealmConfiguration for our user - SyncConfiguration config = user.createConfiguration(BuildConfig.REALM_URL) - .initialData(new Realm.Transaction() { - @Override - public void execute(@Nonnull Realm realm) { - realm.createObject(CRDTCounter.class, user.getIdentity()); - } - }) - .build(); - - // This will automatically sync all changes in the background for as long as the Realm is open - realm = Realm.getInstance(config); - - counterView.setText("-"); - counters = realm.where(CRDTCounter.class).equalTo("name", user.getIdentity()).findAllAsync(); - counters.addChangeListener(new OrderedRealmCollectionChangeListener>() { - @Override - public void onChange(RealmResults counters, OrderedCollectionChangeSet changeSet) { - if (counters.isValid() && !counters.isEmpty()) { - CRDTCounter counter = counters.first(); - counterView.setText(String.format(Locale.US, "%d", counter.getCount())); - } else { - counterView.setText("-"); - } - } - }); - - // Setup progress listeners for indeterminate progress bars - session = SyncManager.getSession(config); - session.addDownloadProgressListener(ProgressMode.INDEFINITELY, downloadListener); - session.addUploadProgressListener(ProgressMode.INDEFINITELY, uploadListener); - } - - @Override - protected void onStop() { - super.onStop(); - if (session != null) { - session.removeProgressListener(downloadListener); - session.removeProgressListener(uploadListener); - session = null; - } - closeRealm(); - user = null; - counters = null; - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.menu_counter, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch(item.getItemId()) { - case R.id.action_logout: - closeRealm(); - user.logOut(); - user = getLoggedInUser(); - return true; - - default: - return super.onOptionsItemSelected(item); - } - } - - @OnClick(R.id.upper) - public void incrementCounter() { - adjustCounter(1); - } - - @OnClick(R.id.lower) - public void decrementCounter() { - adjustCounter(-1); - } - - private void updateProgressBar(boolean downloading, boolean uploading) { - @ColorRes int color = android.R.color.black; - int visibility = View.VISIBLE; - if (downloading && uploading) { - color = R.color.progress_both; - } else if (downloading) { - color = R.color.progress_download; - } else if (uploading) { - color = R.color.progress_upload; - } else { - visibility = View.GONE; - } - progressBar.getIndeterminateDrawable().setColorFilter(getResources().getColor(color), PorterDuff.Mode.SRC_IN); - progressBar.setVisibility(visibility); - } - - private void adjustCounter(final int adjustment) { - // A synchronized Realm can get written to at any point in time, so doing synchronous writes on the UI - // thread is HIGHLY discouraged as it might block longer than intended. Use only async transactions. - realm.executeTransactionAsync(new Realm.Transaction() { - @Override - public void execute(@Nonnull Realm realm) { - CRDTCounter counter = realm.where(CRDTCounter.class).findFirst(); - if (counter != null) { - counter.incrementCounter(adjustment); - } - } - }); - } - - private SyncUser getLoggedInUser() { - SyncUser user = null; - - try { user = SyncUser.current(); } - catch (IllegalStateException ignore) { } - - if (user == null) { - startActivity(new Intent(this, LoginActivity.class)); - } - - return user; - } - - private void closeRealm() { - if (realm != null && !realm.isClosed()) { - realm.close(); - } - } -} diff --git a/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/CounterActivity.kt b/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/CounterActivity.kt new file mode 100644 index 0000000000..bc069f88c6 --- /dev/null +++ b/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/CounterActivity.kt @@ -0,0 +1,177 @@ +/* + * Copyright 2019 Realm Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.realm.examples.objectserver + +import android.content.Intent +import android.databinding.DataBindingUtil +import android.graphics.PorterDuff +import android.os.Bundle +import android.support.annotation.ColorRes +import android.support.v7.app.AppCompatActivity +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.widget.TextView +import io.realm.* +import io.realm.examples.objectserver.databinding.ActivityCounterBinding +import io.realm.examples.objectserver.model.CRDTCounter +import io.realm.kotlin.createObject +import io.realm.kotlin.syncSession +import io.realm.kotlin.where +import io.realm.log.RealmLog +import me.zhanghai.android.materialprogressbar.MaterialProgressBar +import java.util.* +import java.util.concurrent.atomic.AtomicBoolean + +class CounterActivity : AppCompatActivity() { + + private lateinit var binding: ActivityCounterBinding + + private val downloadListener = ProgressListener { progress -> + downloadingChanges.set(!progress.isTransferComplete) + runOnUiThread(updateProgressBar) + } + private val uploadListener = ProgressListener { progress -> + uploadingChanges.set(!progress.isTransferComplete) + runOnUiThread(updateProgressBar) + } + private val updateProgressBar = Runnable { updateProgressBar(downloadingChanges.get(), uploadingChanges.get()) } + + private val downloadingChanges = AtomicBoolean(false) + private val uploadingChanges = AtomicBoolean(false) + + private lateinit var realm: Realm + private lateinit var session: SyncSession + private var user: SyncUser? = null + + private lateinit var counterView: TextView + private lateinit var progressBar: MaterialProgressBar + private lateinit var counters: RealmResults // Keep strong reference to counter to keep change listeners alive. + + private val loggedInUser: SyncUser? + get() { + var user: SyncUser? = null + + try { + user = SyncUser.current() + } catch (e: IllegalStateException) { + RealmLog.warn(e); + } + + if (user == null) { + startActivity(Intent(this, LoginActivity::class.java)) + } + + return user + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = DataBindingUtil.setContentView(this, R.layout.activity_counter) + counterView = binding.textCounter + progressBar = binding.progressbar + binding.upper.setOnClickListener { adjustCounter(1) } + binding.lower.setOnClickListener { adjustCounter(-1) } + } + + override fun onStart() { + super.onStart() + user = loggedInUser + val user = user + if (user != null) { + // Create a RealmConfiguration for our user + val config = user.createConfiguration(BuildConfig.REALM_URL) + .initialData { realm -> realm.createObject(user.identity) } + .build() + + // This will automatically sync all changes in the background for as long as the Realm is open + realm = Realm.getInstance(config) + + counterView.text = "-" + counters = realm.where().equalTo("name", user.identity).findAllAsync() + counters.addChangeListener { counters, _ -> + if (counters.isValid && !counters.isEmpty()) { + val counter = counters.first() + counterView.text = String.format(Locale.US, "%d", counter!!.count) + } else { + counterView.text = "-" + } + } + + // Setup progress listeners for indeterminate progress bars + session = realm.syncSession + session.run { + addDownloadProgressListener(ProgressMode.INDEFINITELY, downloadListener) + addUploadProgressListener(ProgressMode.INDEFINITELY, uploadListener) + } + } + } + + override fun onStop() { + super.onStop() + user?.run { + session.run { + removeProgressListener(downloadListener) + removeProgressListener(uploadListener) + } + realm.close() + } + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.menu_counter, menu) + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.action_logout -> { + realm.close() + val user = user + if (user != null) { + user.logOut() + this.user = loggedInUser + } + true + } + + else -> super.onOptionsItemSelected(item) + } + } + + private fun updateProgressBar(downloading: Boolean, uploading: Boolean) { + @ColorRes val color = when { + downloading && uploading -> R.color.progress_both + downloading -> R.color.progress_download + uploading -> R.color.progress_upload + else -> android.R.color.black + } + progressBar.indeterminateDrawable.setColorFilter(resources.getColor(color), PorterDuff.Mode.SRC_IN) + progressBar.visibility = if (color == android.R.color.black) View.GONE else View.VISIBLE + } + + private fun adjustCounter(adjustment: Int) { + // A synchronized Realm can get written to at any point in time, so doing synchronous writes on the UI + // thread is HIGHLY discouraged as it might block longer than intended. Use only async transactions. + realm.executeTransactionAsync { realm -> + val counter = realm.where().findFirst() + counter?.incrementCounter(adjustment.toLong()) + } + } + +} diff --git a/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/LoginActivity.java b/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/LoginActivity.java deleted file mode 100644 index d16b593802..0000000000 --- a/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/LoginActivity.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2016 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.realm.examples.objectserver; - -import android.app.ProgressDialog; -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; -import android.view.View; -import android.widget.Button; -import android.widget.EditText; -import android.widget.Toast; - -import javax.annotation.Nonnull; - -import butterknife.BindView; -import butterknife.ButterKnife; -import io.realm.SyncCredentials; -import io.realm.ObjectServerError; -import io.realm.SyncUser; - - -public class LoginActivity extends AppCompatActivity { - @BindView(R.id.input_username) EditText username; - @BindView(R.id.input_password) EditText password; - @BindView(R.id.button_login) Button loginButton; - @BindView(R.id.button_create) Button createUserButton; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_login); - ButterKnife.bind(this); - loginButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - login(false); - } - }); - createUserButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - login(true); - } - }); - } - - public void login(boolean createUser) { - if (!validate()) { - onLoginFailed("Invalid username or password"); - return; - } - - createUserButton.setEnabled(false); - loginButton.setEnabled(false); - - final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this); - progressDialog.setIndeterminate(true); - progressDialog.setMessage("Authenticating..."); - progressDialog.show(); - - String username = this.username.getText().toString(); - String password = this.password.getText().toString(); - - SyncCredentials creds = SyncCredentials.usernamePassword(username, password, createUser); - SyncUser.Callback callback = new SyncUser.Callback() { - @Override - public void onSuccess(@Nonnull SyncUser user) { - progressDialog.dismiss(); - onLoginSuccess(); - } - - @Override - public void onError(@Nonnull ObjectServerError error) { - progressDialog.dismiss(); - String errorMsg; - switch (error.getErrorCode()) { - case UNKNOWN_ACCOUNT: - errorMsg = "Account does not exists."; - break; - case INVALID_CREDENTIALS: - errorMsg = "User name and password does not match"; - break; - default: - errorMsg = error.toString(); - } - onLoginFailed(errorMsg); - } - }; - - SyncUser.logInAsync(creds, BuildConfig.REALM_AUTH_URL, callback); - } - - @Override - public void onBackPressed() { - // Disable going back to the MainActivity - moveTaskToBack(true); - } - - public void onLoginSuccess() { - loginButton.setEnabled(true); - createUserButton.setEnabled(true); - finish(); - } - - public void onLoginFailed(String errorMsg) { - loginButton.setEnabled(true); - createUserButton.setEnabled(true); - Toast.makeText(getBaseContext(), errorMsg, Toast.LENGTH_LONG).show(); - } - - public boolean validate() { - boolean valid = true; - String email = username.getText().toString(); - String password = this.password.getText().toString(); - - if (email.isEmpty()) { - valid = false; - } - - if (password.isEmpty()) { - valid = false; - } - - return valid; - } -} diff --git a/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/LoginActivity.kt b/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/LoginActivity.kt new file mode 100644 index 0000000000..1038e795a8 --- /dev/null +++ b/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/LoginActivity.kt @@ -0,0 +1,113 @@ +/* + * Copyright 2019 Realm Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.realm.examples.objectserver + +import android.app.ProgressDialog +import android.databinding.DataBindingUtil +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import android.widget.Button +import android.widget.EditText +import android.widget.Toast +import io.realm.ErrorCode +import io.realm.ObjectServerError +import io.realm.SyncCredentials +import io.realm.SyncUser +import io.realm.examples.objectserver.databinding.ActivityLoginBinding + +class LoginActivity : AppCompatActivity() { + + private lateinit var username: EditText + private lateinit var password: EditText + private lateinit var loginButton: Button + private lateinit var createUserButton: Button + + lateinit private var binding: ActivityLoginBinding + + public override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = DataBindingUtil.setContentView(this, R.layout.activity_login) + username = binding.inputUsername + password = binding.inputPassword + loginButton = binding.buttonLogin + createUserButton = binding.buttonCreate + + loginButton.setOnClickListener { login(false) } + createUserButton.setOnClickListener { login(true) } + } + + private fun login(createUser: Boolean) { + if (!validate()) { + onLoginFailed("Invalid username or password") + return + } + + binding.buttonCreate.isEnabled = false + binding.buttonLogin.isEnabled = false + + val progressDialog = ProgressDialog(this@LoginActivity) + progressDialog.isIndeterminate = true + progressDialog.setMessage("Authenticating...") + progressDialog.show() + + val username = this.username.text.toString() + val password = this.password.text.toString() + + val creds = SyncCredentials.usernamePassword(username, password, createUser) + val callback = object : SyncUser.Callback { + override fun onSuccess(user: SyncUser) { + progressDialog.dismiss() + onLoginSuccess() + } + + override fun onError(error: ObjectServerError) { + progressDialog.dismiss() + val errorMsg: String = when (error.errorCode) { + ErrorCode.UNKNOWN_ACCOUNT -> getString(R.string.login_error_unknown_account) + ErrorCode.INVALID_CREDENTIALS -> getString(R.string.login_error_invalid_credentials) + else -> error.toString() + } + onLoginFailed(errorMsg) + } + } + + SyncUser.logInAsync(creds, BuildConfig.REALM_AUTH_URL, callback) + } + + override fun onBackPressed() { + // Disable going back to the MainActivity + moveTaskToBack(true) + } + + private fun onLoginSuccess() { + loginButton.isEnabled = true + createUserButton.isEnabled = true + finish() + } + + private fun onLoginFailed(errorMsg: String) { + loginButton.isEnabled = true + createUserButton.isEnabled = true + Toast.makeText(baseContext, errorMsg, Toast.LENGTH_LONG).show() + } + + private fun validate(): Boolean = when { + username.text.toString().isEmpty() -> false + password.text.toString().isEmpty() -> false + else -> true + } +} diff --git a/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/MyApplication.java b/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/MyApplication.kt similarity index 62% rename from examples/objectServerExample/src/main/java/io/realm/examples/objectserver/MyApplication.java rename to examples/objectServerExample/src/main/java/io/realm/examples/objectserver/MyApplication.kt index 417fd9d9f5..dc7360fb48 100644 --- a/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/MyApplication.java +++ b/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/MyApplication.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016 Realm Inc. + * Copyright 2019 Realm Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,24 +14,23 @@ * limitations under the License. */ -package io.realm.examples.objectserver; +package io.realm.examples.objectserver -import android.app.Application; -import android.util.Log; +import android.app.Application +import android.util.Log -import io.realm.Realm; -import io.realm.log.RealmLog; +import io.realm.Realm +import io.realm.log.RealmLog -public class MyApplication extends Application { +class MyApplication : Application() { - @Override - public void onCreate() { - super.onCreate(); - Realm.init(this, "ObjectServerExample/" + BuildConfig.VERSION_NAME); + override fun onCreate() { + super.onCreate() + Realm.init(this, "ObjectServerExample/" + BuildConfig.VERSION_NAME) - // Enable full log output when debugging + // Enable more if (BuildConfig.DEBUG) { - RealmLog.setLevel(Log.DEBUG); + RealmLog.setLevel(Log.DEBUG) } } } diff --git a/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/model/CRDTCounter.java b/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/model/CRDTCounter.java deleted file mode 100644 index 0bca8fd53c..0000000000 --- a/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/model/CRDTCounter.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2017 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.realm.examples.objectserver.model; - -import io.realm.MutableRealmInteger; -import io.realm.RealmObject; -import io.realm.annotations.PrimaryKey; -import io.realm.annotations.Required; - -/** - * A named, conflict-free replicated data-type. - */ -public class CRDTCounter extends RealmObject { - @PrimaryKey - private String name; - - @Required - public final MutableRealmInteger counter = MutableRealmInteger.valueOf(0L); - - // Required for Realm - public CRDTCounter() {} - - public CRDTCounter(String name) { this.name = name; } - - public String getName() { return name; } - - public long getCount() { return counter.get().longValue(); } - public void incrementCounter(long delta) { counter.increment(delta); } -} diff --git a/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/model/CRDTCounter.kt b/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/model/CRDTCounter.kt new file mode 100644 index 0000000000..6078bb0512 --- /dev/null +++ b/examples/objectServerExample/src/main/java/io/realm/examples/objectserver/model/CRDTCounter.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2019 Realm Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.realm.examples.objectserver.model + +import io.realm.MutableRealmInteger +import io.realm.RealmObject +import io.realm.annotations.PrimaryKey +import io.realm.annotations.Required + +open class CRDTCounter : RealmObject() { + + @PrimaryKey + var name: String = "" + + @Required + private val counter = MutableRealmInteger.valueOf(0L) + + val count: Long + get() = this.counter.get()!!.toLong() + + fun incrementCounter(delta: Long) { + counter.increment(delta) + } + +} diff --git a/examples/objectServerExample/src/main/res/layout/activity_counter.xml b/examples/objectServerExample/src/main/res/layout/activity_counter.xml index a1300b2123..215c9fb47f 100644 --- a/examples/objectServerExample/src/main/res/layout/activity_counter.xml +++ b/examples/objectServerExample/src/main/res/layout/activity_counter.xml @@ -1,49 +1,51 @@ - - - + + + + + + android:layout_height="match_parent"> - - + android:layout_height="match_parent" + android:orientation="vertical"> + + + + + - + + - - - - - - - - + android:layout_height="wrap_content" + android:layout_gravity="top" + android:indeterminate="true" + android:visibility="visible" + app:mpb_progressStyle="horizontal" /> + + + + diff --git a/examples/objectServerExample/src/main/res/layout/activity_login.xml b/examples/objectServerExample/src/main/res/layout/activity_login.xml index 375cdbca98..29f078ebc2 100644 --- a/examples/objectServerExample/src/main/res/layout/activity_login.xml +++ b/examples/objectServerExample/src/main/res/layout/activity_login.xml @@ -1,68 +1,75 @@ - + - + - + - + android:orientation="vertical" + android:paddingLeft="24dp" + android:paddingTop="56dp" + android:paddingRight="24dp"> - + + - + android:layout_marginTop="8dp" + android:layout_marginBottom="8dp"> - + + - - + android:layout_marginTop="8dp" + android:layout_marginBottom="8dp"> - + + + + + + + + + + - - - diff --git a/examples/objectServerExample/src/main/res/values/strings.xml b/examples/objectServerExample/src/main/res/values/strings.xml index b4f90b3676..dbf98e52eb 100644 --- a/examples/objectServerExample/src/main/res/values/strings.xml +++ b/examples/objectServerExample/src/main/res/values/strings.xml @@ -7,4 +7,6 @@ Create account and login Login Logout + Account does not exist. + User name and password do not match. diff --git a/realm/build.gradle b/realm/build.gradle index 53ffc2de3a..9ab569ac19 100644 --- a/realm/build.gradle +++ b/realm/build.gradle @@ -38,7 +38,7 @@ allprojects { def projectDependencies = new Properties() projectDependencies.load(new FileInputStream("${rootDir}/../dependencies.list")) project.ext.minSdkVersion = 9 - project.ext.compileSdkVersion = 26 + project.ext.compileSdkVersion = 27 project.ext.buildToolsVersion = projectDependencies.get("ANDROID_BUILD_TOOLS") group = 'io.realm'