Android Open Source - streaming_project Media Provider






From Project

Back to project page streaming_project.

License

The source code is released under:

GNU General Public License

If you think the Android project streaming_project listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.example.streaming.streaming;
//from   w w w .  j  a  va2s  .c  o  m

import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;


/*
The content provider manages access to a central repository of data (e.g. SQLite database) by other
applications or activities within the provider's application. It serves as an interface to data
saved in a structured format. It uses an SQLite database API to store the media information with the
help of the SQLiteOpenHelper. All other parts of the app can only access through the Content
Resolver.

Six abstract methods from the abstract class ContentProvider must be implemented: query(), insert(),
update(), delete(), getType(), and onCreate(). However, your code doesn't to do anything in each
method except return the expected data type.
onCreate() is the only method that is not called by the application client that is attempting to
access the content provider.

TODO: This provider will combine table data and files since it will be serving media-related data
TODO: (videos and music).

NOTE 1: Queries must not be performed on the UI thread. They should be done asynchronously on a
separate thread. CursorLoader or AsyncQueryHandler can be used to accomplish that.
NOTE 2: All the methods except onCreate() can be called by multiple threads at once, so they must be
thread-safe
NOTE 3: This provider is defined in the manifest, just like we do for Activity and Service
components.
NOTE 4: since permission to use the provider is not added in the manifest, all applications can read
from or write to the provider

References:
http://blog.stylingandroid.com/adapters-part-5/
http://developer.android.com/guide/topics/providers/content-provider-basics.html
http://developer.android.com/guide/topics/providers/content-provider-creating.html
*/
public class MediaProvider extends ContentProvider {
    private static final int ITEMS = 1;
    private static final int ITEM_ID = 2;

    private static final String AUTHORITY = "com.example.streaming.streaming";
    private static final String BASE_PATH = MediaDatabaseHelper.TABLE_MEDIA;
    public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/items";
    public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/item";

    // A "projection" defines the columns that will be returned for each row by the query
    public static final String[] PROJECTION = {
            MediaDatabaseHelper.COLUMN_MEDIA_ID,
            MediaDatabaseHelper.COLUMN_MEDIA_ARTIST
    };

    // Content URI of the com.example.streaming.streaming's "media" table
    // It is a URI that identifies data in the provider. It includes the AUTHORITY which is the
    // symbolic name of the entire provider and a PATH which is a name that points to a table
    // NOTE 1: the string content:// (the scheme) is always present, and identifies this as a
    // content URI
    // NOTE 2: The optional id part points to an individual row in a table
    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);

    // Handle to the database helper object
    private MediaDatabaseHelper helper;

    // TODO: How does UriMatcher works?
    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    static
    {
        sURIMatcher.addURI(AUTHORITY, BASE_PATH, ITEMS);
        sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/#", ITEM_ID);
    }

    @Override
    // Initializes the provider. It is called by the OS after the provider is created.
    // NOTE 1: The provider is not created until ContentResolver object tries to access it
    // NOTE 2: Avoid doing lengthy computations in onCreate()
    public boolean onCreate()
    {
        // Create a new helper object
        // NOTE: the database itself isn't created or opened until
        // SQLiteOpenHelper.getWritableDatabase is called
        helper = new MediaDatabaseHelper(getContext());
        return helper != null;
    }

    @Override
    // Retrieves data from the provider and returns a Cursor object over the result set
    // The built query is analogous to the SQL statement:
    // SELECT column_name FROM table_name WHERE column_name = val ORDER BY column_name ASC;
    // NOTE: It returns null if there is an internal error
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
    {
        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
        queryBuilder.setTables(MediaDatabaseHelper.TABLE_MEDIA);

        int uriType = sURIMatcher.match(uri);
        switch (uriType)
        {
            case ITEMS:
                break;
            case ITEM_ID:
                queryBuilder.appendWhere(MediaDatabaseHelper.COLUMN_ID + "=" + uri.getLastPathSegment());
                break;
            default:
                // The provider received an invalid content URI
                // NOTE: Android can communicate the following exceptions across process boundaries:
                // IllegalArgumentException and NullPointerException
                throw new IllegalArgumentException("Unknown URI: " + uri);
        }

        SQLiteDatabase db = helper.getWritableDatabase();
        // A cursor is a list of rows and it can be linked to a ListView via a SimpleCursorAdapter
        // to display its contents
        // NOTE: To back a ListView with a Cursor, the cursor must contain a column named _ID
        // TODO: Make sure that if the query doesn't match any rows, a Cursor instance whose getCount() method returns 0
        Cursor cursor = queryBuilder.query(
                db,             // Database to query on
                projection,     // The columns to return for each row
                selection,      // Setting the selection clause to null will return all words
                selectionArgs,  // Selection arguments array
                null,           // GROUP BY clause. null will cause the rows to not be grouped
                null,           // having clase. null will cause all row groups to be included
                sortOrder);     // ORDER BY cluase. null will use the default sort order, which may
                                // be unordered
        cursor.setNotificationUri(getContext().getContentResolver(), uri);

        // Some providers return null if an error occurs, others throw an exception
        return cursor;
    }

    @Override
    // Returns the MIME type of the content URI
    public String getType(Uri uri) {
        return null;
    }

    @Override
    // Inserts a new row in the provider and returns a content URI for the new row.
    // NOTE: "values" defines an object to contain the new values to insert
    // TODO: If a column name is not in the ContentValues argument, provide a default value for it
    // TODO: either in provider code or in the database schema
    public Uri insert(Uri uri, ContentValues values) {
        int uriType = sURIMatcher.match(uri);
        SQLiteDatabase sqlDB = helper.getWritableDatabase();
        long id = 0;
        switch (uriType)
        {
            case ITEMS:
                // TODO: Why do we add the size of values?  Should not values.size be 1 since we are inserting just one row at a time?
                if(getRowCount() + values.size() <= MediaDatabaseHelper.MAX_ROWS) {
                    id = sqlDB.insert(
                            MediaDatabaseHelper.TABLE_MEDIA,    // The table to query on
                            null,                               // nullColumnHack
                            values);                            // The values to insert
                }
                break;
            default:
                throw new IllegalArgumentException("Unknown URI: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        // The content URI returned identifies the newly-added row, with the following format:
        // content://<authority>/<table_name>/<id_value>
        // where id_value is the contents of _ID for the new row
        // TODO: Use withAppendedId() to append the new row's _ID value to the table's content URI
        // TODO: see "Implementing the insert() method" in http://developer.android.com/guide/topics/providers/content-provider-creating.html#ContentProvider
        return Uri.parse(BASE_PATH + "/" + id);
    }

    @Override
    // Deletes rows from the provider and returns the number of deleted rows
    public int delete(Uri uri, String selection, String[] selectionArgs)
    {
        int uriType = sURIMatcher.match(uri);
        SQLiteDatabase sqlDB = helper.getWritableDatabase();
        int rowsDeleted = 0;
        switch (uriType) {
            case ITEMS:
                rowsDeleted = sqlDB.delete(
                        MediaDatabaseHelper.TABLE_MEDIA,   // The table to query on
                        selection,                         // The column to select on
                        selectionArgs);                    // The value to compare to
                break;
            case ITEM_ID:
                String id = uri.getLastPathSegment();
                if (TextUtils.isEmpty(selection)) {
                    rowsDeleted = sqlDB.delete(MediaDatabaseHelper.TABLE_MEDIA, MediaDatabaseHelper.COLUMN_ID + "=" + id, null);
                } else {
                    rowsDeleted = sqlDB.delete(MediaDatabaseHelper.TABLE_MEDIA, MediaDatabaseHelper.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
                }
                break;
            default:
                throw new IllegalArgumentException("Unknown URI: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return rowsDeleted;
    }

    @Override
    // Updates existing rows in the provider and returns the number of rows updated
    // NOTE 1: "values" defines an object that contains the updated values
    // NOTE 2: "selection" and "selectionArgs" define selection criteria for the rows to be updated
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

        int uriType = sURIMatcher.match(uri);
        SQLiteDatabase sqlDB = helper.getWritableDatabase();
        int rowsUpdated = 0;
        switch (uriType) {
            case ITEMS:
                rowsUpdated = sqlDB.update(
                        MediaDatabaseHelper.TABLE_MEDIA,    // The table to query on
                        values,                             // The columns to update
                        selection,                          // The columns to select on
                        selectionArgs);                     // The value to compare to
                break;
            case ITEM_ID:
                String id = uri.getLastPathSegment();
                if (TextUtils.isEmpty(selection)) {
                    rowsUpdated = sqlDB.update(
                            MediaDatabaseHelper.TABLE_MEDIA,
                            values,
                            MediaDatabaseHelper.COLUMN_ID + "=" + id,
                            null);
                } else {
                    rowsUpdated = sqlDB.update(
                            MediaDatabaseHelper.TABLE_MEDIA,
                            values,
                            MediaDatabaseHelper.COLUMN_ID + "=" + id + " and " + selection,
                            selectionArgs);
                }
                break;
            default:
                throw new IllegalArgumentException("Unknown URI: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return rowsUpdated;
    }

    // Returns number of rows in the table
    private long getRowCount() {
        return DatabaseUtils.queryNumEntries(helper.getReadableDatabase(), MediaDatabaseHelper.TABLE_MEDIA);
    }
}




Java Source Code List

com.example.streaming.streaming.ApplicationTest.java
com.example.streaming.streaming.AssetsPropertyReader.java
com.example.streaming.streaming.DataFetcher.java
com.example.streaming.streaming.DataLoader.java
com.example.streaming.streaming.MainActivity.java
com.example.streaming.streaming.MediaActivity.java
com.example.streaming.streaming.MediaDatabaseHelper.java
com.example.streaming.streaming.MediaFragment.java
com.example.streaming.streaming.MediaListActivity.java
com.example.streaming.streaming.MediaListFragment.java
com.example.streaming.streaming.MediaLoader.java
com.example.streaming.streaming.MediaManager.java
com.example.streaming.streaming.MediaProvider.java
com.example.streaming.streaming.Media.java
com.example.streaming.streaming.SQLiteCursorLoader.java
com.example.streaming.streaming.SingleFragmentActivity.java