• Stars
    star
    620
  • Rank 72,387 (Top 2 %)
  • Language
    Java
  • License
    GNU General Publi...
  • Created about 12 years ago
  • Updated about 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A tool to generate Android ContentProviders.

Android ContentProvider Generator (acpg)

Android Arsenal

A tool to generate Android ContentProviders. It takes a set of entity (a.k.a "table") definitions as the input, and generates:

  • a ContentProvider class
  • an SQLiteOpenHelper class
  • one Columns class per entity
  • one Cursor class per entity
  • one ContentValues class per entity
  • one Selection class per entity
  • one Model interface per entity
  • one Bean class per entity (optionally)

Usage

There are two possible ways to generate the code:

  1. as part of the build script (with a Gradle plugin)
  2. as a one-time step (using a command line tool)

The Gradle plugin is perhaps the 'cleaner' way in the sense that the generated code won't be part of the source (not checked into VCS). The configuration is declared inside the Gradle script which allows to update it easily.

Alternatively, a one-time generation can be done (typically at the beginning of the project.) The generated code is part of the source and checked into VCS: this allows you to modify it if you need to.

You can decide which option is the best for your project :)

Option 1: Gradle plugin

Add this to your app's build.gradle:

buildscript {
    dependencies {
        classpath 'org.jraf:acpg-gradle-plugin:1.13.1'
    }
}

apply plugin: 'org.jraf.acpg.gradleplugin'

(...)

// This is where you declare a few parameters used to generate the code
acpg {
    // Where to find the entity files (see 'Entity files' below)
    // Optional - default value: 'etc/acpg' in the root project
    entitiesDir file('etc/acpg-entities')

    // Java package in which all the code will be generated
    providerJavaPackage 'com.example.app.provider'

    // ContentProvider authority
    // "${applicationId}" will be substituted by BuildConfig.APPLICATION_ID in the generated code
    authority '${applicationId}.provider'

    // Name of the provider class
    providerClassName 'ExampleProvider'

    // Name of the db file
    databaseFileName 'example.db'

    // Version of the db
    databaseVersion 1

    // Name of the SQLiteOpenHelper class
    // Optional - default value: providerClassName + "SQLiteOpenHelper"
    sqliteOpenHelperClassName 'ExampleSQLiteOpenHelper'

    // Name of a subclass of BaseSQLiteOpenHelperCallbacks
    // Optional - this allows you to get called when the db is opened/created/upgraded
    sqliteOpenHelperCallbacksClassName 'ExampleSQLiteOpenHelperCallbacks'

    // Whether to enable foreign keys support (see 'Advanced usage' below)
    // Optional - default value: false
    enableForeignKeys true

    // Whether @Nullable/@NonNull annotations will be used in the generated code
    // Optional - default value: false
    useAnnotations true

    // Whether support library classes are used or the Android SDK ones (e.g. CursorLoader)
    // Optional - default value: false
    useSupportLibrary true

    // Whether to generate a 'Beans' class for each entity
    // Optional - default value: true
    generateBeans true

    // Name of a boolean field in BuildConfig to enable/disable debug logging in the generated code
    // Optional - default value: "DEBUG"
    debugLogsFieldName 'LOG_DEBUG_PROVIDER'

    // Version of the tool syntax (must be 4)
    // The allows to break the build immediately if an incompatible version of the tool is used. Safety first!
    // Optional - default value: 4
    syntaxVersion 4
}

Option 2: Command line tool

The configuration is the same, except you declare it in a file named _config.json in the same folder as the entity files.

Here is an example:

{
	"syntaxVersion": 4,
	"packageName": "com.example.app",
	"providerJavaPackage": "com.example.app.provider",
	"authority": "${applicationId}.provider",
	"providerClassName": "ExampleProvider",
	"databaseFileName": "example.db",
	"databaseVersion": 1,
	"sqliteOpenHelperClassName": "ExampleSQLiteOpenHelper",
	"sqliteOpenHelperCallbacksClassName": "ExampleSQLiteOpenHelperCallbacks",
	"enableForeignKeys": true,
	"useAnnotations": true,
	"useSupportLibrary": true,
	"generateBeans": true,
	"debugLogsFieldName": "LOG_DEBUG_PROVIDER"
}

About packageName: this must be the same as the value of the package attribute in your manifest. Not to be confused with the applicationId (see https://developer.android.com/studio/build/application-id.html)

Get and run the tool

Download the acpg-cli-1.13.1.jar file here: https://github.com/BoD/android-contentprovider-generator/releases/latest

java -jar acpg-cli-1.13.1.jar -i <input folder> -o <output folder>

  • Input folder: where to find _config.json and your entity json files
  • Output folder: where the resulting files will be generated

Entity files

Create one file per entity, naming it <entity_name>.json. Inside each file, declare your fields (a.k.a "columns") with a name and a type. You can also optionally declare a default value, an index flag, a documentation and a nullable flag.

Currently the type can be:

  • String (SQLite type: TEXT)
  • Integer (INTEGER)
  • Long (INTEGER)
  • Float (REAL)
  • Double (REAL)
  • Boolean (INTEGER)
  • Date (INTEGER)
  • byte[] (BLOB)
  • enum (INTEGER).

You can also optionally declare table constraints.

Here is a person.json file as an example:

{
	"documentation": "A human being which is part of a team.",
	"fields": [
		{
			"documentation": "First name of this person. For instance, John.",
			"name": "first_name",
			"type": "String",
			"defaultValue": "John"
		},
		{
			"documentation": "Last name (a.k.a. Given name) of this person. For instance, Smith.",
			"name": "last_name",
			"type": "String",
			"nullable": true,
			"defaultValue": "Doe"
		},
		{
			"name": "age",
			"type": "Integer",
			"index": true
		},
		{
			"name": "gender",
			"type": "enum",
			"enumName": "Gender",
			"enumValues": [
				"MALE",
				"FEMALE",
				{"OTHER": "Value to use when neither male nor female"}
			],
			"nullable": false
		}
	],

	"constraints": [
		{
			"name": "unique_name",
			"definition": "UNIQUE (first_name, last_name) ON CONFLICT REPLACE"
		}
	],
	
	"defaultOrder": "first_name, last_name, age DESC"
}

Notes:

  • An _id primary key field is automatically (implicitly) declared for all entities. It must not be declared in the json file.
  • nullable is optional (true by default).
  • if documentation is present the value will be copied in Javadoc blocks in the generated code.
  • the constraints and defaultOrder sections are optional

A more comprehensive sample is available in the sample-app/etc/acpg folder.

You can have a look at the corresponding generated code in the etc/sample-generated-code folder.

By convention, you should name your entities and fields in lower case with words separated by '_', like in the example above.

The header.txt file (optional)

If a header.txt file is present, its contents will be inserted at the top of every generated file.

Use the generated files

  • When querying a table, use the corresponding Selection class as shown in this example:
PersonSelection where = new PersonSelection();
where.firstName("John").or().age(42);
Cursor c = context.getContentResolver().query(where.uri(), projection,
        where.sel(), where.args(), null);
  • When using the results of a query, wrap the resulting Cursor in the corresponding wrapper class. You can then use the generated getters directly as shown in this example:
PersonCursor person = new PersonCursor(c);
String lastName = person.getLastName();
Long age = person.getAge();
  • You can also conveniently combine these two facilities by using the query (or delete) method:
PersonSelection where = new PersonSelection();
where.firstName("John").or().age(42).orderByFirstName();
PersonCursor person = where.query(context);
person.moveToNext();
String lastName = person.getLastName();
Long age = person.getAge();

or, use a CursorLoader:

where.getCursorLoader(context);
  • When updating or inserting into a table, use the corresponding ContentValues class as shown in this example:
PersonContentValues values = new PersonContentValues();
values.putFirstName("John").putAge(42);
context.getContentResolver().update(values.uri(), values.values(), null, null);

or

values.insert(context);

Advanced usage

Foreign key / joins

There is limited support for foreign keys and joins. Here is an example of the syntax:

{
	"fields": [
		{
			"name": "main_team_id",
			"type": "Long",
			"nullable": false,
			"foreignKey": {
				"table": "team",
				"onDelete": "CASCADE"
			}
		},
		{
			"name": "first_name",
			"type": "String",
			"nullable": false
		},

		(...)
}

In this example, the field main_team_id is a foreign key referencing the primary key of the team table.

  • The appropriate FOREIGN KEY SQL constraint is generated (if enableForeignKeys is set to true in _config.json).
  • The team table will be automatically joined when querying the person table [1].
  • Getters for team columns are generated in the PersonCursor wrapper.
  • Of course if team has foreign keys they will also be handled (and recursively).

[1] A table is automatically joined if at least one of its columns is included in the projection. If the projection is null (i.e. all columns), all the tables are joined. Caution: you should be extra careful when using a null projection with joins because you will get several columns named _id in the results!

Limitations

  • Foreign keys always reference the _id column (the implicit primary key of all tables) and thus must always be of type Long - by design.
  • Only one foreign key to a particular table is allowed per table. In the example above only one column in person can point to team.
  • Loops (i.e. A has a foreign key to B and B has a foreign key to A) aren't detected. The generator will infinitely loop if they exist.
  • Cases such as "A has a FK to B, B has a FK to C, A has a FK to C" generate ambiguities in the queries, because C columns appear twice. In the sample app you can see an example of how to deal with this case, using prefixes and aliases (SQL's AS keyword).

Sample

A sample is available in the sample-app folder, with the entities in sample-app/etc/acpg.

You can have a look at the corresponding generated code in the etc/sample-generated-code folder.

Here is the table shema of the sample: Table shema of the sample

Building

This is a Gradle project.

./gradlew install to 'install' the Gradle plugin to your local maven repo

./gradlew shadowJar to build the cli tool

Similar tools

Here is a list of other tools that try to tackle the same problem.

I did not have the chance to try them out.

Licence

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Just to be absolutely clear, this license applies to this program itself, not to the source it will generate!

More Repositories

1

android-switch-backport

A backport of the SwitchPreference component that was introduced on Android 4 (ICS / level 14). This port works on Android 2.1+ (Eclair MR1 / level 7).
Java
498
star
2

android-dip-ruler

Print it, cut it, give it to your designer!
235
star
3

android-prefs

Android preferences for WINNERS!
Java
182
star
4

android-activitylifecyclecallbacks-compat

Android ActivityLifecycleCallbacks Compatibility Library
Java
79
star
5

android-wear-color-picker

A color picker activity optimized for Wear OS (aka Android Wear). Handy for watch face settings.
Kotlin
56
star
6

aLibGlitch

A "glitch effect" library for Android.
Java
52
star
7

klibnotion

A Notion API client library for Kotlin, Java and more.
Kotlin
52
star
8

bikey

A bike computer for Android.
Java
35
star
9

jraf-android-util

A collection of general purpose utilities for Android.
Java
33
star
10

OpenCurrentActivityIntelliJPlugin

A little plugin for Android development (Android Studio or IntelliJ).
Kotlin
33
star
11

NyanTrayIntelliJPlugin

A little plugin for IntelliJ (and Android Studio, and other IntelliJ based IDEs) to let you know when work is ongoing.
Kotlin
27
star
12

android-graphql-sample

Apollo GraphQL Android Sample
Kotlin
16
star
13

apollo-kotlin-template-mpp

Kotlin
8
star
14

android-kprefs

Android preferences for WINNERS! Now optimized for Kotlinâ„¢
Kotlin
6
star
15

irondad

A very simple IRC client library written in Java.
Java
6
star
16

colorsecret

colorsecret, a game for Android similar to the 'Mastermind' board game.
Java
4
star
17

piclabel

An Android app to add labels to pictures.
Java
4
star
18

DoorCodeNotifier

An Android app that notifies you when you're near a friend's place and shows you their door code.
Java
4
star
19

CineToday

An Android Wear app that lists movies showing at your favorite theaters, on your smartwatch.
Kotlin
4
star
20

SimpleWatchface

A very simple Watchface for Android Wear
Java
4
star
21

fbshare

Facebook 'share' action that doesn't suck! (For Android)
Java
4
star
22

CineToday3

WIP
Kotlin
4
star
23

Ticker

An Android app that displays various information as a big full screen text that scrolls.
Kotlin
3
star
24

klibqonto

A Qonto API client library for Kotlin, Java and more.
Kotlin
3
star
25

SimpleWatchFace2

A simple round watchface for Android Wear 2
Kotlin
3
star
26

klibreddit

A reddit client library for Kotlin
Kotlin
3
star
27

kotlinx-io-explorations

Kotlinx-io explorations
Kotlin
3
star
28

android-dockerfile

A very simple Dockerfile with the Android tools
Dockerfile
3
star
29

qonto-api-graphql-bridge

Qonto API GraphQL Bridge
Kotlin
3
star
30

bbt

BoD's Bookmark Tool, a browser extension
Kotlin
3
star
31

winautohide

Automatically exported from code.google.com/p/winautohide
AutoHotkey
3
star
32

notion-to-bookmarks

Webapp to generate a JSON bookmarks from a Notion page
Kotlin
2
star
33

apollo-kotlin-template-mpp-library

Swift
2
star
34

github-to-bookmarks

Generate a JSON bookmarks document from a GitHub user
Kotlin
2
star
35

DeferDemo

Kotlin
2
star
36

klibminitel

A Kotlin (JVM) library to interact with the Minitel
Kotlin
2
star
37

JRAForg

Companion app for Benoit `BoD' Lubek's personal website.
Kotlin
2
star
38

CountdownWidget

A very simple Android widget that shows the number of days until the release of Star Wars Episode VII (December 18, 2015).
Kotlin
2
star
39

get_android_sources

A script to help downloading the Android sources and copy them to your sdk directory, so you can see them in Eclipse.
Shell
2
star
40

apollo-kotlin-template-multi-modules-and-services

Sample: Apollo Kotlin 3 with multiple modules and services
Kotlin
2
star
41

DownloadAndShareImage

A very simple Android app to download an image given a URL, and share it to other apps.
Java
2
star
42

r2k

r2k = RSS to Kindle
Kotlin
2
star
43

app-store-rating-rss

An RSS feed that returns the current App Store (Apple App Store or Google Play Store) rating of an app.
Kotlin
2
star
44

frc-webapp

A very simple webapp that returns the name and object of the day in the French Revolutionary Calendar.
Shell
1
star
45

libticker

A ticker library
Kotlin
1
star
46

GraphQL-Resume

My resume, as a GraphQL API. Because why not?
Kotlin
1
star
47

dbpedia2sqlite

Java
1
star
48

asopposedto

As opposed to?
Kotlin
1
star
49

mastodon-to-rss

A bridge to transform a Mastodon list into an RSS feed.
Kotlin
1
star
50

apollo-kotlin-template-java

apollo-kotlin-template-java
Java
1
star
51

workinghour

How many hours do you work per day, and per week?
Kotlin
1
star
52

vtail

A graphical 'tail -f' like utility, with highlighting capabilities
Java
1
star
53

issue-ktor-js-socket-timeout

Kotlin
1
star
54

winsupermaximize

Automatically exported from code.google.com/p/winsupermaximize
AutoHotkey
1
star
55

ktor-client-native-memory-leak

ktor-client-native-memory-leak
Kotlin
1
star
56

aclock

A very simple clock for Android.
Java
1
star
57

slack-chatgpt-bot

slack-chatgpt-bot
Kotlin
1
star
58

DataBindingPres

Companion example code for a talk about Android DataBinding I gave at the PAUG
Java
1
star
59

klibappstorerating

A tiny Kotlin library to retrieve app store rating of apps on Google Play Store and Apple App Store
Kotlin
1
star
60

routetools

Some tools about routes, gpx, polylines, etc.
Kotlin
1
star
61

Issue36708811

Repro project for https://issuetracker.google.com/issues/36708811
Java
1
star
62

minitel

A "ticker" for the minitel.
Kotlin
1
star
63

apollo-kotlin-tutorial-compose

apollo-kotlin-tutorial-compose
Kotlin
1
star
64

wifiaction

A very simple little 'script' that uses tshark to monitor a wifi mac address on the network and trigger an action when it is detected.
Kotlin
1
star
65

Fire

An Android app that shows a fire.
Kotlin
1
star
66

HelloMundo

An application for Android that updates the wallpaper with beautiful live pictures of places from all around the world!
Java
1
star
67

apollo-kotlin-template-java-runtime

apollo-kotlin-template-java-runtime
Java
1
star
68

apollo-kotlin-template

Kotlin
1
star
69

a

A minimalist launcher (home application) for Android
Kotlin
1
star
70

BoD-IntelliJ-Theme

A Darcula (IntelliJ Theme) customization that makes the selected tree item background inactive color more visible.
1
star
71

apollo-kotlin-template-android-variants

Kotlin
1
star
72

ApolloKotlinPaginationSample

Apollo Kotlin pagination sample
Kotlin
1
star