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://"
}
}
Adding To Manifest
In other applications or your current's AndroidManifest.xml add the generated $Provider class:
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@TableEndpointfor it to compile/pass error checking
Adding endpoints into the data
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.
Connect Model operations to the newly created ContentProvider
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!
Interacting with the Content Provider
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
Advanced Usage
Notify Methods
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.