diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 4218585..c32e821 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -35,6 +35,10 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
+ - uses: actions/setup-java@v4
+ with:
+ distribution: 'temurin'
+ java-version: '17'
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
@@ -61,8 +65,8 @@ jobs:
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
- # echo "Run, Build Application using script"
- # ./location_of_script_within_repo/buildscript.sh
+ # echo "Run, Build Application using script"
+ # - run: ./gradlew assembleDebug
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml
new file mode 100644
index 0000000..ed96868
--- /dev/null
+++ b/.github/workflows/publish-release.yml
@@ -0,0 +1,31 @@
+name: Publish - Release
+
+on:
+ release:
+ types: [released]
+
+jobs:
+ publish:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout project sources
+ uses: actions/checkout@v3
+ - name: Setup Gradle
+ uses: gradle/gradle-build-action@v2
+ - name: Setup local.properties
+ run: |
+ cat << EOF >> local.properties
+ sdk.dir=$ANDROID_HOME
+ EOF
+ - name: Gradle build and clean
+ run: |
+ ./gradlew clean build
+ - name: Publish the SDK
+ run: |
+ ./gradlew publishAndReleaseToMavenCentral --no-configuration-cache
+ env:
+ ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.mavenCentralUsername }}
+ ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.mavenCentralPassword }}
+ ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.signingInMemoryKey }}
+ ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.signingInMemoryKeyId }}
+ ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.signingInMemoryKeyPassword }}
\ No newline at end of file
diff --git a/.github/workflows/publish-snapshot.yml b/.github/workflows/publish-snapshot.yml
new file mode 100644
index 0000000..7cf1c3b
--- /dev/null
+++ b/.github/workflows/publish-snapshot.yml
@@ -0,0 +1,40 @@
+name: Publish - Snapshot
+
+on:
+ push:
+ branches:
+ - master
+
+jobs:
+ publish:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout project sources
+ uses: actions/checkout@v3
+ - name: Check whether the version is a snapshot
+ run: |
+ if grep -q "\-SNAPSHOT" ./contentstack/build.gradle
+ then
+ :
+ else
+ exit 1
+ fi
+ - name: Setup Gradle
+ uses: gradle/gradle-build-action@v2
+ - name: Setup local.properties
+ run: |
+ cat << EOF >> local.properties
+ sdk.dir=$ANDROID_HOME
+ EOF
+ - name: Build the SDK - Snapshot
+ run: |
+ ./gradlew clean build
+ - name: Publish the SDK - Snapshot
+ run: |
+ ./gradlew publishAllPublicationsToMavenCentralRepository
+ env:
+ ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.mavenCentralUsername }}
+ ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.mavenCentralPassword }}
+ ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.signingInMemoryKey }}
+ ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.signingInMemoryKeyId }}
+ ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.signingInMemoryKeyPassword }}
\ No newline at end of file
diff --git a/.github/workflows/sca-scan.yml b/.github/workflows/sca-scan.yml
index 9304a2a..e652d79 100644
--- a/.github/workflows/sca-scan.yml
+++ b/.github/workflows/sca-scan.yml
@@ -1,26 +1,28 @@
name: Source Composition Analysis Scan
on:
pull_request:
- types: [ opened, synchronize, reopened ]
+ types: [opened, synchronize, reopened]
jobs:
security:
runs-on: ubuntu-latest
-
steps:
- uses: actions/checkout@master
- - name: Generate local.properties
- run: echo "sdk.dir=${ANDROID_SDK_ROOT}" > local.properties
- - name: cat
- run: cat local.properties
- - name: pwd
- run: pwd
- - name: env
- run: env
- - name: Run Snyk to check for vulnerabilities
- uses: snyk/actions/gradle-jdk14@master
+ - uses: actions/setup-java@v4
+ with:
+ distribution: 'temurin'
+ java-version: '17'
+ - name: Setup local.properties
+ run: |
+ cat << EOF >> local.properties
+ sdk.dir=$ANDROID_HOME
+ host="${{ secrets.HOST }}"
+ APIKey="${{ secrets.API_KEY }}"
+ deliveryToken="${{ secrets.DELIVERY_TOKEN }}"
+ environment="${{ secrets.ENVIRONMENT }}"
+ contentType="${{ secrets.CONTENT_TYPE }}"
+ assetUid="${{ secrets.ASSET_UID }}"
+ EOF
+ - uses: snyk/actions/setup@master
+ - run: snyk test
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
- with:
- args: --fail-on=all
- command: test || ls
-
diff --git a/.gitignore b/.gitignore
index 2b75303..5192629 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,4 @@
/build
/captures
.externalNativeBuild
+/.idea/
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index b589d56..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/dictionaries/shaileshmishra.xml b/.idea/dictionaries/shaileshmishra.xml
deleted file mode 100644
index 46b9d3e..0000000
--- a/.idea/dictionaries/shaileshmishra.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
deleted file mode 100644
index 15a15b2..0000000
--- a/.idea/encodings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index 38c211a..0000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
deleted file mode 100644
index 31a4180..0000000
--- a/.idea/jarRepositories.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 34d68b5..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index b5890c1..4825a14 100644
--- a/README.md
+++ b/README.md
@@ -1,45 +1,45 @@
+[](https://www.contentstack.com/)
-[](https://www.contentstack.com/)
-
-# Contentstack Android Persistence Library
-
-
-
-Contentstack provides [Android Persistence Library](https://www.contentstack.com/docs/guide/synchronization/using-realm-persistence-library-with-android-sync-sdk) that lets your application store data on the device's local storage. This helps you build apps that can work offline too. Given below is a detailed guide and helpful resources to get started with our android Persistence Library.
-
-## Prerequisites
-
- * [Android Studio](https://developer.android.com/studio/)
- * [Java jdk 8](https://www.oracle.com/technetwork/es/java/javase/downloads/jdk8-downloads-2133151.html)
-
-## Setup and Initialize library
-
-
-### For Realm
-
-You download below four files from [Repository](https://github.com/contentstack/contentstack-android-persistence/tree/master/app/src/main/java/com/contentstack/persistence) and keep it in your src folder.
- * RealmStore * SyncManager * SyncPersistable
-* SyncStore
-
-#### Initialize the library
-
-To start using the library in your application, you will need to initialize it by providing the stack details:
-
-```java
- Stack stack = Contentstack.stack(context, "apiKey", "accessToken", "environment");
-
- //Provide realmInstance using
- Realm realmInstance = Realm.getDefaultInstance();
- //Provide realmInstance to RealmStore's constructor like below.
- RealmStore realmStore = new RealmStore(realmInstance);
-
- SyncManager manager = new SyncManager(realmStore, stack);
- manager.stackRequest();
-
+# Contentstack Android Persistence Library
+
+Contentstack provides [Android Persistence Library](https://www.contentstack.com/docs/guide/synchronization/using-realm-persistence-library-with-android-sync-sdk) that lets your application store data on the device's local storage. This helps you build apps that can work offline too. Given below is a detailed guide and helpful resources to get started with our android Persistence Library.
+
+## Prerequisites
+
+* [Android Studio](https://developer.android.com/studio/) IDE
+* [Java JDK 8](https://www.oracle.com/technetwork/es/java/javase/downloads/jdk8-downloads-2133151.html) or above installed in your machine
+* [Realm](https://www.mongodb.com/docs/realm/sdk/java/install/#std-label-java-install) should be installed
+
+## Setup and initialize library
+
+### To use realm local database
+
+Download the following four files from [Repository](https://github.com/contentstack/contentstack-android-persistence/tree/master/app/src/main/java/com/contentstack/persistence) and place them in your src folder:
+
+- `RealmStore`
+- `SyncManager`
+- `SyncPersistable`
+- `SyncStore`
+- `Utils`
+
+### Initialize the library
+
+You can initialize the Persistence SDK using the code below in your application.
+
+```java
+Stack stack = Contentstack.stack(applicationContext,"apiKey","deliveryToken","environment");
+Realm realmInstance = Realm.getDefaultInstance(); // gets default realm instance
+RealmStore realmStore = new RealmStore(realmInstance); ////Provide realmInstance to RealmStore's constructor like below
+SyncManager manager = new SyncManager(realmStore,stack);
+manager.stackRequest();
```
-We have created an example app using android Persistence Library that stores data on the device's local storage. [Read the tutorial](https://github.com/contentstack/contentstack-android-persistence-example) to get started with the example app.
-### Helpful Links
-
-- [Android Persistence Library Docs](https://www.contentstack.com/docs/guide/synchronization/using-realm-persistence-library-with-android-sync-sdk)
-- [Android Persistence Example App](https://github.com/contentstack/contentstack-android-persistence-example)
+
+***Note:** Explore our example app built with the Android Persistence SDK, which securely stores data on your Android device's local storage. [Read the tutorial](https://github.com/contentstack/contentstack-android-persistence-example) to begin with the example app.*
+
+*Please write migrations in case table schema changes are expected.*
+
+### Helpful Links
+
+- [Android Persistence Library Docs](https://www.contentstack.com/docs/guide/synchronization/using-realm-persistence-library-with-android-sync-sdk)
+- [Android Persistence Example App](https://github.com/contentstack/contentstack-android-persistence-example)
- [Content Delivery API Docs](https://contentstack.com/docs/apis/content-delivery-api/)
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index efd9904..77fde14 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,14 +1,17 @@
plugins {
id 'com.android.application'
id "realm-android"
+ id "com.vanniktech.maven.publish" version "0.27.0"
}
+// import com.vanniktech.maven.publish.SonatypeHost
+
android {
- compileSdkVersion 33
+ compileSdkVersion 34
namespace 'com.contentstack.sdk.persistence'
defaultConfig {
minSdkVersion 24
- targetSdkVersion 33
+ targetSdkVersion 34
versionCode 1
versionName "0.0.2"
}
@@ -27,11 +30,10 @@ android {
}
dependencies {
- implementation 'com.contentstack.sdk:android:3.13.0'
- implementation 'androidx.appcompat:appcompat:1.0.0'
- implementation 'com.google.android.material:material:1.0.0'
- implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
- implementation 'androidx.lifecycle:lifecycle-livedata:2.0.0'
- implementation 'androidx.lifecycle:lifecycle-viewmodel:2.0.0'
-}
-
+ implementation 'com.contentstack.sdk:android:3.14.0-20240208.095825-3'
+ implementation 'androidx.appcompat:appcompat:1.6.1'
+ implementation 'com.google.android.material:material:1.11.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation 'androidx.lifecycle:lifecycle-livedata:2.7.0'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel:2.7.0'
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/contentstack/sdk/persistence/Home.java b/app/src/main/java/com/contentstack/sdk/persistence/Home.java
index d28f69c..6c46733 100644
--- a/app/src/main/java/com/contentstack/sdk/persistence/Home.java
+++ b/app/src/main/java/com/contentstack/sdk/persistence/Home.java
@@ -6,6 +6,7 @@
import io.realm.annotations.RealmClass;
import io.realm.annotations.RealmField;
+// This is only for testing support
@RealmClass(name = "a")
public class Home extends RealmObject {
diff --git a/app/src/main/java/com/contentstack/sdk/persistence/MainActivity.java b/app/src/main/java/com/contentstack/sdk/persistence/MainActivity.java
index 4ec5320..c2f8c37 100644
--- a/app/src/main/java/com/contentstack/sdk/persistence/MainActivity.java
+++ b/app/src/main/java/com/contentstack/sdk/persistence/MainActivity.java
@@ -10,6 +10,7 @@
import io.realm.Realm;
+// This is only for testing support
public class MainActivity extends AppCompatActivity {
@Override
@@ -24,10 +25,10 @@ protected void onCreate(Bundle savedInstanceState) {
private void loadTheSDK() {
try {
Config config = new Config();
- config.setHost("*************");
+ config.setHost("************");
Stack stack = Contentstack.stack(getApplicationContext(),
- "*************", "*************",
- "*************", config);
+ "************", "************",
+ "dev", config);
Realm realmInstance = Realm.getDefaultInstance();
diff --git a/app/src/main/java/com/contentstack/sdk/persistence/SyncManager.java b/app/src/main/java/com/contentstack/sdk/persistence/SyncManager.java
index 8d84872..93c0109 100644
--- a/app/src/main/java/com/contentstack/sdk/persistence/SyncManager.java
+++ b/app/src/main/java/com/contentstack/sdk/persistence/SyncManager.java
@@ -32,8 +32,8 @@
public class SyncManager {
- final private String TAG = SyncManager.class.getSimpleName();
- final private Logger logger = Logger.getLogger(TAG);
+ final private static String TAG = SyncManager.class.getSimpleName();
+ final private static Logger logger = Logger.getLogger(TAG);
final private Stack stackInstance;
final private RealmStore realmStoreInstance;
final private Realm realmInstance;
@@ -55,44 +55,63 @@ public SyncManager(@NonNull RealmStore realmStore, @NonNull Stack stackInstance)
}
- private void handleError(Error error) {
-
- if (error.getStatusCode() == 422) {
-
- if (error.getErrors().containsKey("pagination_token")) {
+ void makeRandomDelay() {
+ int minDelayMillis = 1000; // Minimum delay of 1000 milliseconds (1 second)
+ int maxDelayMillis = 3000; // Maximum delay of 3000 milliseconds (3 seconds)
+ int delayMillis = minDelayMillis + (int) (Math.random() * (maxDelayMillis - minDelayMillis + 1));
+ //It's helpful to introduce a random delay of 1000-3000 milliseconds in the request.
+ try {
+ Thread.sleep(delayMillis);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt(); // Restore interrupted state
+ throw new RuntimeException("Thread sleep interrupted: " + e.getMessage());
+ }
+ }
- deleteToken(null, getPaginationToken()); // Delete pagination token from local DB
- stackRequest();
- } else if (error.getErrors().containsKey("sync_token")) {
- deleteToken(getSyncToken(), null); // Delete sync token from local DB
+ private void handleError(Error error) {
+ int statusCode = error.getStatusCode();
+ if (statusCode == 422) {
+ if (error.getErrors().containsKey("sync")) {
+ deleteSeqToken();
stackRequest();
} else {
-
- try {
- throw new Exception();
- } catch (Exception e) {
- throw new RuntimeException(e.getLocalizedMessage());
- }
+ throw new RuntimeException("Unprocessable Entity Error: " + error.getErrors());
}
+ } else if (statusCode == 429) {
+ handleRateLimitError();
+ }
+ }
- } else if (error.getStatusCode() == 429) {
- int delayMillis = (int) (1000 + Math.random() * 2000);
- try {
- Thread.sleep(delayMillis);
- } catch (InterruptedException e) {
- throw new RuntimeException(e.getLocalizedMessage());
- }
- stackRequest();
+ private void deleteSeqToken() {
+ try {
+ SyncStore ts = new SyncStore();
+ ts.setSeqToken(null); // Setting Sequence Token Null
+ realmStoreInstance.beginWriteTransaction();
+ realmStoreInstance.getRealmInstance().insertOrUpdate(ts);
+ realmStoreInstance.commitWriteTransaction();
+ } catch (Exception e) {
+ Log.e("Error :", e.getLocalizedMessage());
+ e.printStackTrace();
+ } finally {
+ realmStoreInstance.closeTransaction();
}
}
- public void stackRequest() {
- if (getSyncToken() != null) {
- Log.i(TAG, "Call initiated for Sync Token " + getSyncToken());
- stackInstance.syncToken(getSyncToken(), new SyncResultCallBack() {
+ private void handleRateLimitError() {
+ makeRandomDelay();
+ stackRequest();
+ }
+
+
+ public void stackRequest() {
+ Log.w(TAG, "Sync API request made");
+ String sequenceId = getToken(TokenEnum.SEQ);
+ if (sequenceId != null) {
+ Log.i(TAG, "seqId " + sequenceId);
+ stackInstance.seqSync(sequenceId, new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
if (error == null) {
@@ -103,66 +122,116 @@ public void onCompletion(SyncStack syncStack, Error error) {
}
}
});
+ } else {
+ // When the application is already installed and in use with existing data.
+ String syncToken = getToken(TokenEnum.SYNC);
+ String paginateToken = getToken(TokenEnum.PAGINATION);
+ if (syncToken != null || paginateToken != null) {
+ appAlreadyInUse();
+ } else {
+ newInitialSync();
+ }
+ }
+ }
- } else if (getPaginationToken() != null) {
- Log.i(TAG, "Call initiated for Pagination Token " + getPaginationToken());
- stackInstance.syncPaginationToken(getPaginationToken(), new SyncResultCallBack() {
+ private void newInitialSync() {
+ // Whn it's fresh start for Application (new usr) !
+ stackInstance.initSeqSync(new SyncResultCallBack() {
+ @Override
+ public void onCompletion(SyncStack syncStack, Error error) {
+ Log.i(TAG, "Init Sync");
+ if (error == null) {
+ logger.log(Level.INFO, syncStack.getJSONResponse().toString());
+ parseResponse(syncStack);
+ } else {
+ handleError(error);
+ }
+ }
+ });
+ }
+
+ private void appAlreadyInUse() {
+ // To provide support for old sync api
+ String syncToken = getToken(TokenEnum.SYNC);
+ String paginateToken = getToken(TokenEnum.PAGINATION);
+ if (syncToken != null) {
+ stackInstance.syncToken(syncToken, new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
- if (error == null) {
- logger.log(Level.INFO, syncStack.getJSONResponse().toString());
- parseResponse(syncStack);
- } else {
- handleError(error);
- }
+ //old sync api support
+ // it may have data or may not have, when it does not have any data means everything is up to date
+ // if it contains some data the get last item and generate seqId based on event timestamp
+ processStackResponse(syncStack);
}
});
- } else {
- stackInstance.sync(new SyncResultCallBack() {
+ } else if (paginateToken != null) {
+ stackInstance.syncPaginationToken(paginateToken, new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
- Log.i(TAG, "Initial Sync Call");
- if (error == null) {
- logger.log(Level.INFO, syncStack.getJSONResponse().toString());
- parseResponse(syncStack);
- } else {
- handleError(error);
- }
+ //old sync api support
+ //It defiantly has some data, calculate last item timestamp and generate the seqId
+ processStackResponse(syncStack);
}
});
+ } else {
+ newInitialSync();
}
}
+ private void processStackResponse(SyncStack stackResponse) {
+ // Calculate item size and find the timestamp of the last event to generate seqId
+ int size = stackResponse.getCount();
+ if (size > 0) {
+ ArrayList jsonList = stackResponse.getItems();
+ JSONObject lastItem = jsonList.get(size - 1);
+ String timestamp = lastItem.optString("event_at");
- private String getSyncToken() {
- SyncStore syncStore = realmInstance.where(SyncStore.class).findFirst();
- if (syncStore != null) {
- return realmInstance.where(SyncStore.class).findFirst().getSyncToken();
- } else {
- Log.e(TAG, "Sync Token Not Found");
- return null;
+ // Generate seqId based on the timestamp
+ String seqId = Utils.generateSeqId(timestamp); // TODO: re-visit the code
+ Log.w(TAG, "Newly generated seqId: " + seqId);
+
+ // Store sequence id along with sync and pagination tokens
+ String syncToken = stackResponse.getSyncToken();
+ String paginateToken = stackResponse.getPaginationToken();
+ storeSequenceId(syncToken, paginateToken, seqId);
+
+ // Initiate another stack request for further processing
+ stackRequest();
}
}
- private String getPaginationToken() {
+ private String getToken(TokenEnum tokenType) {
SyncStore syncStore = realmInstance.where(SyncStore.class).findFirst();
if (syncStore != null) {
- return realmInstance.where(SyncStore.class).findFirst().getPaginationToken();
+ switch (tokenType) {
+ case SEQ:
+ return syncStore.getSeqToken();
+ case SYNC:
+ return syncStore.getSyncToken();
+ case PAGINATION:
+ return syncStore.getPaginationToken();
+ default:
+ Log.e(TAG, "Invalid token type");
+ return null;
+ }
} else {
- Log.e(TAG, "Pagination Token Not Found");
+ Log.e(TAG, "SyncStore Not Found");
return null;
}
}
+ enum TokenEnum {
+ SEQ, SYNC, PAGINATION
+ }
private void parseResponse(SyncStack stackResponse) {
ArrayList jsonList = stackResponse.getItems();
+ String seqToken = stackResponse.getSequentialToken();
String syncToken = stackResponse.getSyncToken();
- String pagiToken = stackResponse.getPaginationToken();
- if (syncToken != null) {
- persistsToken(syncToken, pagiToken);
- }
+ String paginateToken = stackResponse.getPaginationToken();
+
+ storeSequenceId(syncToken, paginateToken, seqToken);
jsonList.forEach(this::handleJSON);
}
@@ -365,43 +434,20 @@ private void reflectionThing(Class extends RealmModel> MODEL_CLASS) {
}
- private void persistsToken(String sync_token, String pagination_token) {
- Log.e("Tokens :", "Sync Token: " + sync_token + " pagination_token: " + pagination_token);
+ private void storeSequenceId(String syncToken, String paginationToken, String seqId) {
+ Log.e(TAG, "SyncToken: " + syncToken);
+ Log.e(TAG, "PaginationToken: " + paginationToken);
+ Log.e(TAG, "SeqId: " + seqId);
try {
realmStoreInstance.beginWriteTransaction();
- realmStoreInstance.getRealmInstance().insertOrUpdate(new SyncStore("token", sync_token, pagination_token));
+ realmStoreInstance.getRealmInstance().insertOrUpdate(new SyncStore("seqToken", syncToken, paginationToken, seqId));
realmStoreInstance.commitWriteTransaction();
} catch (Exception e) {
- Log.e("Persistence Token :", e.getLocalizedMessage().toString());
+ Log.e("Error :", e.getLocalizedMessage());
e.printStackTrace();
} finally {
realmStoreInstance.closeTransaction();
}
}
- private void deleteToken(String syncToken, String paginationToken) {
- try {
- realmStoreInstance.beginWriteTransaction();
- if (syncToken != null) {
- realmStoreInstance.getRealmInstance().insertOrUpdate(new SyncStore("token", null, paginationToken));
- Log.i(TAG, "syncToken deleted");
- }
- if (paginationToken != null) {
- realmStoreInstance.getRealmInstance().insertOrUpdate(new SyncStore("token", syncToken, null));
- Log.i(TAG, "paginationToken deleted");
- }
- if (syncToken != null && paginationToken != null) {
- realmStoreInstance.getRealmInstance().insertOrUpdate(new SyncStore("token", null, null));
- Log.i(TAG, "sync and pagination token deleted");
- }
- realmStoreInstance.commitWriteTransaction();
- } catch (Exception e) {
- Log.e("Persistence Token :", e.getLocalizedMessage());
- e.printStackTrace();
- } finally {
- realmStoreInstance.closeTransaction();
- }
- }
-
-
}
diff --git a/app/src/main/java/com/contentstack/sdk/persistence/SyncStore.java b/app/src/main/java/com/contentstack/sdk/persistence/SyncStore.java
index e499ae5..9853d2f 100644
--- a/app/src/main/java/com/contentstack/sdk/persistence/SyncStore.java
+++ b/app/src/main/java/com/contentstack/sdk/persistence/SyncStore.java
@@ -5,20 +5,22 @@
public class SyncStore extends RealmObject {
- @PrimaryKey
- private String uniqueId;
- private String syncToken;
- private String paginationToken;
-
- public SyncStore() {
- }
-
- public SyncStore(String uniqueId, String syncToken, String paginationToken) {
+ public SyncStore(String uniqueId, String syncToken, String paginationToken, String seqToken) {
this.uniqueId = uniqueId;
this.syncToken = syncToken;
this.paginationToken = paginationToken;
+ this.seqToken = seqToken;
+ }
+
+ public SyncStore() {
}
+ @PrimaryKey
+ private String uniqueId;
+ private String syncToken;
+ private String paginationToken;
+ private String seqToken;
+
public String getUniqueId() {
return uniqueId;
}
@@ -31,15 +33,25 @@ public String getSyncToken() {
return syncToken;
}
- public void setSyncToken(String sync_token) {
- this.syncToken = sync_token;
+ public void setSyncToken(String syncToken) {
+ this.syncToken = syncToken;
}
public String getPaginationToken() {
return paginationToken;
}
- public void setPaginationToken(String pagination_token) {
- this.paginationToken = pagination_token;
+ public void setPaginationToken(String paginationToken) {
+ this.paginationToken = paginationToken;
+ }
+
+ public String getSeqToken() {
+ return seqToken;
+ }
+
+ public void setSeqToken(String seqToken) {
+ this.seqToken = seqToken;
}
-}
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/contentstack/sdk/persistence/Utils.java b/app/src/main/java/com/contentstack/sdk/persistence/Utils.java
new file mode 100644
index 0000000..d2fc589
--- /dev/null
+++ b/app/src/main/java/com/contentstack/sdk/persistence/Utils.java
@@ -0,0 +1,33 @@
+package com.contentstack.sdk.persistence;
+
+import org.bson.types.ObjectId;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Objects;
+import java.util.TimeZone;
+
+public class Utils {
+
+ static String generateSeqId(String timestamp) {
+ Objects.requireNonNull(timestamp, "Timestamp Should Not Be Null");
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+ sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
+ Date eventAtDate = null;
+ try {
+ eventAtDate = sdf.parse(timestamp);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+
+ // Convert the Date to a Unix timestamp in milliseconds
+ long unixTimeInMillis = eventAtDate.getTime();
+
+ // Create a BSON ObjectId using the Unix timestamp
+ ObjectId objectId = new ObjectId((int) (unixTimeInMillis / 1000), 0);
+ String seqId = objectId.toHexString();
+ System.out.println(seqId);
+ return seqId;
+ }
+}
diff --git a/build.gradle b/build.gradle
index 92bbada..73b680e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -2,14 +2,13 @@ buildscript {
repositories {
google()
mavenCentral()
-
}
dependencies {
- classpath 'com.android.tools.build:gradle:8.2.2'
+ // classpath 'com.android.tools.build:gradle:8.2.2'
+ classpath 'com.android.tools.build:gradle:7.4.2'
classpath 'io.realm:realm-gradle-plugin:10.15.1'
}
}
-
allprojects {
repositories {
google()
@@ -17,7 +16,6 @@ allprojects {
maven { url =uri("https://oss.sonatype.org/content/repositories/snapshots") }
}
}
-
task clean(type: Delete) {
delete rootProject.buildDir
}