android in practice_Working with a custom ContentProvider(MyMoviesContentProvider)

android in practice_Working with a custom ContentProvider(MyMoviesContentProvider)_第1张图片

The ContentProvider API is a thin layer on top of a SQLite database.

This example showcased using the ContactsContract provider. The android.provider package also contains providers for the calendar and for multimedia.

You’ll follow a similar pattern when working with any given ContentProvider, including custom ones.

You want to expose data collected by your app to other apps, and even allow them to add to this data. You want to give other apps flexibility in how they query this data, and
you don’t want to maintain an application/service layer for doing this.

let’s look at how we implement a ContentProvider to allow apps (including our own!) to use this data. First, we must declare our custom ContentProvider in our AndroidManifest.xml:

<provider android:name="example.mymoviesdatabase.provider.MyMoviesProvider"
			android:authorities="example.mymoviesdatabase" />

subclass the abstract class android.content.ContentProvider.

create the class MyMoviesContract

public class MyMoviesContract {
	public static final String AUTHORITY = "example.mymoviesdatabase";
	public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
	private MyMoviesContract(){
		
	}
	public static final class Movies{
		public static final Uri CONTENT_URI=Uri.withAppendedPath(AUTHORITY_URI, "movies");
		private Movies(){
			
		}
		public static abstract class MovieColumns extends MovieTable.MovieColumns{
			public static final String CATEGORIES = "category_names";
			private MovieColumns(){
				
			}
			static final HashMap<String,String> projectionMap=new HashMap<String,String>(){
				{
					put(_ID, _ID);
			        put(NAME, NAME);
		            put(RATING, RATING);
		            put(TAGLINE, TAGLINE);
		            put(THUMB_URL, THUMB_URL);
		            put(IMAGE_URL, IMAGE_URL);
		            put(TRAILER, TRAILER);
		            put(URL, URL);
		            put(YEAR, YEAR);
		            put(CATEGORIES, "mcat.names");
				}
				 
			};
		}
	}
}
subclass the abstract class android.content.ContentProvider:

public class MyMoviesProvider extends ContentProvider {
  final private static int MOVIES = 1;
  final private static int MOVIE_ID = 2;
  final private static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  static {
     uriMatcher.addURI(AUTHORITY, "movies", MOVIES);
     uriMatcher.addURI(AUTHORITY, "movies/#", MOVIE_ID);
  }
  private SQLiteDatabase db;//Ref to SQLite db where data is stored
  
  @Override
  public boolean onCreate() {
  SQLiteOpenHelper openHelper=new OpenHelper(getContext());
  db=openHelper.getWritableDatabase();
      return true;
  }


@Override
public Cursor query(Uri uri, final String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Set<String> projectionCols=new HashSet<String>();
//if projection valid
if(projection!=null){
projectionCols=new HashSet<String>(Arrays.asList(projection));
if(!MyMoviesContract.Movies.MovieColumns.projectionMap.keySet().containsAll(projectionCols)){
throw new IllegalArgumentException("Unrecognized column(s) in projection");
}
}
SQLiteQueryBuilder qb=new SQLiteQueryBuilder();
switch(uriMatcher.match(uri)){
case MOVIES:
//query all movies
qb.setTables(MovieTable.TABLE_NAME);
return qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
case MOVIE_ID:
//query particular movie
long movieId=ContentUris.parseId(uri);
StringBuilder tables=new StringBuilder(MovieTable.TABLE_NAME).append(" as outer_movie");
LinkedList<String> newSelectionArgs=new LinkedList<String>();
newSelectionArgs.add(String.valueOf(movieId));
if(selectionArgs!=null){
newSelectionArgs.addAll(Arrays.asList(selectionArgs));
}
String[] allSelectionArgs=newSelectionArgs.toArray(new String[0]);
//join category table
if(projectionCols.contains(MyMoviesContract.Movies.MovieColumns.CATEGORIES)){
tables.append(" left outer join (select group_concat(")
.append(CategoryColumns.NAME)
.append(") as names from ")
.append(MovieCategoryTable.TABLE_NAME)
.append(", ")
.append(CategoryTable.TABLE_NAME)
.append(" where ")
.append(MovieCategoryTable.TABLE_NAME)
.append(".")
.append(MovieCategoryColumns.MOVIE_ID)
.append("= ? and ")
.append(MovieCategoryTable.TABLE_NAME)
.append(".")
.append(MovieCategoryColumns.CATEGORY_ID)
.append("=")
.append(CategoryTable.TABLE_NAME)
.append(".")
.append(CategoryColumns._ID)
.append(") mcat");
}
StringBuilder where=new StringBuilder();
where.append("outer_moview.").append(MovieColumns._ID).append("=?");
qb.setProjectionMap(MyMoviesContract.Movies.MovieColumns.projectionMap);
qb.setTables(tables.toString());
qb.appendWhere(where.toString());
return qb.query(db, projection, selection, allSelectionArgs, null, null, sortOrder);
case UriMatcher.NO_MATCH:
        default:
           throw new IllegalArgumentException("unrecognized URI " + uri);

}
  }

@Override
public String getType(Uri arg0) {
// TODO Auto-generated method stub
return null;
}

@Override
  public Uri insert(Uri uri, ContentValues cv) {
     switch (uriMatcher.match(uri)) {
        case MOVIES:
           db.beginTransaction();
           long id = -1;
           try {
              String categoryNames = "";
              if (cv.containsKey(MyMoviesContract.Movies.MovieColumns.CATEGORIES)) {
                 categoryNames = cv.getAsString(MyMoviesContract.Movies.MovieColumns.CATEGORIES);
                 cv = new ContentValues(cv);
                 cv.remove(MyMoviesContract.Movies.MovieColumns.CATEGORIES);
              }
              id = db.insert(MovieTable.TABLE_NAME, null, cv);
              Iterable<Category> categories = getOrCreateCategories(categoryNames.split(","));
              for (Category cat : categories) {
                 ContentValues movieCat = new ContentValues();
                 movieCat.put(MovieCategoryColumns.MOVIE_ID, id);
                 movieCat.put(MovieCategoryColumns.CATEGORY_ID, cat.getId());
                 db.insert(MovieCategoryTable.TABLE_NAME, null, movieCat);
              }
              db.setTransactionSuccessful();
           } finally {
              db.endTransaction();
           }


           if (id >= 0) {
              return ContentUris.withAppendedId(MyMoviesContract.Movies.CONTENT_URI, id);
           } else {
              return null;
           }
        case UriMatcher.NO_MATCH:
        default:
           throw new IllegalArgumentException("unrecognized URI " + uri);
     }
  }


  @Override
  public int delete(Uri uri, String selection, String[] selectionArgs) {
     switch (uriMatcher.match(uri)) {
        case MOVIE_ID:
           long movieId = ContentUris.parseId(uri);


           StringBuilder where = new StringBuilder(MovieColumns._ID).append("=?");
           if (selection != null) {
              where.append(" and ").append(selection);
           }
           selection = where.toString();


           String[] allSelectionArgs = new String[1 + (selectionArgs == null ? 0 : selectionArgs.length)];
           allSelectionArgs[0] = String.valueOf(movieId);
           if (selectionArgs != null) {
              System.arraycopy(selectionArgs, 0, allSelectionArgs, 1, selectionArgs.length);
           }


           String categoriesSelection = new StringBuilder(MovieCategoryColumns.MOVIE_ID).append("=?").toString();
           String[] categoriesArgs = new String[] { String.valueOf(movieId) };


           int rowsDeleted = 0;
           db.beginTransaction();
           try {
              db.delete(MovieCategoryTable.TABLE_NAME, categoriesSelection, categoriesArgs);
              rowsDeleted = db.delete(MovieTable.TABLE_NAME, selection, allSelectionArgs);
              db.setTransactionSuccessful();
           } finally {
              db.endTransaction();
           }


           return rowsDeleted;


        case UriMatcher.NO_MATCH:
        default:
           throw new IllegalArgumentException("unrecognized URI " + uri);
     }
  }


  @Override
  public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) {
     switch (uriMatcher.match(uri)) {
        case MOVIE_ID:
           long movieId = ContentUris.parseId(uri);


           String categoryNames = null;
           int updated = 0;
           if (contentValues.containsKey(MyMoviesContract.Movies.MovieColumns.CATEGORIES)) {
              contentValues = new ContentValues(contentValues);
              categoryNames = contentValues.getAsString(MyMoviesContract.Movies.MovieColumns.CATEGORIES);
              contentValues.remove(MyMoviesContract.Movies.MovieColumns.CATEGORIES);
           }


           StringBuilder where = new StringBuilder(MovieColumns._ID).append("=?");
           if (selection != null) {
              where.append(" and ").append(selection);
           }
           selection = where.toString();
           String[] allSelectionArgs = new String[1 + (selectionArgs == null ? 0 : selectionArgs.length)];
           allSelectionArgs[0] = String.valueOf(movieId);
           if (selectionArgs != null) {
              System.arraycopy(selectionArgs, 0, allSelectionArgs, 1, selectionArgs.length);
           }


           db.beginTransaction();
           try {
              boolean updateCategories = false;
              if (contentValues.size() > 0) {
                 updated = db.update(MovieTable.TABLE_NAME, contentValues, selection, allSelectionArgs);
                 updateCategories = updated > 0;
              } else {
                 Cursor c =
                          db.query(MovieTable.TABLE_NAME, new String[] { MovieColumns._ID }, selection,
                                   allSelectionArgs, null, null, null);
                 updateCategories = c.getCount() > 0;
                 c.close();
              }


              if (categoryNames != null && updateCategories) {
                 String categoriesSelection = new StringBuilder(MovieCategoryColumns.MOVIE_ID).append("=?").toString();
                 String[] categoriesArgs = new String[] { String.valueOf(movieId) };
                 db.delete(MovieCategoryTable.TABLE_NAME, categoriesSelection, categoriesArgs);


                 Iterable<Category> categories = getOrCreateCategories(categoryNames.split(","));
                 for (Category cat : categories) {
                    ContentValues movieCat = new ContentValues();
                    movieCat.put(MovieCategoryColumns.MOVIE_ID, movieId);
                    movieCat.put(MovieCategoryColumns.CATEGORY_ID, cat.getId());
                    db.insert(MovieCategoryTable.TABLE_NAME, null, movieCat);
                 }
                 updated = 1;
              }
              db.setTransactionSuccessful();
           } finally {
              db.endTransaction();
           }


           return updated;
        case UriMatcher.NO_MATCH:
        default:
           throw new IllegalArgumentException("unrecognized URI " + uri);
     }
  }


  private Iterable<Category> getOrCreateCategories(String... names) {
     LinkedList<Category> categories = new LinkedList<Category>();
     for (String name : names) {
        String where = new StringBuilder(CategoryColumns.NAME).append("=?").toString();
        String[] whereArgs = new String[] { name };
        Cursor cursor =
                 db.query(CategoryTable.TABLE_NAME, new String[] { CategoryColumns._ID, CategoryColumns.NAME }, where,
                          whereArgs, null, null, null);
        if (cursor.moveToFirst()) {
           categories.add(new Category(cursor.getLong(0), cursor.getString(1)));
           cursor.close();
        } else {
           cursor.close();
           ContentValues cv = new ContentValues(1);
           cv.put(CategoryColumns.NAME, name);
           long id = db.insert(CategoryTable.TABLE_NAME, null, cv);
           categories.add(new Category(id, name));
        }
     }
     return categories;
  }
}

你可能感兴趣的:(android in practice_Working with a custom ContentProvider(MyMoviesContentProvider))