bod / android-contentprovider-generator Goto Github PK
View Code? Open in Web Editor NEWA tool to generate Android ContentProviders.
License: GNU General Public License v3.0
A tool to generate Android ContentProviders.
License: GNU General Public License v3.0
The generated SomeModelContentValues.update(Context context, SomeModelSelection where)
method uses uri()
where where.uri()
should be used. And likewise the SomeModelContentValues.update(ContentProvider contentProvider, SomeModelSelection where)
method.
I've issued a pull request to fix this problem and make some other improvements.
Or please edit the contentprovider.ftl file and fix this problem. Thanks.
Because they perform better maybe.
Currently only limit
is supported, I will write up a PR to add offset
as well.
Currently there is a generated default order by which is hardcoded to be _id.
Instead this should be definable in the entities.
Also, if not defined, the default behavior should be to not have an ORDER BY clause at all.
With the 1.8.1 version of the lib, there are two bugs:
getCachedColumnIndexOrThrow
of AbstractCursor
is not qualified and therefor is the first one found that have the colNameXXXProvider.getQueryParams
method, the qualifyAmbiguousColumns
should be called on all joined tablesI don't think it's just me who wants to add some custom logic in onCreate :) What about triggers or some other tweaking like executing some pragma commands?
This requires to add a minSdk attribute in the config!
When using 'on conflict abort' for instance, insert could have no effect, in this case currently a uri ending with -1 is returned. It would be better to return null in that case.
Hi,
Using your tool, automatically would create POJO objects and the possibility of fill up the pojos using the cursor or similar object
PD. Sorry, I don't know how to label the issue as enchantment
I think it isn't very efficient:
public Integer getIntegerOrNull(String colName) {
Integer index = getCachedColumnIndexOrThrow(colName); // int to Integer
if (isNull(index)) return null; // Integer to int
return getInt(index); // Integer to int and int to Integer
}
and
public class GeneratedCursor extends AbstractCursor {
...
public String getTitle() {
Integer index = getCachedColumnIndexOrThrow(GeneratedColumns.TITLE); // int to Integer
return getString(index); // Integer to int
}
...
}
Possible?
Thanks.
I have been playing around with the idea that the _Object_Selection class would have a method to return a CursorLoader.
Something like this:
public CursorLoader cursorLoader(Context context, String[] projection) {
return new CursorLoader(context, *Object*Columns.CONTENT_URI, projection, sel(), args(), order()) {
@Override
public Cursor loadInBackground() {
return new *Object*Cursor(super.loadInBackground());
}
};
}
I am personally stuck on how to get the AbstractSelection to come into effect. Would we need a _Object_CursorLoader that extends a _Object_AbstractCursorLoader?
It seems that adding that Edited code above to the selection class would work well but I am not sure if it is nessessary.
The selection builder does not escape any arguments passed to and and just appends them to the query string when you pass multiple arguments.
To fix use prepared statements instead.
protected void addEquals(String column, Object... value) {
mSelection.append(column);
if (value == null) {
// Single null value
mSelection.append(IS_NULL);
} else if (value.length > 1) {
// Multiple values ('in' clause)
mSelection.append(IN);
for (int i = 0; i < value.length; i++) {
mSelection.append("?");
if (i < value.length - 1) {
mSelection.append(COMMA);
}
mSelectionArgs.add(valueOf(value[i]));
}
mSelection.append(PAREN_CLOSE);
} else {
// Single value
mSelection.append(EQ);
mSelectionArgs.add(valueOf(value[0]));
}
}
hello,
currently, _id can't be setted and used as normal field, and foreign keys always reference the _id column.
In most apps, an idea is sent by a server, and we have to manage two different ids, and put in database is not easy :
insert object
query object to get _ids
insert subObject.
Instead of just use an applyBatch.
I feel that all limitations are added by contentprovidergenerator to preserve misuse, but its use as a normal fields (ObjectContentValues, ObjectSelection...) could be useful in some cases.
did I miss something ?
thanks
Hi, when I run mvn assembly:single I get this error:
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 17.171s
[INFO] Finished at: Thu Nov 21 18:45:59 CET 2013
[INFO] Final Memory: 7M/108M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-assembly-plugin:2.2-beta-5:single (default-cli) on project android_contentprovider_generator: Error reading assemblies: Descriptor with ID 'bundle' not found -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
Can you help me?
Thanks!
I have the following tables:
Person:
{
"fields": [
{
"name": "person_name",
"type": "String",
"nullable": false
}
]
}
Addresses:
{
"fields": [
{
"name": "person_id",
"type": "Long",
"nullable": false,
"foreignKey": {
"table": "Person",
"onDelete": "CASCADE"
}
},
{
"name": "address_name",
"type": "String",
"nullable": false
}
]
}
I use CursorLoaders for the Person and Addresses table. A person can have multiple addresses. The problem is that if I delete a Person, I need the ContentProvider to also notify the CursorLoader for Adresses. Basically for delete notify besides the URI for Person, the URI for Addresses. This can be expanded to all CRUD operations.
Hi, i'm very happy when you created this the tool, but i don't understend input and output when run this tool, can you guide step by tep for me ?
The columns class for a table uses ==
to check string equality in hasColumns
, is this intentional because it would seem risky to do this if the content provider will be used in a cross process environment.
Hello,
I have a code that does something like this
cursor.moveToFirst();
do {
UserCursor userCursor = new UserCursor(cursor);
if (userCursor.getIsRegistered() != null && !userCursor.getIsRegistered()) {
// do Something
}
} while (cursor.moveToNext());
Instead of creating a new UserCursor each time, why don't we add a setCursor method and reuse the object instead of creating new one, I think that would save memory, right ?
The newly added models are awesome but they don't expose any way to get the ID of the model, is there any reason for this?
We have these tables:
// table1.json
{
"fields": [{
"name": "capture_id",
"type": "Long",
"nullable": true,
"index": true,
"foreignKey": {
"table": "table2",
"onDelete": "CASCADE"
}
}]
}
// table2.json
{
"fields": [{
"name": "name",
"type": "String",
"nullable": false
}]
}
So when we do this:
Table1Cursor cursor = new Table1Selection()
.id(1)
.query(context.getContentResolver(), new String[] {Table2.name, ...});
cursor.moveToNext();
cursor.getTable2Name(); // Crash because it throws a NullPointerException
It possible it would be great if we allowed non null columns for tables joined with nullable foreign keys to return null
I added a non-nullable field is_favorite to my db. In order for the content provider to compile, I had to make this change:
-
- public PoemSelection isFavorite(boolean... value) {
- addEquals(PoemColumns.IS_FAVORITE, toObjectArray(value));
- return this;
- }
-
- public PoemSelection isFavoriteNot(boolean... value) {
- addNotEquals(PoemColumns.IS_FAVORITE, toObjectArray(value));
+ public PoemSelection isFavorite(boolean value) {
+ addEquals(PoemColumns.IS_FAVORITE, value ? new Object[] { "1" } : new Object[] { "0" });
return this;
}
To be copy/paste to the manifest.
For some reason when I try to set a non-nullable field to have a default value, it ignores the default value and only applies the NOT NULL on the create table statement.
{
"name": "quantity",
"type": "Integer",
"nullable": false,
"default_value": "1"
},
HI,
Sqlite documentation says:The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and disk I/O overhead and should be avoided if not strictly needed. It is usually not needed.
And sometime I don't need it?
Can you add an extra option in the json template.
Thanks.
Optionally of course (new flag in _config.json).
To be used in Cursors and maybe in Selections.
I want to use groupBy and sum together
It would be stored as a long, but the Wrappers can return a Date.
The Log.d calls may be conditioned by a single Field / Constant to allow the dev to switch it off in one change.
In the SQLiteOpenHelper class, the method onUpgrade usually contains upgrade code, that will be overriden when re-generating the files.
We need a way to not lose this code (maybe put it in another class, that won't be touch if it exists).
I get following errors in Android Studio when using the code generated by android-contentprovider-generator 1.9.3, with "TableName" being the provided name for a database table:
error: method orderById(boolean) is already defined in class TableNameSelection
error: method orderById() is already defined in class TableNameSelection
error: method getId() is already defined in class TableNameCursor
error: TableNameCursor is not abstract and does not override abstract method getId() in TableNameModel
error: getId() in TableNameCursor cannot implement getId() in TableNameModel
return type long is not compatible with Integer
For instance, an attribute "addedInVersion" could be added on tables, and the tool would generate CREATE TABLE statements when upgrading from version n-1 to n.
Another one "deletedInVersion", to delete a no longer used table (a less useful feature, but why not).
I guess it may also be possible to handle table rename cases.
And also columns creation/deletion/renames, maybe.
Due to section of String optimisation, cursor.getString() creates a new String.
So, there is a method copyStringToBuffer that is useful for viewHolder pattern in adapter.
Your adapterWrapper got very useful methods of getting data, would be very cool to add a copyToStringBuffer method!
Thanks!
@Override
public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) throws OperationApplicationException {
Log.v(TAG, "applyBatch: " + operations);
Set<Uri> urisToNotify = new HashSet<Uri>();
for (ContentProviderOperation operation : operations)
urisToNotify.add(operation.getUri());
Log.v(TAG, "applyBatch: will notify these uris after persisting: " + urisToNotify);
SQLiteDatabase db = mNetworkMonitorDatabase.getWritableDatabase();
db.beginTransaction();
try {
ContentProviderResult[] result = super.applyBatch(operations);
db.setTransactionSuccessful();
for (Uri uri : urisToNotify)
getContext().getContentResolver().notifyChange(uri, null);
return result;
} finally {
db.endTransaction();
}
This should probably be an option...
For instance:
{
"comment": "The first name of the person.",
"name": "first_name",
"type": "String",
"nullable": false,
},
Then use it in Javadoc of generated classes.
It would be awesome if the generated code used annotation for things can can and cannot be null.
That way we would get warnings in Android Studio.
It would be nice to add this code to AbstractSelection
private String mOrderBy = null;
public T orderBy(String order, boolean desc) {
mOrderBy = order + (desc ? " DESC" : "");
return (T) this;
}
public CursorLoader cursorLoader(Context context) {
return new CursorLoader(context, uri(), null, sel(), args(), mOrderBy);
}
public int count(ContentResolver resolver) {
final Cursor cursor = resolver.query(uri(), new String[0], sel(), args(), null);
if (cursor == null)
return 0;
try {
return cursor.getCount();
} finally {
cursor.close();
}
}
This simple change greatly simplifies common tasks like these:
@Override public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new EventSelection().number(mEventNumber).orderBy("date", true).cursorLoader(mContext);
}
int count = new EventSelection().number(mEventNumber).count(getContentResolver());
if (count > 0) {
// Do something useful
}
So new versions of the tool can detect that the files must be updated.
This will bring several advantages:
Add a LIMIT support, the same way GROUP BY is implemented.
Hey I like to check if this this project is still maintained and any support for batch inserts of data
I have a configuration file, named entity_name.json
:
{
"fields": [
{
"name": "entity_name_field",
"type": "String"
}
]
}
When the entity_name
classes are generated, their package names lack underscores:
package com.app.provider.entityname;
However, in the generated classes that import the generated entity_name
classes, the import statements include underscores:
import com.app.provider.entity_name.*;
I'm using version 1.8.0.
Hi.
I am currently using the generator and i thought about extending some of the generators functionality without touching the generated classes and the generator itself.
I would like to discuss if it would be a valuable Feature to add Extension classes that the user can use to add custom methods/constants etc.
Actually you generate a class like AbstractSelection. From my personal point of view there is e.g. a count method missing. So i would like to add it to the AbstractSelection functionality. but after regenerating the Code it will be dropped. So it would be nice to have a defined Extension Point at nearly every class as it is done with the OpenHelpherCallbacks.
I'll fid it nice if the hierarchy for this example was:
AbstractSelection <-AbstractSelectionExtension <-MyClassSelection(domain) <-MyClassSelectionExtension
So i would have two Extension points, one per entity and one per generated set of classes. I would do the same with Cursor (here i often add a fromRow method to get a Domain object), Columns, ContentValues (here i add a Constructor with domain object parameter to fill the CV initially). Even the ContentProvider itself needs some Extension Points for adding e.g. custom URIs and so on.
if you like the idea, i would like to discuss it. I could also fork make a code suggestions if it helps.
Regards.And thanks for the work!
Hi again.
Another topic i recently came across is the support for SQL Views. I need to define a View to easily merge/Join some tables for simple usage in Lists with a CursorAdapter. Therefore i had to change the genrated classes and i think it would be possible to support Views out of the box.
What we need to use a View:
-a Type property for each .json file indicating if this is a table or a view
-Selection
-Cursor
-Columns
-SQL_CREATE -> i currently added it in the OpenHelperCallbacks class, but i think it would be nicer to add the views directly in the DatabaseHelper, e.g. with defining a method:
public String getStatementFor in the OpenHelperCallbacks Interface/class
-additional URI for the View and the appropriate Mappings in the Contentprovider itself, alternatively the possibility to define and Extension class to add this kind of URIs
Would be nice to discuss it with you.
Regards.
like idGt and so on.
select.orderByX doesn't seem to work, I was ordering by timeStamp and noticed it only took ORDER BY ._id
Hi,
I have seen this conditional in sqliteopenhelper.ftl:
INTEGER PRIMARY KEY<#if field.isAutoIncrement> AUTOINCREMENT</#if>
It means will you put a neu parameter autoincrement in the jsons to enable or disable autoincrement?
Cheer.s
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.