Android, content provider in library project
Asked Answered
R

1

10

I have a library project providing the base code for a number of apps that all needs the same database structure and functionality and I'm looking for the best way to implement this. My main concern is really about how to provide a non static authority so I can override it with the package name of the app that uses the library.

So in the library project I was thinking I could change the following constants to static methods that will accept a context that will allow me to get the authority from a resource string or from the context.getPackageName method

library project model

    public static final class Questions implements BaseColumns {
//      public static final Uri CONTENT_URI =
//          Uri.parse("content://" + Config.AUTHORITY + "/questions");
//  use getAuthority instead which in turn will just get the package ae. Will this work?
        public static Uri getContentUri(Context c){
            return Uri.parse("content://" + getAuthority(c) + "/questions");
        }
    ...
    }

public static String getAuthority(Context c){
    return c.getPackageName + ".QuizProvider";
}

library project content provider

public class QuizProvider extends ContentProvider {

//    private SQLiteDatabase mDB;

    private static final String TAG = "MyLog";

    private static final String DATABASE_NAME = "quiz.db";

    private static final int DATABASE_VERSION = 1;

    private static final int QUESTIONS = 1;
    private static final int QUESTION_ID = 2;

    private static final UriMatcher URI_MATCHER = new UriMatcher(
        UriMatcher.NO_MATCH);

    private static Map<String, String> QUESTION_LIST_PROJECTION_MAP = null;

    private DatabaseHelper mOpenHelper;

    /**
     * This class helps open, create, and upgrade the database file.
     */

    private static class DatabaseHelper extends SQLiteOpenHelper {

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        int match = URI_MATCHER.match(uri);
        switch (match) {
        case QUESTIONS:
            return insertQuestion(values);
        ...
        }

...
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

        switch (URI_MATCHER.match(uri)) {
        case QUESTIONS:
            qb.setTables(QuizModel.Questions.TABLE_NAME);
            qb.setProjectionMap(QUESTION_LIST_PROJECTION_MAP);
            break;
...
        }

//How do I change this?    
        static {
            URI_MATCHER.addURI(Config.AUTHORITY, QuizModel.Questions.TABLE_NAME, QUESTIONS);
    ...
            QUESTION_LIST_PROJECTION_MAP = new HashMap<String, String>();
    ...
        }

1) I don't really understand the static { URI_MATCHER.addUR } declaration and am struggling to understand how I can convert this?

2) Is this the best approach to be able to reuse the whole functionality in whatever app? If not what would be better?

Rub answered 25/4, 2012 at 17:25 Comment(1)
For those who're looking for the same question, yes you can as stated in this Stackoverflow comment.Cyder
G
1

I subclassed UriMatcher with something like this :

private static final UriMatcher sUriMatcher
        = new UriMatcher(UriMatcher.NO_MATCH){
    @Override
    public int match(Uri uri) {
        return super.match(uri.buildUpon().authority(AUTHORITY).build());
    }       
};

The app which uses the library should declare the provider in the manifest with it's own authority string.

You can also replace the public static Uri objects in your model classes with a getUri(Context c) function which creates the Uri appropriate for THAT application.

Gospodin answered 4/12, 2013 at 4:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.