Migrating from Version 2.x to Version 3.x

Version 3 of the Kinvey libraries adds a number of new capabilities, and incorporates feedback from our developers into a powerful, improved API. We've simplified our libraries to enable common use cases such as syncing, offline usage, user management and querying with minimal code for the app developer.

We recommend that all Kinvey apps use the latest version of the library. This guide is intended to help developers who wish to migrate to v3 from an earlier Kinvey library version.

What's New in Version 3

Version 3 is a major overhaul of the Kinvey mobile libraries that improves on the previous versions and adds several new features. Here are some highlights of the new capabilities of v3:

Data Store Types and Sync

Version 3 simplifies the DataStore with built-in caching and syncing capabilities. We have designed our data stores in a way that makes it easy for developers to support different caching and offline use cases. All you need to do is specify a type when a data store is created. The library takes care of configuring read and write policies, creating and managing a cache, keeping track of offline write operations and optimizing data transfers between the device and the backend. Syncing your backend in Version 3 is much easier with the new pull(), push() and sync() APIs on the DataStores.

For more, check out our DataStore guide.

Querying

Queries can be expressed using the native syntax you are familiar with - for example, you can write queries as NSPredicates on iOS or Lync on Xamarin. The library uses the native expressions to query the cache locally, and seamlessly translates the query when it is run against the backend.

For more, check out the section on querying in our DataStore guide.

Delta Set Caching

In Version 3, we designed a mechanism to reduce the amount of data transferred between the app and the backend on a data fetch. We call this mechanism "delta set caching", and we recommend that developers enable it to gain significant performance benefits in data synchronization.

For more, check out our DataStore guide.

Resumable File Uploads

Version 3 supports resumable file uploads with Google Cloud Storage. The library will try to upload as much of a file as possible and handle interruptions seamlessly by resuming where it left off.

For more, check out our file guide.

Data Store

In v2, data stores were accessed by type using the AsyncAppData<T> or AppData<T> class, instantiated via Client.appData method. In v3, the class that handles data store operations is now simply called DataStore<T>, and in order to access a data store for a particular collection, the static DataStore.collection() method is called.

v2.x

AsyncAppData<Entity> mdataEvents = mKinveyClient.appData("events", Entity.class);

v3.x

DataStore<Entity> mDataStore = DataStore.collection("CollectionName", Entity.class, StoreType.CACHE, mKinveyClient);

Fetching

With fetching entities, there are two primary changes. First, fetching methods no longer returns an array of those entities, but instead will return a List of those entities. And secondly, the names of the fetch methods are now find instead of get.

v2.x

mDataStore.get(new KinveyListCallback<Entity>() {
    @Override
    public void onSuccess(Entity[] users) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable throwable) {
        // Place your error handler here            
    }
});

v3.x

mDataStore.find(new KinveyListCallback<Entity>() {
    @Override
    public void onSuccess(List<Entity> list) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable throwable) {
        // Place your error handler here
    }
});

Deleting

The main change in the delete API is returning Class in onSuccess() method in KinveyDeleteCallback.

v2.x

mDataStore.delete(entityID, new KinveyDeleteCallback() {
    @Override
    public void onSuccess(KinveyDeleteResponse kinveyDeleteResponse) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable throwable) {
        // Place your error handler here
    }
});

v3.x

mDataStore.delete(entityID, new KinveyDeleteCallback() {
    @Override
    public void onSuccess(Integer integer) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable throwable) {
        // Place your error handler here
    }
});

Calculation methods

The main change in calculation methods is extra callback for cached data: KinveyCachedAggregateCallback.

To count all elements in the group, use the dataStore.count().

v2.x

ArrayList<String> fields = new ArrayList<String>();
fields.add("userName");
dataStore.count(fields, null, new KinveyAggregateCallback() {
    @Override
    public void onSuccess(Aggregation res) { 
        Log.i("TAG",  "got: " +res.results[0].get("_result"));
    }  
    @Override
    public void onFailure(Throwable error) {
        Log.e("TAG", "something went wrong ", error);
    }     
});

v3.x

ArrayList<String> list = new ArrayList<String>();
list.add("bookname");
Query query = myClient.query();
query = query.equals("field", "value");
dataStore.count(list, query, new KinveyAggregateCallback() {
    @Override
    public void onFailure(Throwable error) {
      Log.e("TAG", "something went wrong ", error);
      // Place your error handler here
    }

    @Override
    public void onSuccess(Aggregation response) {
      Log.i("TAG",  "got: " + response.getResultsFor("key", "value"));
      // Place your code here
    }
}, new KinveyCachedAggregateCallback() {
    @Override
    public void onFailure(Throwable error) {
      Log.e("TAG", "something went wrong ", error);
      // Place your error handler here
    }

    @Override
    public void onSuccess(Aggregation response) {
      Log.i("TAG",  "got: " + response.getResultsFor("key", "value"));
      // Place your code here
    }
});

Refer to the Data Store guide for details.

Relational Data

Previous major versions of the library include KinveyRefs - a feature for modeling and automatically handling relationships between data entities. This is a useful tool, but suffers from several limitations, such as the limit on number of references, performance during data retrieval etc.

The recommended way to handle data relationships in 3.x is described in Data Modeling guide. The v3 libraries do not implement KinveyRefs, but an equivalent capability of automatically handling relationships is on our roadmap.

Users

Active User

You need an active user before interacting with any data from your backend. In v2, the user that is currently logged into the app, called the active user, is accessed by calling the user() method on the Client object. In v3, the active user is now accessed by a property on the Client called getActiveUser. This is called to get the user that is logged into the app. A value of null indicates that there is no active user in the app.

v2.x

User user = kinveyClient.user();

v3.x

User user = kinveyClient.getActiveUser();

Static User Methods

In v2, the methods of operation available on a user were instance methods, accessed through the current user. In a lot of cases, it made more sense from an API perspective to place these methods on the UserStore class. These methods, such as signUp() and login(), do not require an active user, since these methods will return the active user object in KinveyClientCallback, and so they are now available as a static method on the UserStore class. Also object of Client has added to signature of most of all UserStore static methods.

v2.x

kinveyClient.user().login(userID, password, new KinveyClientCallback<User>() {
    @Override
    public void onSuccess(User user) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable throwable) {
        // Place your error handler here
    }
});

v3.x

UserStore.login(userID, password, client, new KinveyClientCallback<User>() {
    @Override
    public void onSuccess(User user) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable throwable) {
        // Place your error handler here
    }
});

User Creation Method

The name of the method for creating new user has changed from create to signUp, this method is static and availible in UserStore class. Also object of Client has added to signature of this method.

v2.x

kinveyClient.user().create(userName, password, new KinveyClientCallback<User>() {
    @Override
    public void onSuccess(User user) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable throwable) {
        // Place your error handler here
    }
});

v3.x

UserStore.signUp(userName, password, client, new KinveyClientCallback<User>() {
    @Override
    public void onSuccess(User user) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable throwable) {
        // Place your error handler here
    }
});

Refer to the Users guide for details.

Files

You need an active user before interacting with any files from your backend. In v3, Class for work with files was changed from AsyncFile to FileStore. You can get instance of this class by calling the getFileStore(StoreType) method on the Client object. StoreType can be: NEWTWORK, CACHE, SYNC.

v2.x

AsyncFile asyncFile = kinveyClient.file();

v3.x

FileStore fileStore = kinveyClient.getFileStore(StoreType.CACHE);

Uploading

The upload API has changed in callback. UploaderProgressListener was changed to AsyncUploaderProgressListener<FileMetaData>, also were added onCancelled() and isCancelled(). It was added because v3 has a possibility to use resuming uploading and downloading.

v2.x

AsyncFile asyncFile = kinveyClient.file();
asyncFile.upload(file, new UploaderProgressListener() {
    @Override
    public void progressChanged(MediaHttpUploader mediaHttpUploader) throws IOException {
        // Place your code here
    }

    @Override
    public void onSuccess(Void aVoid) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable throwable) {
        // Place your error handler here
    }
});

v3.x

boolean isCancelled = false;
FileStore fileStore = kinveyClient.getFileStore(StoreType.CACHE);
fileStore.upload(file, new AsyncUploaderProgressListener<FileMetaData>() {
    @Override
    public void onSuccess(FileMetaData fileMetaData) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable throwable) {
        // Place your error handler here
    }

    @Override
    public void progressChanged(MediaHttpUploader mediaHttpUploader) throws IOException {
        // Place your code here
    }

    @Override
    public void onCancelled() {
        // Place your code here
    }

    @Override
    public boolean isCancelled() {
        return isCancelled;
    }
});

You can cancel file uploading by calling fileStore.cancelUploading().

isCancelled = true;
fileStore.cancelUploading();

Downloading

The first change in the download API is the FileId was chnaged to FileMetadata in the first parameter. The second change is callback has changed from MediaHttpUploader to AsyncUploaderProgressListener<FileMetaData>, also were added onCancelled() and isCancelled() methods in callback. It was added because v3 has a possibility to use resuming file uploading and downloading.

v2.x

FileOutputStream fos= new FileOutputStream("mug.png");
kinveyClient.file().download("myFileID", fos, new DownloaderProgressListener() {
    @Override
    public void onSuccess(Void result) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable error) {
        // Place your code here
    }

    @Override
    public void progressChanged(MediaHttpDownloader downloader) throws IOException {
        // Place your code here
        // any updates to UI widgets must be done on the UI thread
    }
});

v3.x

FileOutputStream fos = new FileOutputStream("mug.png");
FileMetaData fileMetaDataForDownload = new FileMetaData();
fileMetaDataForDownload.setId("myFileID");
boolean isCancelled = false;
FileStore fileStore = kinveyClient.getFileStore(StoreType.CACHE);
fileStore.download(fileMetaDataForDownload, fos, new AsyncDownloaderProgressListener<FileMetaData>() {

    @Override
    public void onSuccess(FileMetaData fileMetaData) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable throwable) {
        // Place your error handler here
    }

    @Override
    public void progressChanged(MediaHttpDownloader mediaHttpDownloader) throws IOException {
        // Place your code here
    }

    @Override
    public void onCancelled() {
        // Place your code here
    }

    @Override
    public boolean isCancelled() {
        return isCancelled;
    }
});

You can cancel file downloading by calling fileStore.cancelDownloading().

isCancelled = true;
fileStore.cancelDownloading();

Removing

The first change in the delete API is the name of the delete method has changed from delete to remove. The second change is callback has changed from KinveyClientCallback to KinveyDeleteCallback.

v2.x

AsyncFile asyncFile = kinveyClient.file();
asyncFile.delete(fileMetaData, new KinveyClientCallback<KinveyDeleteResponse>() {
    @Override
    public void onSuccess(KinveyDeleteResponse kinveyDeleteResponse) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable throwable) {
        // Place your error handler here
    }
});

v3.x

FileStore fileStore = kinveyClient.getFileStore(StoreType.CACHE);
fileStore.remove(fileMetaData, new KinveyDeleteCallback() {
    @Override
    public void onSuccess(Integer integer) {
        // Place your code here
    }

    @Override
    public void onFailure(Throwable throwable) {
        // Place your error handler here
    }
});

File Store clearing

In v3 the File Store is cleared by calling the clearCache() method on FileStore object, instead calling clearFileStorage() method on AsyncFile object in v2.

v2.x

AsyncFile asyncFile = kinveyClient.file();
asyncFile.clearFileStorage();

v3.x

FileStore fileStore = kinveyClient.getFileStore(StoreType.CACHE);
fileStore.clearCache();

Get Started

For more information take a look at the all of our DevCenter Guides. If you have any issues or need help, please reach out to us using Kinvey Support. To get started developing great apps, take a look at our Getting Started Guide.

Got a question?