This library includes a very fast, easy way to use ContentProvider
! Using annotations, you can generate ContentProvider
with ease.
This feature is largely based off of schematic, while leveraging DBFlow's power.
In order to define a ContentProvider
, you must define a placeholder class:
@ContentProvider(authority = TestContentProvider.AUTHORITY,
database = TestDatabase.class,
baseContentUri = TestContentProvider.BASE_CONTENT_URI)
public class TestContentProvider {
public static final String AUTHORITY = "com.raizlabs.android.dbflow.test.provider";
public static final String BASE_CONTENT_URI = "content://";
}
or you can use the annotation in any class you wish. The recommended place would be in a @Database
placeholder class. This is to simplify some of the declarations and keep it all in one place.
@ContentProvider(authority = TestDatabase.AUTHORITY,
database = TestDatabase.class,
baseContentUri = TestDatabase.BASE_CONTENT_URI)
@Database(name = TestDatabase.NAME, version = TestDatabase.VERSION)
public class TestDatabase {
public static final String NAME = "TestDatabase";
public static final int VERSION = "1";
public static final String AUTHORITY = "com.raizlabs.android.dbflow.test.provider";
public static final String BASE_CONTENT_URI = "content://";
}
In other applications or your current's AndroidManifest.xml
add the generated $Provider class:
<provider
android:authorities="com.raizlabs.android.dbflow.test.provider"
android:exported="true|false"
android:name=".provider.TestContentProvider$Provider"/>
android:exported
: setting this to true, enables other applications to make use of it.
True is recommended for outside application access.
Note you must have at least one @TableEndpoint
for it to compile/pass error checking
There are two ways of defining @TableEndpoint
:
- Create an inner class within the
@ContentProvider
annotation. - Or Add the annotation to a
@Table
and specify the content provider class name (ex. TestContentProvider)
@TableEndpoint
: links up a query, insert, delete, and update to a specific table in the ContentProvider
local database.
Some recommendations:
- (if inside a
@ContentProvider
class) Name the inner class same as the table it's referencing - Create a
public static final String ENDPOINT = "{tableName}"
field for reusability - Create
buildUri()
method (see below) to aid in creating other ones.
To define one:
@TableEndpoint(ContentProviderModel.ENDPOINT)
public static class ContentProviderModel {
public static final String ENDPOINT = "ContentProviderModel";
private static Uri buildUri(String... paths) {
Uri.Builder builder = Uri.parse(BASE_CONTENT_URI + AUTHORITY).buildUpon();
for (String path : paths) {
builder.appendPath(path);
}
return builder.build();
}
@ContentUri(path = ContentProviderModel.ENDPOINT,
type = ContentUri.ContentType.VND_MULTIPLE + ENDPOINT)
public static Uri CONTENT_URI = buildUri(ENDPOINT);
}
or via the table it belongs to
@TableEndpoint(name = ContentProviderModel.NAME, contentProviderName = "ContentDatabase")
@Table(database = ContentDatabase.class, tableName = ContentProviderModel.NAME)
public class ContentProviderModel extends BaseProviderModel<ContentProviderModel> {
public static final String NAME = "ContentProviderModel";
@ContentUri(path = NAME, type = ContentUri.ContentType.VND_MULTIPLE + NAME)
public static final Uri CONTENT_URI = ContentUtils.buildUri(ContentDatabase.AUTHORITY);
@Column
@PrimaryKey(autoincrement = true)
long id;
@Column
String notes;
@Column
String title;
@Override
public Uri getDeleteUri() {
return TestContentProvider.ContentProviderModel.CONTENT_URI;
}
@Override
public Uri getInsertUri() {
return TestContentProvider.ContentProviderModel.CONTENT_URI;
}
@Override
public Uri getUpdateUri() {
return TestContentProvider.ContentProviderModel.CONTENT_URI;
}
@Override
public Uri getQueryUri() {
return TestContentProvider.ContentProviderModel.CONTENT_URI;
}
}
There are much more detailed usages of the @ContentUri
annotation. Those will be in a later section.
There are two kinds of Model
that connect your application to a ContentProvider that was defined in your app, or another app. Extend these for convenience, however they are not required.
BaseProviderModel
: Overrides all Model
methods and performs them on the ContentProvider
BaseSyncableProviderModel
: same as above, except it will synchronize the data changes with the local app database as well!
You can use the ContentUtils
methods:
ContentProviderModel contentProviderModel = ...; // some instance
int count = ContentUtils.update(getContentResolver(), ContentProviderModel.CONTENT_URI, contentProviderModel);
Uri uri = ContentUtils.insert(getContentResolver(), ContentProviderModel.CONTENT_URI, contentProviderModel);
int count = ContentUtils.delete(getContentResolver(), someContentUri, contentProviderModel);
Recommended usage is extending BaseSyncableProviderModel
(for inter-app usage) so the local database contains the same data. Otherwise BaseProviderModel
works just as well.
MyModel model = new MyModel();
model.id = 5;
model.load(); // queries the content provider
model.someProp = "Hello"
model.update(false); // runs an update on the CP
model.insert(false); // inserts the data into the CP
You can define @Notify
method to specify a custom interaction with the ContentProvider
and return a custom Uri[]
that notifies the contained ContentResolver
. These methods can have any valid parameter from the ContentProvider
methods.
Supported kinds include:
- Update
- Insert
- Delete
@Notify(method = Notify.Method.UPDATE,
paths = {}) // specify paths that will call this method when specified.
public static Uri[] onUpdate(Context context, Uri uri) {
return new Uri[] {
// return custom uris here
};
}
Path segments enable you to "filter" the uri query, update, insert, and deletion by a specific column and a value define by '#'.
To specify one, this is an example path
path = "Friends/#/#"
then match up the segments as:
segments = {@PathSegment(segment = 1, column = "id"),
@PathSegment(segment = 2, column = "name")}
And to put it all together:
@ContentUri(type = ContentType.VND_MULTIPLE,
path = "Friends/#/#",
segments = {@PathSegment(segment = 1, column = "id"),
@PathSegment(segment = 2, column = "name")})
public static Uri withIdAndName(int id, String name) {
return buildUri(id, name);
}