Git Product home page Git Product logo

snappydb's Introduction

SnappyDB

SnappyDB is a key-value database for Android it's an alternative for SQLite if you want to use a NoSQL approach.

It allows you to store and get primitive types, but also a Serializable object or array in a type-safe way.

SnappyDB can outperform SQLite in read/write operations. benchmark

SnappyDB is based on leveldb and use snappy compression algorithm, on redundant content you could achieve a good compression ratio

Check out the Demo App PlayStore

Usage

try {
   DB snappydb = DBFactory.open(context); //create or open an existing database using the default name
   
   snappydb.put("name", "Jack Reacher"); 
   snappydb.putInt("age", 42);  
   snappydb.putBoolean("single", true);
   snappydb.put("books", new String[]{"One Shot", "Tripwire", "61 Hours"}); 
   
   String 	 name   =  snappydb.get("name");
   int 	   age    =  snappydb.getInt("age");
   boolean  single =  snappydb.getBoolean("single");
   String[] books  =  snappydb.getArray("books", String.class);// get array of string
   	
   snappydb.close();
   
   } catch (SnappydbException e) {
   }

For more recipes please take a look at the Cookbook.

With SnappyDB you could seamlessly store and retrieve your object/array, it uses Kryo serialization which is faster than the regular Java serialization.

Installation

SnappyDB uses native code for performance, it's available as an Android Library Project AAR.

dependencies {
    compile 'com.snappydb:snappydb-lib:0.5.2'
    compile 'com.esotericsoftware.kryo:kryo:2.24.0'
}

or

Manual:

  • Download JAR file and other folders from here
  • Put all the files and folders in the libs subfolder of your Android project
libs
├───|── snappydb-0.5.2.jar
    |── armeabi
    │   └── libsnappydb-native.so
    ├── armeabi-v7a
    │   └── libsnappydb-native.so
    ├── mips
    │   └── libsnappydb-native.so
    └── x86
        └── libsnappydb-native.so

Cookbook

Common tasks snippets

Create database

Create using the default name
 DB snappydb = DBFactory.open(context);
Create with a given name
 DB snappydb = DBFactory.open(context, "books");

SnappyDB use the internal storage to create your database. It creates a directory containing all the necessary files Ex: /data/data/com.snappydb/files/mydatabse

Using the builder pattern
 DB snappyDB = new SnappyDB.Builder(context)
                    .directory(Environment.getExternalStorageDirectory().getAbsolutePath()) //optional
                    .name("books")//optional
                    .build();

directory Specify the location of the database (sdcard in this example)

Close database

snappydb.close();

Destroy database

snappydb.destroy();

Insert primitive types

snappyDB.put("quote", "bazinga!");

snappyDB.putShort("myshort", (short)32768);

snappyDB.putInt("max_int", Integer.MAX_VALUE);

snappyDB.putLong("max_long", Long.MAX_VALUE);

snappyDB.putDouble("max_double", Double.MAX_VALUE);

snappyDB.putFloat("myfloat", 10.30f);

snappyDB.putBoolean("myboolean", true);

Read primitive types

String quote      = snappyDB.get("quote");

short myshort     = snappyDB.getShort("myshort");

int maxInt        = snappyDB.getInt("max_int");

long maxLong      = snappyDB.getLong("max_long");

double maxDouble  = snappyDB.getDouble("max_double");

float myFloat     = snappyDB.getFloat("myfloat");

boolean myBoolean = snappyDB.getBoolean("myboolean");

Insert Serializable

AtomicInteger objAtomicInt = new AtomicInteger (42);
snappyDB.put("atomic integer", objAtomicInt);

Insert Object

MyPojo pojo = new MyPojo ();
snappyDB.put("my_pojo", pojo);

Note: MyPojo doesn't have to implement Serializable interface

Read Serializable

 AtomicInteger myObject = snappyDB.get("atomic integer", AtomicInteger.class);

Read Object

MyPojo myObject = snappyDB.getObject("non_serializable", MyPojo.class);

Note: MyPojo doesn't have to implement Serializable interface

Insert Array

Number[] array = {new AtomicInteger (42), new BigDecimal("10E8"), Double.valueOf(Math.PI)};

snappyDB.put("array", array);

Read Array

Number [] numbers = snappyDB.getObjectArray("array", Number.class);

Check Key

boolean isKeyExist = snappyDB.exists("key");

Delete Key

snappyDB.del("key");

Keys Search

By Prefix
snappyDB.put("android:03", "Cupcake"); // adding 0 to maintain lexicographical order
snappyDB.put("android:04", "Donut");
snappyDB.put("android:05", "Eclair");
snappyDB.put("android:08", "Froyo");
snappyDB.put("android:09", "Gingerbread");
snappyDB.put("android:11", "Honeycomb");
snappyDB.put("android:14", "Ice Cream Sandwich");
snappyDB.put("android:16", "Jelly Bean");
snappyDB.put("android:19", "KitKat");

String [] keys = snappyDB.findKeys("android");
assert keys.length == 9;

keys = snappyDB.findKeys("android:0");
assert keys.length == 5;

assert snappyDB.get(keys[0]).equals("Cupcake");
assert snappyDB.get(keys[1]).equals("Donut");
assert snappyDB.get(keys[2]).equals("Eclair");
assert snappyDB.get(keys[3]).equals("Froyo");
assert snappyDB.get(keys[4]).equals("Gingerbread");

keys = snappyDB.findKeys("android:1");
assert keys.length == 4;

assert snappyDB.get(keys[0]).equals("Honeycomb");
assert snappyDB.get(keys[1]).equals("Ice Cream Sandwich");
assert snappyDB.get(keys[2]).equals("Jelly Bean");
assert snappyDB.get(keys[3]).equals("KitKat");
By Range [from .. to]
  • both 'FROM' & 'TO' keys exist
keys = snappyDB.findKeysBetween("android:08", "android:11");
assertEquals(3, keys.length);
assertEquals("android:08", keys[0]);
assertEquals("android:09", keys[1]);
assertEquals("android:11", keys[2]);
  • 'FROM' key exist, but not the `TO
keys = snappyDB.findKeysBetween("android:05", "android:10");
assertEquals(3, keys.length);
assertEquals("android:05", keys[0]);
assertEquals("android:08", keys[1]);
assertEquals("android:09", keys[2]);
  • 'FROM' key doesn't exist but the 'TO' key do
keys = snappyDB.findKeysBetween("android:07", "android:09");
assertEquals(2, keys.length);
assertEquals("android:08", keys[0]);
assertEquals("android:09", keys[1]);
  • both 'FROM' & 'TO' keys doesn't exist
keys = snappyDB.findKeysBetween("android:13", "android:99");
assertEquals(3, keys.length);
assertEquals("android:14", keys[0]);
assertEquals("android:16", keys[1]);
assertEquals("android:19", keys[2]);
With offset and limit
//return all keys starting with "android" after the first 5
keys = snappyDB.findKeys("android", 5);
assertEquals(4, keys.length);
assertEquals("android:11", keys[0]);
assertEquals("android:14", keys[1]);
assertEquals("android:16", keys[2]);
assertEquals("android:19", keys[3]);

//return 3 first keys starting with "android"
keys = snappyDB.findKeys("android", 0, 3);
assertEquals(3, keys.length);
assertEquals("android:03", keys[0]);
assertEquals("android:04", keys[1]);
assertEquals("android:05", keys[2]);

//return the fourth key starting with "android" (offset 3, limit 1)
keys = snappyDB.findKeys("android", 3, 1);
assertEquals(1, keys.length);
assertEquals("android:08", keys[0]);

//return the two first keys between android:14 and android:99
keys = snappyDB.findKeysBetween("android:14", "android:99", 0, 2);
assertEquals(2, keys.length);
assertEquals("android:14", keys[0]);
assertEquals("android:16", keys[1]);

//return the third key (offset 2, limit 1) after android:10 before android:99
keys = snappyDB.findKeysBetween("android:10", "android:99", 2, 1);
assertEquals(1, keys.length);
assertEquals("android:16", keys[0]);

Keys Count

Counting is quicker than extracting values (if you don't need them). Especially on very big collections.

By Prefix
assertEquals(9, snappyDB.countKeys("android"));
assertEquals(5, snappyDB.countKeys("android:0"));
By Range [from .. to]
assertEquals(3, snappyDB.countKeysBetween("android:08", "android:11"));
assertEquals(3, snappyDB.countKeysBetween("android:13", "android:99"));

Iterators

Each time you use the offset & limit arguments, the engine makes the query and then scrolls to your offset. Which means that the bigger the offset is, the longer the query will take. This is not a problem on small collections, but on very large collections, it is.

An iterator keeps it's position in the key collection and can be asked for the next key at any time. It is therefore better to use an iterator on very large collections.

Iterators work on DB snapshot, which means that if you add or delete value in / from the DB, the iterators will not see those changes.

Please note that iterators given by the SnappyDB are closeable and need to be closed once finished with. As iterators work on a DB snapshot, not closing them is a serious memory leak.

// An iterator to all keys
it = snappyDB.allKeysIterator();
/*...*/
it.close();

// An iterator to all keys in reverse order
it = snappyDB.allKeysReverseIterator();
/*...*/
it.close();

// An iterator to all keys including and after android:14
it = snappyDB.findKeysIterator("android:14");
/*...*/
it.close();

// An iterator to all keys from android:05 to android:10
it = snappyDB.findKeysBetweenIterator("android:05", "android:10");
/*...*/
it.close();

// An iterator to all keys from android:09 to android:05 in reverse order
it = snappyDB.findKeysBetweenReverseIterator("android:09", "android:05");
/*...*/
it.close();

Here are the methods implemented in KeyIterator :

public boolean hasNext(); // Whether or not this is the last key.
public String[] next(int max); // Get an array of next keys (maximum [max] keys).
void close(); // Closes the iterator.
Iterable<String[]> byBatch(int size); // Get an iterable of key batch, each batch of maximum [size] keys.

Iterators work on key batchs (key arrays) and not directly on keys. You may iterate on all keys with the form:

for (String[] batch : db.findKeysIterator("android").byBatch(BATCH_SIZE)) {
    for (String key : batch) {
        /*...*/
    }
}

Please note that you should use the byBatch iterable to process all keys only on large collections. On reasonably small collections, using the array based APIs (findKeys and findKeysBetween) with the form for (String key : db.findKeys("android")) is a lot more efficient.
Iterators should only be used to process large collections or for collection paging view / access.

License

SnappyDB is opensource, contribution and feedback are welcomed

Copyright 2013 Nabil HACHICHA.

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.

Follow @nabil_hachicha

<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-46288191-1', 'github.com'); ga('send', 'pageview'); </script>

Android Arsenal

snappydb's People

Contributors

ben-j69 avatar days avatar jason-cooke avatar manish05 avatar nhachicha avatar salomonbrys avatar simpleton avatar yonghoon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

snappydb's Issues

com.esotericsoftware.kryo.KryoException: java.lang.IndexOutOfBoundsException

11-08 22:37:05.412 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ com.esotericsoftware.kryo.KryoException: java.lang.IndexOutOfBoundsException: Invalid index 104, size is 11 11-08 22:37:05.412 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ Serialization trace: 11-08 22:37:05.412 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ auditItems (com.cloudjay.cjay.model.Session) 11-08 22:37:05.412 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:125) 11-08 22:37:05.412 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:528) 11-08 22:37:05.422 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:657) 11-08 22:37:05.422 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at com.snappydb.internal.DBImpl.getObject(DBImpl.java:276) 11-08 22:37:05.422 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at com.cloudjay.cjay.DataCenter.uploadImportSession(DataCenter.java:1110) 11-08 22:37:05.432 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at com.cloudjay.cjay.task.job.UploadSessionJob.onRun(UploadSessionJob.java:141) 11-08 22:37:05.432 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at com.path.android.jobqueue.BaseJob.safeRun(BaseJob.java:109) 11-08 22:37:05.432 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at com.path.android.jobqueue.JobHolder.safeRun(JobHolder.java:60) 11-08 22:37:05.432 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at com.path.android.jobqueue.executor.JobConsumerExecutor$JobConsumer.run(JobConsumerExecutor.java:209) 11-08 22:37:05.442 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at java.lang.Thread.run(Thread.java:856) 11-08 22:37:05.472 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ Caused by: java.lang.IndexOutOfBoundsException: Invalid index 104, size is 11 11-08 22:37:05.472 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251) 11-08 22:37:05.482 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at java.util.ArrayList.get(ArrayList.java:304) 11-08 22:37:05.482 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at com.esotericsoftware.kryo.util.MapReferenceResolver.getReadObject(MapReferenceResolver.java:42) 11-08 22:37:05.482 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at com.esotericsoftware.kryo.Kryo.readReferenceOrNull(Kryo.java:805) 11-08 22:37:05.492 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:677) 11-08 22:37:05.492 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:106) 11-08 22:37:05.492 22269-22925/com.cloudjay.cjay.dev W/System.err﹕ ... 9 more

Sorry for pasting a lot of text but I just want to provide you full stack trace.

I face this problem when I try to call getObject() from multi-thread. Then it throw this Exception and say that:

 com.snappydb.SnappydbException: Maybe you tried to retrieve an array using this method ? please use getObjectArray instead java.lang.IndexOutOfBoundsException: Invalid index 104, size is 31
    Serialization trace:
    auditItems (com.cloudjay.cjay.model.Session)
            at com.snappydb.internal.DBImpl.getObject(DBImpl.java:280)
            at com.cloudjay.cjay.DataCenter.uploadImportSession(DataCenter.java:1110)```

Add dedicated Serializer for java.util.Date

Hi there,

thanks for creating SnappyDB, it's absolutely awesome. I'm using it for caching data retrieved from a REST API (wrote a little blog post about first impressions here).

At this point, all of my model classes are structured such that Kryo can serialize them nicely (mostly simple POJOs). However, I recently added java.util.Date fields to some of them. It turns out that SnappyDB fails to properly store and retrieve them. SnappyDB does not complain when storing the data but throws Unable to find class: java.util.Date upon trying to deserialize it.

This seems be due to this known issue, which - as the Kryo authors point out - is easily remedied by using the custom DateSerializer that comes with Kryo. However, SnappyDB does not seem to provide a way to configure this.
My question is thus: Could you enhance SnappyDB so that it would automatically register java.util.date fields using

kryo.register(Date.class, new DateSerializer());

instead of the normal registration?
I believe this is what anybody including a Java date type in their model would want.

Is opening a SnappyDB database an expensive operation?

The documentation is not clear on it. Should i hold a static instance to DBFactory.open(context) somewhere and always use that, or can i inexpensively call DBFactory.open(context) and close the instance whenever i have need for it. ( for instance, saving data in a much called rest-api call )

Custom keys sorting and/or findKeyContains()?

Hi!
I've been poking around with your by all means awesome library and found one major issue:
All keys are sorted by alphabetical order. OK, it's not that big a deal, if one could find certain key, which "contains" exact id or something. I've googled leveldb and found that it has custom comparators. Is it implemented it your library or it just me who missed that? As an example, one would have temporary list of items which shouldn't be persisted over app relaunches (news app or whatever) with endless scroll. And every time one inserts new data in db it would be messed up in the displaying list. Maybe one could start key with currentTime (with some leading zero, just in case) or create own indexing, but this will be obsolete if by tap one should open details by object's id (which one won't be able to retrieve from db).
I understand, that maybe NoSQL solution is not the best for the case I described, but if there is a way, why not?)

getObjectArray() returns List with empty values

getObjectArray() always returns a List with all the previous saved items but without values. Let's say that my Category Class has a name attribute and id attribute, when I save them everything seems to works properly but when I try to retrieve them I get the same items without name and id values, for Strings are nulls and for integers zero.

Maybe I am doing something wrong, the same thing happens with getArray() method.

public class CategoryHelperDao {

    private final String KEY = "category_list";

    private DB snappyDb;

    @Inject
    private Context context;

    @Inject
    public CategoryHelperDao(Context context) throws SnappydbException {
        Kryo kryo=new Kryo();
        kryo.setDefaultSerializer(TaggedFieldSerializer.class);
        snappyDb = DBFactory.open(context,kryo);
    }

    public void saveCategoryList(List<Category> categoryList) throws SnappydbException {
        snappyDb.put(KEY, categoryList.toArray());
        snappyDb.close();
    }


    public List<Category> queryForAllCategory() throws SnappydbException {
        Category[] categoryList = snappyDb.getObjectArray(KEY, Category.class);
        return Arrays.asList(categoryList);
    }


    public void deleteCategory(Category category) throws SnappydbException {
        snappyDb.del(category.getSysName());
    }

    public void deleteCategoryList(List<Category> categoryList) throws SnappydbException {
        for (Category category: categoryList){
            deleteCategory(category);
        }
    }

    public void close() throws SnappydbException {
        snappyDb.close();
    }

}

Cannot resolve the library in gradle

Failed to resolve: com.snappydb:snappydb-lib:0.5.2-SNAPSHOT

or

Failed to resolve: com.snappydb:snappydb-lib:0.5.2

both variants give the same result.

Support full text search

Hi @SalomonBrys, thank you for reading my issue. In case you are working on new pull request, can I ask you a favor for adding full text search to snappydb. It will be great if snappydb has this feature.

Best regards.

Support for write_batch.cc/h

I noticed that there is a write_batch.cc that allows users to perform multiple write calls atomically. However, JNI doesn't seem to expose any methods to access this feature. I was wondering if the JNI could be extended to incorporate these features.

Thank you!

Encrypting data

Is there any solution for data encryption while using SnappyDB? Or at least any ideas how it should/may be done.
Also, how huge performance impact would be (at least in theory)?
Unfortunatly, Google does not really help.

How Many Key Prefixes?

How many key prefixes can you have? Is it just one or many?

Is foo:bar:baz:1 valid or just foo:1?

com.snappydb.SnappydbException: Your database is still open, please close it before

I have closed the database, verified that the database the close method is still being called and yet, I am still facing this issue.

if (snappydb != null && snappydb.isOpen()) {
    snappydb.close();
}

this is how I am opening the database

if(name.equals(Constant.DB_DEFAULT))
    snappydb = DBFactory.open(App.getInstance());
else
    snappydb = DBFactory.open(App.getInstance(), name);

UnsatisfiedLinkError

Here is the error I obtain on some devices like Galaxy S4, note 2, xperia M...

java.lang.UnsatisfiedLinkError: Couldn't load snappydb-native from loader dalvik.system.PathClassLoader[dexPath=/data/app/com.jbl.android.spotimote-4.apk,libraryPath=/data/app-lib/com.jbl.android.spotimote-4]: findLibrary returned null
at java.lang.Runtime.loadLibrary(Runtime.java:358)
at java.lang.System.loadLibrary(System.java:526)
at com.snappydb.internal.DBImpl.(DBImpl.java:38)
at com.snappydb.DBFactory.open(DBFactory.java:40)
at com.snappydb.DBFactory.open(DBFactory.java:65)
at com.snappydb.DBFactory.open(DBFactory.java:77)
at com.jbl.android.spotimote.Lookup.ItemsCache.(ItemsCache.java:31)
at com.jbl.android.spotimote.SpotimoteService.bootService(SpotimoteService.java:319)
at com.jbl.android.spotimote.SpotimoteService.onStartCommand(SpotimoteService.java:230)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2860)
at android.app.ActivityThread.access$2200(ActivityThread.java:161)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1362)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)

SnappyDB with SQLiteDB

First of all I'm very impressed with this library's ease of use and performance. In my app, I'm using another library which is very much required but it uses SQLiteDB internally. Now after integrating this with my present app, which has SnappyDB, I get an error -

java.lang.UnsatisfiedLinkError: Couldn't load snappydb-native from loader dalvik.system.PathClassLoader[dexPath=/data/app/com.package.name-84.apk,libraryPath=/data/app-lib/com.package.name-84]: findLibrary returned null

Is there any way I can integrate both snappyDB abd SQLiteDB in my app and make both work.

Issues with persisting objects over multiple network calls.

Hi, I am a beginner on Android and I have been using SnappyDb for my project.
I have a lot of network requests using retrofit. I am able to get the objects related to JSON passed over the network in my app.
Now the issue is that upon receipt of the object i try to persist them, and they get persisted for few calls and later i start getting "com.snappydb.SnappydbException: Your database is still open, please close it" this error.

Is there a simpler way to check whether a db is open or not, and also if there are any such inbuilt methods to handle these situations.

Problem when importing this lib (UNEXPECTED TOP-LEVEL EXCEPTION:)

I'm trying to import the library on my project, but I'm getting that exception.

Error:Execution failed for task ':app:dexDevDebug'.

com.android.ide.common.internal.LoggedErrorException: Failed to run command:
C:\android\sdk\build-tools\21.1.1\dx.bat --dex --no-optimize --output C:\Users\Danilo\Documents\AndroidStudioProjects\Contele GE 2.0 Mobile\app\build\intermediates\dex\dev\debug --input-list=C:\Users\Danilo\Documents\AndroidStudioProjects\Contele GE 2.0 Mobile\app\build\intermediates\tmp\dex\dev\debug\inputList.txt
Error Code:
2
Output:
UNEXPECTED TOP-LEVEL EXCEPTION:
com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
at com.android.dx.merge.DexMerger$6.updateIndex(DexMerger.java:502)
at com.android.dx.merge.DexMerger$IdMerger.mergeSorted(DexMerger.java:277)
at com.android.dx.merge.DexMerger.mergeMethodIds(DexMerger.java:491)
at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:168)
at com.android.dx.merge.DexMerger.merge(DexMerger.java:189)
at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:454)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:302)
at com.android.dx.command.dexer.Main.run(Main.java:245)
at com.android.dx.command.dexer.Main.main(Main.java:214)
at com.android.dx.command.Main.main(Main.java:106)

I'm not Gradle expert so I could'n find a solution.

NoSuchMethodError exception when trying to open the database

Hi,
I'm trying to use snappydb but some problems occurs.
my code is:

public void TrySnappy() throws SnappydbException{
    DB snappydb = DBFactory.open(this.getBaseContext());
}

but this exception is thrown:
java.lang.NoSuchMethodError: com.esotericsoftware.kryo.Kryo.setAsmEnabled
at com.snappydb.internal.DBImpl.(DBImpl.java:51)
at com.snappydb.DBFactory.open(DBFactory.java:40)
at com.snappydb.DBFactory.open(DBFactory.java:65)
at com.snappydb.DBFactory.open(DBFactory.java:77)
......
thanks

Check if a key is present

Hi,

Thanks for the lib, I just included it in my project to make some tests and so far it looks nice and really fast. It would be nice to have a way to check if a key is present in the DB. Currently we have to use one of the get methods and catch an exception. There are 2 main problems with that:

  • An exception is extremely expensive for the JVM and a lot slower compared to a simple boolean check.
  • There's no way to know if the exception comes from an IO error or from a key being not present.

It makes twice IO operations to check-then-get, so maybe you could just return "null" in case a key is not present. What do you think?

Using Parcelable instead of serializable

I may sound noob here but I have read some where that parcelable is 10 times faster than serializable for android. So why using Serializable Object instead of Parcelable objects.?

findKeysIterator behavior

Let's say I have following keys in my single DB:

user:10001
user:10002
user:10003
user:10004
post:500
post:501
post:502
post:503

As you can see, the prefixes in the keys indicate stored object type. However when I use findKeysIterator, I find strange result:

String PREFIX = "post";
iterator = snappyDB.findKeysIterator(PREFIX);
for (String[] batch : iterator.byBatch(BATCH_SIZE)) {
    for (String key : batch) {
        Log.d("KEY", key);
    }
}

The logged output is surprisingly shows all keys including "user"-prefixed ones. Is this the correct behavior?

I was thinking to separate my object types into different database, but just realized that it might not work well (issue #26). My current workaround is by adding if(key.startsWith(PREFIX) inside the innermost for-loop.

Is there any cleaner way to achieve my desired result? (i.e. find keys with specified prefix)

Migration

Let's say that the structure of an object changes in a new version of my app (a new field is added/removed). Is there any way to handle this migration so old data is not lost?

Thank you.

Multiple tables

Is it possible to have multiple tables within a single database?

If yes, how can I accomplish that?

Thanks.

Failed to open/create database: IO error: lock

Hi,

I'm facing some concurrency issue whereby my threads are accessing the dB concurrently. Is there a snapshot created everytime the dB is opened?

com.snappydb.SnappydbException: Failed to open/create database: IO error: lock LOCK: already held by process

Default values

Hi, I'm using SnappyDB in my app as a store for some key value pairs.
I'm wrapping the DB interface with my own interface with default values in it's api. Example:

String get(String key, String defaultValue);

I noticed the only way to know if a key doesn't exist in the DB is to catch an exception and assume the reason for it was a missing key (which is a wild assumption).

Any ideas on how I could implement the default value feature in a less ugly, more accurate way that won't hide relevant exceptions?

Thanks.

min sdk version

is there a reason for min sdk to be 9 ? I modified it to be 7 and it seemed to work.

Question: Overuse of Exception

This is more of a question of design rather than a problem, but why does every method basically throw an exception?

I think overall the library should reduce the use of exceptions as it causes unnecessary try and catch blocks.

It does make sense in some cases to fail if it's really an issue, but it seems that all of the get* methods should just return null or the value if found or if there's not an issue.

For put methods you can return boolean true or false if it was successful or a problem.

It just seems like exceptions should be used for either really critical or dumb mistakes (IE I forgot to close the database connection) instead of normal things where users of the library should check their code themselves (IE use the right get method).

how to use snappydb with Raizlabs/Singleton library?

https://github.com/Raizlabs/Singleton
I would like to create a singleton out of snappydb using this lib

heres the setup:

Singleton<TestObject> testObjectSingleton = new Singleton.Builder<>()
        .tag("Test")
        .type(TestObject.class)
        .persists(true)
        .build();

or 

MyClass myObject = new Singleton(TestObject.class).getInstance();

where would this:

DB snappydb = DBFactory.open(context);

go using the examples above?

Error while testing

Hello,

I use SnappyDB in my android project, it works well. But when I want to test it (with robolectric) I have 2 errors :
java.lang.NoClassDefFoundError: Could not initialize class com.snappydb.DBFactory
java.lang.UnsatisfiedLinkError: no snappydb-native in java.library.path

In my build.gradle I have the same dependencies that the README. I don't find the problem...

findKeys that support limit and offset

Hi Hachicha,

I'm using SnappyDB in my new app and I'm building a feature like pagination that need index, limit and offset/skip. Do you have any idea?

How can I obtain it with Snappy or where can I modify to make custom findKeys? Please teach me.

Thank you.

Is SnappyDB Fast enough for the UI thread

How would the performance of SnappyDB compare to the Android Resource system for looking a string via a key (resource ID)? Is it fast enough to do on the UI thread like the Android Resource system?

SharedPreferences comparison

Hi!

First of all, good job! Your library looks incredible, I think it will become a very good alternative to save data in our devices.

It would be great having a comparison chart between using shared preferences and SnappyDB. Even more comparing deserialization with Gson or jackson and using your serialization. I think it will encourage people to use this!

I really want to try it but first I would like to know if it's better deserialize my own Strings from SharedPreferences with Gson, or using Kryo ;-)

Thanks,

Problems with Range Search: FROM and TO not exists, no record founded

Hi,
I have a lot of records entered into the database, where each of them has key with ISO8601 string.

I have to query before a certain date and between two dates passed as ISO8601 string. In my case, the FROM and TO keys not exists. I receive no records from the query.

There are some rules that I don't know?

Support for List

Hi,

This library already looks great, but I have read all the docs you provided but I didn't read anywhere that this library supports any type of List like Array List etc.

Can you please let me know if it supports?

Thank you.

Weird exception

Getting this weird exception after restarting my AVD that was running tests.

Caused by: com.snappydb.SnappydbException: Failed to open/create database: Corruption: no meta-nextfile entry in descriptor at com.snappydb.internal.DBImpl.__open(Native Method) at com.snappydb.internal.DBImpl.<init>(DBImpl.java:53) at com.snappydb.DBFactory.open(DBFactory.java:40) at com.snappydb.SnappyDB$Builder.build(SnappyDB.java:95)

Could not find class 'sun.nio.ch.DirectBuffer'

I got the following though the snappydb still works. Do I need to worry about this?

05-28 12:01:35.836 1015-1015/com.hello.test.app E/dalvikvm﹕ Could not find class 'sun.nio.ch.DirectBuffer', referenced from method com.esotericsoftware.kryo.util.UnsafeUtil.releaseBuffer
05-28 12:01:35.836 1015-1015/com.hello.test.app W/dalvikvm﹕ VFY: unable to resolve check-cast 2143 (Lsun/nio/ch/DirectBuffer;) in Lcom/esotericsoftware/kryo/util/UnsafeUtil;
05-28 12:01:35.836 1015-1015/com.hello.test.app D/dalvikvm﹕ VFY: replacing opcode 0x1f at 0x0008
05-28 12:01:35.846 1015-1015/com.hello.test.app I/dalvikvm﹕ Could not find method sun.misc.Unsafe.addressSize, referenced from method com.esotericsoftware.kryo.serializers.FieldSerializerUnsafeUtil.fieldSizeOf
05-28 12:01:35.846 1015-1015/com.hello.test.app W/dalvikvm﹕ VFY: unable to resolve virtual method 15175: Lsun/misc/Unsafe;.addressSize ()I
05-28 12:01:35.846 1015-1015/com.hello.test.app D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x002d

com.snappydb.SnappydbException: Maybe you tried to retrieve an array using this method ? please use getObjectArray instead java.lang.IndexOutOfBoundsException: Invalid index 104, size is 7

Im getting this error in random cases, when app crash, i do same steps and works fine sometimes.
What can be happenning?

com.snappydb.SnappydbException: Maybe you tried to retrieve an array using this method ? please use getObjectArray instead java.lang.IndexOutOfBoundsException: Invalid index 104, size is 7
Serialization trace:
date (com.firext.android.model.bbdd.DBWork)
at com.snappydb.internal.DBImpl.getObject(DBImpl.java:280)
at com.firext.android.data.NoSQLWorksPersistenceImpl.getWorkById(NoSQLWorksPersistenceImpl.java:68)
at com.firext.android.data.NoSQLWorksPersistenceImpl.getReportInWorkById(NoSQLWorksPersistenceImpl.java:143)
at com.firext.android.jobs.GetReplieGroupsForWorkAndReport.onRun(GetReplieGroupsForWorkAndReport.java:31)
at com.path.android.jobqueue.BaseJob.safeRun(BaseJob.java:108)
at com.path.android.jobqueue.JobHolder.safeRun(JobHolder.java:60)
at com.path.android.jobqueue.executor.JobConsumerExecutor$JobConsumer.run(JobConsumerExecutor.java:201)
at java.lang.Thread.run(Thread.java:841)

Packaging problem

Not sure what's going on here, even after following the instructions to exclude...

Error:duplicate files during packaging of APK /Users/amchang/Development/projects/hedonismbot/groups/build/outputs/apk/groups-development-debug-unaligned.apk
    Path in archive: lib/armeabi/libsnappydb-native.so
    Origin 1: /Users/amchang/Development/projects/hedonismbot/groups/src/main/jniLibs/armeabi/libsnappydb-native.so
    Origin 2: /Users/amchang/Development/projects/hedonismbot/groups/build/intermediates/exploded-aar/com.snappydb/snappydb-lib/0.4.0/jni/armeabi/libsnappydb-native.so
You can ignore those files in your build.gradle:
    android {
      packagingOptions {
        exclude 'lib/armeabi/libsnappydb-native.so'
      }
    }
Error:Execution failed for task ':groups:packageDevelopmentDebug'.
> Duplicate files copied in APK lib/armeabi/libsnappydb-native.so
    File 1: /Users/amchang/Development/projects/hedonismbot/groups/src/main/jniLibs/armeabi/libsnappydb-native.so
    File 2: /Users/amchang/Development/projects/hedonismbot/groups/src/main/jniLibs/armeabi/libsnappydb-native.so
Information:BUILD FAILED

Complex objects with arrays

Models with array attributes like

class Person {
public int Id;
public String Name;
public Phone[] Phones;
}

class Phone {
public int Id;
public String Number;
}

cannot be deserialized by Kryo.

Allow registration of custom serializers for Kryo

Kryo is based on several serializers (one per class type). The library provide a bunch of them for common types.

Currently and for non native type, SnappyDB creates a new instance of Kryo (shouldn't we create a singleton instance the first time we need it ?) and register a serializer according to the given type.

But, there is no way to add custom serializer in order to handle some external libs (like Jodatime for example). @magro created a project providing some extra serializers, but we can't uses them right now.

So, it may be great to have a way to configure the Kryo instance. It could be done via a builder method which can be overridden if needed :

public class DBImpl {
  public void put(String key, Serializable value) ... {
    ..
    Kryo kryo = getKryoInstance();
    kryo.register(value.getClass());
    ...
  }

  protected Kryo getKryoInstance() {
    Kryo kryo = new Kryo();
    kryo.setAsmEnabled(true);
  }
  ..
}
public class MyDBImpl extends DBImpl {
  protected Kryo getKryoInstance() {
    Kryo kryo = super.getKryoInstance();
    kryo.register(DateTime.class, new JodaDateTimeSerializer());
  }
}

WDYT ?

Android app crashes when Proguard is enabled.

Hi,
I am using Proguard in my app, can you please help in adding the relevant Proguard rules?
We are getting exceptions such as these:

java.lang.IllegalArgumentException: Unable to create serializer "com.c.a.c.bg" for class: com.iam.nearer.model.Interest
       at com.esotericsoftware.kryo.factories.ReflectionSerializerFactory.makeSerializer()
       at com.esotericsoftware.kryo.factories.ReflectionSerializerFactory.makeSerializer()
       at com.esotericsoftware.kryo.Kryo.newDefaultSerializer()
       at com.esotericsoftware.kryo.Kryo.addDefaultSerializer()
       at com.esotericsoftware.kryo.Kryo.register()
       at com.snappydb.internal.DBImpl.close()
       at com.iam.nearer.fragments.BestHereFragment.getAllInterestsFromDB()
       at com.iam.nearer.fragments.BestHereFragment.getDataFromLocal()
       at com.iam.nearer.fragments.BestHereFragment.onCreateView()
       at android.support.v4.app.Fragment.performCreateView()
       at android.support.v4.app.FragmentManagerImpl.throwException()
       at android.support.v4.app.FragmentManagerImpl.throwException()
       at android.support.v4.app.BackStackRecord.run()
       at android.support.v4.app.FragmentManagerImpl.makeInactive()
       at android.support.v4.app.FragmentManagerImpl.executePendingTransactions()
       at android.support.v4.app.FragmentPagerAdapter.setPrimaryItem()
       at android.support.v4.view.ViewPager.initViewPager()
       at android.support.v4.view.ViewPager.populate()
       at android.support.v4.view.ViewPager.onMeasure()
       at android.view.View.measure(View.java:17448)
       at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:727)
       at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:463)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.support.v7.internal.widget.ActionBarOverlayLayout.onMeasure()
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
       at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
       at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
       at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2560)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2031)
       at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1189)
       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1402)
       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1077)
       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5884)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
       at android.view.Choreographer.doCallbacks(Choreographer.java:580)
       at android.view.Choreographer.doFrame(Choreographer.java:550)
       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
       at android.os.Handler.handleCallback(Handler.java:739)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:135)
       at android.app.ActivityThread.main(ActivityThread.java:5312)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
Caused by: java.lang.InstantiationException: class com.c.a.c.bg has no zero argument constructor
       at java.lang.Class.newInstance(Class.java:1563)
       at com.esotericsoftware.kryo.factories.ReflectionSerializerFactory.makeSerializer()
       at com.esotericsoftware.kryo.factories.ReflectionSerializerFactory.makeSerializer()
       at com.esotericsoftware.kryo.Kryo.newDefaultSerializer()
       at com.esotericsoftware.kryo.Kryo.addDefaultSerializer()
       at com.esotericsoftware.kryo.Kryo.register()
       at com.snappydb.internal.DBImpl.close()
       at com.iam.nearer.fragments.BestHereFragment.getAllInterestsFromDB()
       at com.iam.nearer.fragments.BestHereFragment.getDataFromLocal()
       at com.iam.nearer.fragments.BestHereFragment.onCreateView()
       at android.support.v4.app.Fragment.performCreateView()
       at android.support.v4.app.FragmentManagerImpl.throwException()
       at android.support.v4.app.FragmentManagerImpl.throwException()
       at android.support.v4.app.BackStackRecord.run()
       at android.support.v4.app.FragmentManagerImpl.makeInactive()
       at android.support.v4.app.FragmentManagerImpl.executePendingTransactions()
       at android.support.v4.app.FragmentPagerAdapter.setPrimaryItem()
       at android.support.v4.view.ViewPager.initViewPager()
       at android.support.v4.view.ViewPager.populate()
       at android.support.v4.view.ViewPager.onMeasure()
       at android.view.View.measure(View.java:17448)
       at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:727)
       at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:463)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.support.v7.internal.widget.ActionBarOverlayLayout.onMeasure()
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
       at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
       at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
       at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2560)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2031)
       at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1189)
       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1402)
       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1077)
       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5884)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
       at android.view.Choreographer.doCallbacks(Choreographer.java:580)
       at android.view.Choreographer.doFrame(Choreographer.java:550)
       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
       at android.os.Handler.handleCallback(Handler.java:739)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:135)
       at android.app.ActivityThread.main(ActivityThread.java:5312)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
Caused by: java.lang.NoSuchMethodException: <init> []
       at java.lang.Class.getConstructor(Class.java:531)
       at java.lang.Class.getDeclaredConstructor(Class.java:510)
       at java.lang.Class.newInstance(Class.java:1561)
       at com.esotericsoftware.kryo.factories.ReflectionSerializerFactory.makeSerializer()
       at com.esotericsoftware.kryo.factories.ReflectionSerializerFactory.makeSerializer()
       at com.esotericsoftware.kryo.Kryo.newDefaultSerializer()
       at com.esotericsoftware.kryo.Kryo.addDefaultSerializer()
       at com.esotericsoftware.kryo.Kryo.register()
       at com.snappydb.internal.DBImpl.close()
       at com.iam.nearer.fragments.BestHereFragment.getAllInterestsFromDB()
       at com.iam.nearer.fragments.BestHereFragment.getDataFromLocal()
       at com.iam.nearer.fragments.BestHereFragment.onCreateView()
       at android.support.v4.app.Fragment.performCreateView()
       at android.support.v4.app.FragmentManagerImpl.throwException()
       at android.support.v4.app.FragmentManagerImpl.throwException()
       at android.support.v4.app.BackStackRecord.run()
       at android.support.v4.app.FragmentManagerImpl.makeInactive()
       at android.support.v4.app.FragmentManagerImpl.executePendingTransactions()
       at android.support.v4.app.FragmentPagerAdapter.setPrimaryItem()
       at android.support.v4.view.ViewPager.initViewPager()
       at android.support.v4.view.ViewPager.populate()
       at android.support.v4.view.ViewPager.onMeasure()
       at android.view.View.measure(View.java:17448)
       at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:727)
       at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:463)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.support.v7.internal.widget.ActionBarOverlayLayout.onMeasure()
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
       at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
       at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5465)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
       at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2560)
       at android.view.View.measure(View.java:17448)
       at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2031)
       at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1189)
       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1402)
       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1077)
       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5884)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
       at android.view.Choreographer.doCallbacks(Choreographer.java:580)
       at android.view.Choreographer.doFrame(Choreographer.java:550)
       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
       at android.os.Handler.handleCallback(Handler.java:739)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:135)
       at android.app.ActivityThread.main(ActivityThread.java:5312)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)

Here are my Proguard rules:

# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\Program Files\Android\android-sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}
# Keep our interfaces so they can be used by other ProGuard rules.
# See http://sourceforge.net/p/proguard/bugs/466/
#-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip

# Do not strip any method/class that is annotated with @DoNotStrip
-keep @com.facebook.common.internal.DoNotStrip class *
-keepclassmembers class * {
    @com.facebook.common.internal.DoNotStrip *;
}
-dontwarn com.amazon.device.messaging.**
-dontwarn bo.app.**
-keep class bo.app.** { *; }
-keep class com.appboy.** { *; }
-keep class com.iam.nearer.model.** { *; }
#-keep class cn.pedant.** { *; }
-ignorewarnings

How can I use SnappyDB with Gradle?

I can add the snappydb-api in the dependencies but unsure how to add the native libraries in the dependencies.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.snappydb:snappydb-api:0.2.0'
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.