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 it in a placeholder class:
@ContentProvider(authority = TestContentProvider.AUTHORITY,
database = TestDatabase::class,
baseContentUri = TestContentProvider.BASE_CONTENT_URI)
object TestContentProvider {
const val AUTHORITY = "com.dbflow5.test.provider"
const val 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. Any database this annotated class references must extend ContentProviderDatabase
@ContentProvider(authority = TestDatabase.AUTHORITY,
database = TestDatabase::class,
baseContentUri = TestDatabase.BASE_CONTENT_URI)
@Database(name = TestDatabase.NAME, version = TestDatabase.VERSION)
abstract class TestDatabase: ContentProviderDatabase() {
companion object {
const val NAME = "TestDatabase"
const val VERSION = 1
const val AUTHORITY = "com.dbflow5.test.provider"
const val BASE_CONTENT_URI = "content://"
}
}
In other applications or your current's AndroidManifest.xml
add the generated $Provider class:
<provider
android:authorities="com.dbflow5.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
const val ENDPOINT = "{tableName}"
field for reusability -
Create
buildUri()
method (see below) to aid in creating other ones.
To define one:
@TableEndpoint(ContentProviderModel.ENDPOINT)
object ContentProviderModel {
const val ENDPOINT = "ContentProviderModel"
fun buildUri(vararg paths: String): Uri {
val builder = Uri.parse(BASE_CONTENT_URI + AUTHORITY).buildUpon()
for (path in paths) {
builder.appendPath(path)
}
return builder.build()
}
@ContentUri(path = ContentProviderModel.ENDPOINT,
type = ContentUri.ContentType.VND_MULTIPLE + ENDPOINT)
val CONTENT_URI = buildUri(ENDPOINT);
}
or via the table it belongs to
@TableEndpoint(name = ContentProviderModel.NAME, contentProvider = ContentDatabase::class)
@Table(database = ContentDatabase::class, name = ContentProviderModel.NAME, generateContentValues = true)
class ContentProviderModel(@PrimaryKey(autoincrement = true)
var id: Long = 0,
var notes: String? = null,
var title: String? = null) : BaseProviderModel() {
override val deleteUri get() = TestContentProvider.ContentProviderModel.CONTENT_URI
override val insertUri get() = TestContentProvider.ContentProviderModel.CONTENT_URI
override val updateUri get() = TestContentProvider.ContentProviderModel.CONTENT_URI
override val queryUri get() = TestContentProvider.ContentProviderModel.CONTENT_URI
companion object {
const val NAME = "ContentProviderModel"
@ContentUri(path = NAME, type = "${ContentType.VND_MULTIPLE}${NAME}")
val CONTENT_URI = ContentUtils.buildUriWithAuthority(ContentDatabase.AUTHORITY)
}
}
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:
val contentProviderModel: ContentProviderModel = ...; // some instance
val count = ContentUtils.update(contentResolver, ContentProviderModel.CONTENT_URI, contentProviderModel)
val uri = ContentUtils.insert(contentResolver, ContentProviderModel.CONTENT_URI, contentProviderModel)
val count = ContentUtils.delete(contentResolver, 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(database<ContentDatabase>()) // queries the content provider
model.someProp = "Hello"
model.update(database<ContentDatabase>()) // runs an update on the CP
model.insert(database<ContentDatabase>()) // 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: 1. Update 2. Insert 3. Delete
@JvmStatic
@Notify(method = NotifyMethod.UPDATE,
paths = {}) // specify paths that will call this method when specified.
fun onUpdate(context: Context, uri: Uri): Array<Uri> {
return arrayOf(...) // 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:
@JvmStatic
@ContentUri(type = ContentType.VND_MULTIPLE,
path = "Friends/#/#",
segments = [@PathSegment(segment = 1, column = "id"),
@PathSegment(segment = 2, column = "name")])
fun withIdAndName(int id, String name): Uri = buildUri(id, name)