{"id":15040892,"url":"https://github.com/bod/android-contentprovider-generator","last_synced_at":"2025-04-04T19:11:40.914Z","repository":{"id":5430141,"uuid":"6622342","full_name":"BoD/android-contentprovider-generator","owner":"BoD","description":"A tool to generate Android ContentProviders.","archived":false,"fork":false,"pushed_at":"2017-10-04T07:38:41.000Z","size":961,"stargazers_count":620,"open_issues_count":15,"forks_count":148,"subscribers_count":53,"default_branch":"master","last_synced_at":"2025-04-04T19:11:33.916Z","etag":null,"topics":["android","android-contentprovider","android-development"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"andreasBihlmaier/ahbstring","license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BoD.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-11-09T23:50:06.000Z","updated_at":"2024-12-30T02:40:59.000Z","dependencies_parsed_at":"2022-08-25T11:40:43.728Z","dependency_job_id":null,"html_url":"https://github.com/BoD/android-contentprovider-generator","commit_stats":null,"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BoD%2Fandroid-contentprovider-generator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BoD%2Fandroid-contentprovider-generator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BoD%2Fandroid-contentprovider-generator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BoD%2Fandroid-contentprovider-generator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BoD","download_url":"https://codeload.github.com/BoD/android-contentprovider-generator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247234922,"owners_count":20905854,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-contentprovider","android-development"],"created_at":"2024-09-24T20:45:14.718Z","updated_at":"2025-04-04T19:11:40.885Z","avatar_url":"https://github.com/BoD.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"Android ContentProvider Generator (acpg)\n========================================\n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Android%20ContentProvider%20Generator-brightgreen.svg?style=plastic)](https://android-arsenal.com/details/1/111)\n\nA tool to generate Android ContentProviders.\nIt takes a set of entity (a.k.a \"table\") definitions as the input, and generates:\n- a `ContentProvider` class\n- an `SQLiteOpenHelper` class\n- one `Columns` class per entity\n- one `Cursor` class per entity\n- one `ContentValues` class per entity\n- one `Selection` class per entity\n- one `Model` interface per entity\n- one `Bean` class per entity (optionally)\n\n\nUsage\n-----\n\nThere are two possible ways to generate the code:\n\n1. as part of the build script (with a Gradle plugin)\n2. as a one-time step (using a command line tool)\n\nThe Gradle plugin is perhaps the 'cleaner' way in the sense that the generated\ncode won't be part of the source (not checked into VCS). The configuration is declared inside\nthe Gradle script which allows to update it easily.\n\nAlternatively, a one-time generation can be done (typically at the beginning of the project.)\nThe generated code is part of the source and checked into VCS: this allows you\nto modify it if you need to.\n\nYou can decide which option is the best for your project :)\n\n\n### Option 1: Gradle plugin\n\nAdd this to your app's `build.gradle`:\n```groovy\nbuildscript {\n    dependencies {\n        classpath 'org.jraf:acpg-gradle-plugin:1.13.1'\n    }\n}\n\napply plugin: 'org.jraf.acpg.gradleplugin'\n\n(...)\n\n// This is where you declare a few parameters used to generate the code\nacpg {\n    // Where to find the entity files (see 'Entity files' below)\n    // Optional - default value: 'etc/acpg' in the root project\n    entitiesDir file('etc/acpg-entities')\n\n    // Java package in which all the code will be generated\n    providerJavaPackage 'com.example.app.provider'\n\n    // ContentProvider authority\n    // \"${applicationId}\" will be substituted by BuildConfig.APPLICATION_ID in the generated code\n    authority '${applicationId}.provider'\n\n    // Name of the provider class\n    providerClassName 'ExampleProvider'\n\n    // Name of the db file\n    databaseFileName 'example.db'\n\n    // Version of the db\n    databaseVersion 1\n\n    // Name of the SQLiteOpenHelper class\n    // Optional - default value: providerClassName + \"SQLiteOpenHelper\"\n    sqliteOpenHelperClassName 'ExampleSQLiteOpenHelper'\n\n    // Name of a subclass of BaseSQLiteOpenHelperCallbacks\n    // Optional - this allows you to get called when the db is opened/created/upgraded\n    sqliteOpenHelperCallbacksClassName 'ExampleSQLiteOpenHelperCallbacks'\n\n    // Whether to enable foreign keys support (see 'Advanced usage' below)\n    // Optional - default value: false\n    enableForeignKeys true\n\n    // Whether @Nullable/@NonNull annotations will be used in the generated code\n    // Optional - default value: false\n    useAnnotations true\n\n    // Whether support library classes are used or the Android SDK ones (e.g. CursorLoader)\n    // Optional - default value: false\n    useSupportLibrary true\n\n    // Whether to generate a 'Beans' class for each entity\n    // Optional - default value: true\n    generateBeans true\n\n    // Name of a boolean field in BuildConfig to enable/disable debug logging in the generated code\n    // Optional - default value: \"DEBUG\"\n    debugLogsFieldName 'LOG_DEBUG_PROVIDER'\n\n    // Version of the tool syntax (must be 4)\n    // The allows to break the build immediately if an incompatible version of the tool is used. Safety first!\n    // Optional - default value: 4\n    syntaxVersion 4\n}\n```\n\n\n### Option 2: Command line tool\n\nThe configuration is the same, except you declare it in a file named `_config.json`\nin the same folder as the entity files.\n\nHere is an example:\n```json\n{\n\t\"syntaxVersion\": 4,\n\t\"packageName\": \"com.example.app\",\n\t\"providerJavaPackage\": \"com.example.app.provider\",\n\t\"authority\": \"${applicationId}.provider\",\n\t\"providerClassName\": \"ExampleProvider\",\n\t\"databaseFileName\": \"example.db\",\n\t\"databaseVersion\": 1,\n\t\"sqliteOpenHelperClassName\": \"ExampleSQLiteOpenHelper\",\n\t\"sqliteOpenHelperCallbacksClassName\": \"ExampleSQLiteOpenHelperCallbacks\",\n\t\"enableForeignKeys\": true,\n\t\"useAnnotations\": true,\n\t\"useSupportLibrary\": true,\n\t\"generateBeans\": true,\n\t\"debugLogsFieldName\": \"LOG_DEBUG_PROVIDER\"\n}\n```\n\nAbout `packageName`: this must be the same as the value of the `package` attribute in your manifest.\nNot to be confused with the `applicationId` (see https://developer.android.com/studio/build/application-id.html)\n\n#### Get and run the tool\n\nDownload the `acpg-cli-1.13.1.jar` file here:\nhttps://github.com/BoD/android-contentprovider-generator/releases/latest\n\n`java -jar acpg-cli-1.13.1.jar -i \u003cinput folder\u003e -o \u003coutput folder\u003e`\n- Input folder: where to find `_config.json` and your entity json files\n- Output folder: where the resulting files will be generated\n\n\n### Entity files\n\nCreate one file per entity, naming it `\u003centity_name\u003e.json`.\nInside each file, declare your fields (a.k.a \"columns\") with a name and a type.\nYou can also optionally declare a default value, an index flag, a documentation and a nullable flag.\n\nCurrently the type can be:\n- `String` (SQLite type: `TEXT`)\n- `Integer` (`INTEGER`)\n- `Long` (`INTEGER`)\n- `Float` (`REAL`)\n- `Double` (`REAL`)\n- `Boolean` (`INTEGER`)\n- `Date` (`INTEGER`)\n- `byte[]` (`BLOB`)\n- `enum` (`INTEGER`).\n\nYou can also optionally declare table constraints.\n\nHere is a `person.json` file as an example:\n\n```json\n{\n\t\"documentation\": \"A human being which is part of a team.\",\n\t\"fields\": [\n\t\t{\n\t\t\t\"documentation\": \"First name of this person. For instance, John.\",\n\t\t\t\"name\": \"first_name\",\n\t\t\t\"type\": \"String\",\n\t\t\t\"defaultValue\": \"John\"\n\t\t},\n\t\t{\n\t\t\t\"documentation\": \"Last name (a.k.a. Given name) of this person. For instance, Smith.\",\n\t\t\t\"name\": \"last_name\",\n\t\t\t\"type\": \"String\",\n\t\t\t\"nullable\": true,\n\t\t\t\"defaultValue\": \"Doe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"age\",\n\t\t\t\"type\": \"Integer\",\n\t\t\t\"index\": true\n\t\t},\n\t\t{\n\t\t\t\"name\": \"gender\",\n\t\t\t\"type\": \"enum\",\n\t\t\t\"enumName\": \"Gender\",\n\t\t\t\"enumValues\": [\n\t\t\t\t\"MALE\",\n\t\t\t\t\"FEMALE\",\n\t\t\t\t{\"OTHER\": \"Value to use when neither male nor female\"}\n\t\t\t],\n\t\t\t\"nullable\": false\n\t\t}\n\t],\n\n\t\"constraints\": [\n\t\t{\n\t\t\t\"name\": \"unique_name\",\n\t\t\t\"definition\": \"UNIQUE (first_name, last_name) ON CONFLICT REPLACE\"\n\t\t}\n\t],\n\t\n\t\"defaultOrder\": \"first_name, last_name, age DESC\"\n}\n```\n\nNotes:\n- An `_id` primary key field is automatically (implicitly) declared for all entities. It must not be declared in the json file.\n- `nullable` is optional (true by default).\n- if `documentation` is present the value will be copied in Javadoc blocks in the generated code.\n- the `constraints` and `defaultOrder` sections are optional\n\nA more comprehensive sample is available in the [sample-app/etc/acpg](sample-app/etc/acpg) folder.\n\nYou can have a look at the corresponding generated code in the [etc/sample-generated-code](etc/sample-generated-code) folder.\n\nBy convention, you should name your entities and fields in lower case with words separated by '_', like in the example above.\n\n### The `header.txt` file (optional)\n\nIf a `header.txt` file is present, its contents will be inserted at the top of every generated file.\n\n\n### Use the generated files\n\n- When querying a table, use the corresponding `Selection` class as shown in this example:\n\n```java\nPersonSelection where = new PersonSelection();\nwhere.firstName(\"John\").or().age(42);\nCursor c = context.getContentResolver().query(where.uri(), projection,\n        where.sel(), where.args(), null);\n```\n\n- When using the results of a query, wrap the resulting `Cursor` in the corresponding wrapper class.  You can then use\nthe generated getters directly as shown in this example:\n\n```java\nPersonCursor person = new PersonCursor(c);\nString lastName = person.getLastName();\nLong age = person.getAge();\n```\n\n- You can also conveniently combine these two facilities by using the `query` (or `delete`) method:\n\n```java\nPersonSelection where = new PersonSelection();\nwhere.firstName(\"John\").or().age(42).orderByFirstName();\nPersonCursor person = where.query(context);\nperson.moveToNext();\nString lastName = person.getLastName();\nLong age = person.getAge();\n```\nor, use a `CursorLoader`:\n```java\nwhere.getCursorLoader(context);\n```\n\n- When updating or inserting into a table, use the corresponding `ContentValues` class as shown in this example:\n\n```java\nPersonContentValues values = new PersonContentValues();\nvalues.putFirstName(\"John\").putAge(42);\ncontext.getContentResolver().update(values.uri(), values.values(), null, null);\n```\nor\n```java\nvalues.insert(context);\n```\n\n\nAdvanced usage\n--------------\n\n### Foreign key / joins\n\nThere is limited support for foreign keys and joins.\nHere is an example of the syntax:\n```json\n{\n\t\"fields\": [\n\t\t{\n\t\t\t\"name\": \"main_team_id\",\n\t\t\t\"type\": \"Long\",\n\t\t\t\"nullable\": false,\n\t\t\t\"foreignKey\": {\n\t\t\t\t\"table\": \"team\",\n\t\t\t\t\"onDelete\": \"CASCADE\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"name\": \"first_name\",\n\t\t\t\"type\": \"String\",\n\t\t\t\"nullable\": false\n\t\t},\n\n\t\t(...)\n}\n```\nIn this example, the field `main_team_id` is a foreign key referencing the primary key of the `team` table.\n- The appropriate `FOREIGN KEY` SQL constraint is generated (if `enableForeignKeys` is set to `true` in `_config.json`).\n- The `team` table will be automatically joined when querying the `person` table `[1]`.\n- Getters for `team` columns are generated in the `PersonCursor` wrapper.\n- Of course if `team` has foreign keys they will also be handled (and recursively).\n\n`[1]` A table is automatically joined if at least one of its columns is included in the projection.\nIf the projection is `null` (i.e. all columns), all the tables are joined. Caution: you should be extra careful when using a `null` projection\nwith joins because you will get several columns named `_id` in the results!\n\n#### Limitations\n- Foreign keys always reference the `_id` column (the implicit primary key of all tables) and thus must always be of type `Long`  - by design.\n- **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`.\n- **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.\n- 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](etc/sample/app/src/org/jraf/androidcontentprovidergenerator/sample/app/SampleActivity.java) you can see an example of how to deal with this case, using prefixes and aliases (SQL's `AS` keyword).\n\n\nSample\n------\n\nA sample is available in the [sample-app](sample-app) folder, with the entities in [sample-app/etc/acpg](sample-app/etc/acpg).\n\nYou can have a look at the corresponding generated code in the [etc/sample-generated-code](etc/sample-generated-code) folder.\n\nHere is the table shema of the sample:\n![Table shema of the sample](etc/sample-schema.png?raw=true \"The sample\")\n\n\nBuilding\n--------\n\nThis is a Gradle project.\n\n`./gradlew install` to 'install' the Gradle plugin to your local maven repo\n\n`./gradlew shadowJar` to build the cli tool\n\n\nSimilar tools\n-------------\nHere is a list of other tools that try to tackle the same problem.\n\nI did not have the chance to try them out.\n\n- https://github.com/SimonVT/schematic\n- https://github.com/TimotheeJeannin/ProviGen\n- http://triple-t.github.io/simpleprovider/\n- https://github.com/foxykeep/ContentProviderCodeGenerator\n- https://code.google.com/p/mdsd-android-content-provider/\n- https://github.com/hamsterksu/Android-AnnotatedSQL\n- http://robotoworks.com/mechanoid/doc/db/api.html\n- https://github.com/robUx4/android-contentprovider-generator (a fork of this project that generates more code)\n- https://github.com/novoda/sqlite-analyzer (based on sql statements, not json)\n- https://github.com/ckurtm/simple-sql-provider\n\n\nLicence\n-------\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not, see \u003chttp://www.gnu.org/licenses/\u003e.\n\n__*Just to be absolutely clear, this license applies to this program itself,\nnot to the source it will generate!*__\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbod%2Fandroid-contentprovider-generator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbod%2Fandroid-contentprovider-generator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbod%2Fandroid-contentprovider-generator/lists"}