Giter Club home page Giter Club logo

simpleprovider's Introduction

SimpleProvider

Create simple ContentProviders for Android Applications reducing boilerplate code.

Build Status

Goals

Writing Content Providers in Android Applications can be really annoying. In most cases there is not much complexity in regards of the data. Still, you have to write a great deal of boilerplate code to get going. This library is intended to ease up the creation of very simple Content Providers using annotations.

Download

Grab the latest version from Maven Central

compile 'com.github.triplet.simpleprovider:simpleprovider:1.1.0'

We introduced a possibly incompatible change in version 1.1.0. See The Changelog for details.

Usage

SimpleProvider uses annotations on classes and fields to define the database structure. Everything else (database and table creation, URI matching, CRUD operations) is handled by the abstract class AbstractProvider.

Writing your own Provider

To write your own ContentProvider you have to extend the AbstractProvider class and implement the abstract method getAuthority():

public class BlogProvider extends AbstractProvider {

    protected String getAuthority() {
        return "com.example.blog.DATA";
    }

}

Next you will want to define the tables and columns that make up your data. To do so, create inner classes inside your BlogProvider and use the provided annotations @Table and @Column:

@Table
public class Post {

    @Column(value = Column.FieldType.INTEGER, primaryKey = true)
    public static final String KEY_ID = "_id";

    @Column(Column.FieldType.TEXT)
    public static final String KEY_TITLE = "title";
    
    @Column(Column.FieldType.TEXT)
    public static final String KEY_CONTENT = "content";

    @Column(Column.FieldType.TEXT)
    public static final String KEY_AUTHOR = "author";

}

@Table
public class Comment {

    @Column(value = Column.FieldType.INTEGER, primaryKey = true)
    public static final String KEY_ID = "_id";

    @Column(Column.FieldType.INTEGER)
    public static final String KEY_POST_ID = "post_id";
    
    @Column(Column.FieldType.TEXT)
    public static final String KEY_CONTENT = "content";

    @Column(Column.FieldType.TEXT)
    public static final String KEY_AUTHOR = "author";

}

In the example above we create a simple data structure for a blog application that has posts and comments on posts.

The @Table-Annotation registers a class as a database table. AbstractProvider will take care of creating tables called posts and comments. Note, how we used the plural version of the class name. You can override this behaviour by providing an additional String as the table name.

The @Column-Annotation defines a database column for that table. It requires a column type (One of Column.FieldType.INTEGER, Column.FieldType.TEXT, Column.FieldType.FLOAT or Column.FieldType.BLOB). You may also add SQL extras, e.g. to define a column as the primary key for that table as we did for Post.KEY_ID.

That's all. The AbstractProvider will handle the database creation and default CRUD operations for us.

Accessing your Provider

The above example creates two tables that can be accessed using the standard insert(), query(), update(), delete() operations provided by the ContentResolver class. AbstractProvider automatically handles the standard URIs that directly access a single table.

Based on the example above, and assuming your authority is something like com.example.blog.DATA, then your ContentProvider will automatically handle the following URIs:

com.example.blog.DATA/posts
com.example.blog.DATA/posts/*
com.example.blog.DATA/comments
com.example.blog.DATA/comments/*

Upgrading the database

We may find ourselves in the situation where we need to change our database schema after we have released our app. Let's assume, we want to add a column to the Posts table that holds the creation date for a post. We obviously need to update the Post class to define the additional column:

@Table
public class Post {

    // ... (previously defined columns)

    @Column(value = Column.FieldType.INTEGER, since = 2)
    public static final String KEY_CREATION_DATE = "creation_date";

}

Note, how we used the since-key of the @Column-Annotation to state that this column has been added to the database schema in version 2. To make sure all the upgrade routines are called we also have to override the getSchemaVersion() method:

@Override
protected int getSchemaVersion() {
    return 2;
}

Proguard

SimpleProvider uses Annotations and Reflection to create the SQL tables. For example we try to use the pluralized class names of your schema classes in a CREATE TABLE statement. Please make sure to add the following lines to your project-specific proguard rules:

# The AbstractProvider searches for inner classes annotated with @Table
# but proguard flattens nested classes. This line makes sure the structure
# is preserved.
-keepattributes InnerClasses

# Don't obfuscate the FieldType enum as those values are added
# to the CREATE TABLE statement directly
-keep enum de.triplet.simpleprovider.Column$FieldType { public *; }

# Do not obfuscate anything that is annotated with @Table or @Column
# so AbstractProvider can automatically generate the table and column names.
# (This line might be optional if you're fine with a table called 'a' and columns
# called 'a', 'b', 'c', 'd' and so forth).
-keep @de.triplet.simpleprovider.Table class * { @de.triplet.simpleprovider.Column *; }

Please note that these rules have not been fully tested so use them at your own risk.

License

 The MIT License (MIT)
 
 Copyright (c) 2014 Christian Becker
 Copyright (c) 2014 Björn Hurling

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.

simpleprovider's People

Contributors

bhurling avatar christiankatzmann avatar icedtoast avatar kimar 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

simpleprovider's Issues

Database Name

Hi there,

I was wondering what's the name of the Database simpleprovider creates, as i can't find it in the Docs. I have to override the query()-Method for In-App Search, so I can't rely on the Cursor returned by LoaderManager.

Many thanks in advance!

java.lang.RuntimeException: Unable to create application com.edcast.EdCastApplication: android.database.sqlite.SQLiteDiskIOException: disk I/O error (code 4874 SQLITE_IOERR_SHMSIZE): , while compiling: PRAGMA journal_mode

Crashed on Android 9.0(API lev 28).
java.lang.RuntimeException: Unable to create application com.Application: android.database.sqlite.SQLiteDiskIOException: disk I/O error (code 4874 SQLITE_IOERR_SHMSIZE): , while compiling: PRAGMA journal_mode

android.app.ActivityThread.handleBindApplication(ActivityThread.java:5954)
android.app.ActivityThread.access$1200(ActivityThread.java:200)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1673)
android.os.Handler.dispatchMessage(Handler.java:106)
android.os.Looper.loop(Looper.java:201)
android.app.ActivityThread.main(ActivityThread.java:6810)
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)

I have already tried setting WAL mode to enable and disable still facing the issue.

Here is the code which I have used in our project

public static DatabaseProvider sDatabaseProvider;

    public static DatabaseProvider getInstance(Context context) {
        if (sDatabaseProvider == null) {
            synchronized (DatabaseProvider.class) {
                if (sDatabaseProvider == null) {
                    sDatabaseProvider = new DatabaseProvider();
                }
            }
        }
        return sDatabaseProvider;
    }
// For enabling and disabling the WAL by increasing the database version so I can get the logs.
@Override
 protected void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
   // to enable VAL setting 
   // db.enableWriteAheadLogging();
   // to disable VAL setting
     db.disableWriteAheadLogging();
   // And for testing val setting I have verified using 
  // to check WAL settings. 
   boolean isWriteAheadLoggingEnabled = db.isWriteAheadLoggingEnabled();
 }

I have already upgraded the to 1.1.0 which is the latest one.
// com.github.triplet.simpleprovider:simpleprovider:1.1.0

Is there any solution for such kind of crashes? Thanks in advanced

min sdk

it's required min sdk 15
i want 14
and is there any way to use it with gradle instead of maven?
thanks

Upgrade to robolectric 2.3

I think it should be possible to upgrade to Robolectric 2.3. The only problem is that travis does not find the support library 19.0.1. This can be fixed by manually installing extra-android-m2repository before we build it. In contrast, 2.2 uses support library v7 which is on central and thus can be found during the build.

android.database.sqlite.SQLiteException: no such table

When I use the code as given in the example in my own project, I see an error on startup because a table does not exist:

Caused by: android.database.sqlite.SQLiteException: no such table: journeys (code 1): , while compiling: SELECT * FROM journeys

My provider looks like this:

public class JourneyProvider extends AbstractProvider {

    private static final int SCHEMA_VERSION = 1;

    protected String getAuthority() {
        return getContext().getString(R.string.authority);
    }

    @Table
    public class Journey {

        @Column(Column.FieldType.INTEGER)
        public static final String KEY_ID = "_id";

        @Column(Column.FieldType.TEXT)
        public static final String KEY_TITLE = "title";

    }

    @Override
    protected int getSchemaVersion() {
        return SCHEMA_VERSION;
    }
}

Make onCreate not be final

Please do not make the onCreate method final so I can override it to allow creation of views.
I would to:
public boolean onCreate() {
super.onCreate();
//mDatabase.createView...
}
Thanks.

DB Recreation Error

I noticed something. If I drop a Table when I implement Logout in my app and come back in, the data is stored, but it can't be accessible unless I quit the app and then open it again. Do you know what might be the cause. I tried to log that the data is being stored and I noticed it's. But, then why isn't getting accessible on first try?

Crash in release build using proguard

Application crashes when proguard is enabled in release build variant.
I created fork of library (https://github.com/mbajor/simpleprovider)
and added commit (https://github.com/mbajor/simpleprovider/commit/c109dc0c1f79edfaa0e5269af05ae7f0e3329170) to provide investigation of the issue by using simpleprovider-sample app.
Before run, uninstall simpleprovider-sample or clear app data.

There is stack trace of simpleprovider-sample (release + proguard).

07-29 12:16:19.070  12680-12720/? E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
    java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask$3.done(AsyncTask.java:299)
            at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
            at java.util.concurrent.FutureTask.run(FutureTask.java:239)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at java.lang.Thread.run(Thread.java:841)
     Caused by: android.database.sqlite.SQLiteException: no such table: posts (code 1): , while compiling: SELECT * FROM posts
            at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
            at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1118)
            at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:691)
            at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
            at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
            at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
            at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
            at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1436)
            at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1283)
            at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1154)
            at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1360)
            at de.triplet.simpleprovider.e.a(Unknown Source)
            at de.triplet.simpleprovider.e.a(Unknown Source)
            at de.triplet.simpleprovider.a.query(Unknown Source)
            at android.content.ContentProvider.query(ContentProvider.java:744)
            at android.content.ContentProvider$Transport.query(ContentProvider.java:199)
            at android.content.ContentResolver.query(ContentResolver.java:417)
            at android.content.CursorLoader.loadInBackground(CursorLoader.java:65)
            at android.content.CursorLoader.loadInBackground(CursorLoader.java:43)
            at android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:303)
            at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:68)
            at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:56)
            at android.os.AsyncTask$2.call(AsyncTask.java:287)
            at java.util.concurrent.FutureTask.run(FutureTask.java:234)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at java.lang.Thread.run(Thread.java:841)

Storing Image

How can we store Image in the ContentProvider. I tried this, but not working

@Column(Column.FieldType.BLOB)
        public static final String IMAGE = "image"; //objectId

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.