Search code examples
androiduriandroid-contentproviderandroid-4.2-jelly-bean

Android : Content Provider : Uri Type Wrong on Jellybean 4.2.2


I am having problems with acquiring proper uriType on Jellybean 4.2.2. The code given below works fine on other versions.

package com.karacraft.security;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;   
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;

import com.karacraft.data.ItemsContract;
import com.karacraft.data.MasterSahabDatabaseHelper;
import com.karacraft.data.MerchandisesContract;
import com.karacraft.data.OrdersContract;
import com.karacraft.data.StaffContract;
import com.karacraft.data.StatsContract;
import com.karacraft.data.SuitsContract;
import com.karacraft.data.TailorsContract;
import com.karacraft.utils.Constants;


public class MasterSahabProvider extends ContentProvider
{
public static final String AUTHORITY ="com.karacraft.security.mastersahab";
public static final String KEY_URI = "/#";

//database
private MasterSahabDatabaseHelper database;

//Table Names
private static final String ITEMS_TABLE         = "/" + ItemsContract.TABLE_ITEMS;
private static final String MERCHANDISES_TABLE  = "/" + MerchandisesContract.TABLE_MERCHANDISES;
private static final String ORDERS_TABLE        = "/" + OrdersContract.TABLE_ORDERS;
private static final String SUITS_TABLE         = "/" + SuitsContract.TABLE_SUITS;
private static final String TAILORS_TABLE       = "/" + TailorsContract.TABLE_TAILORS;
private static final String STAFF_TABLE         = "/" + StaffContract.TABLE_STAFF;
private static final String STATS_TABLE         = "/" + StatsContract.TABLE_STATS;

//Uri for Multiple Tables
public static final Uri CONTENT_URI_ITEMS           = Uri.parse("content://" + AUTHORITY + ITEMS_TABLE);
public static final Uri CONTENT_URI_MERCHANDISES    = Uri.parse("content://" + AUTHORITY + MERCHANDISES_TABLE);
public static final Uri CONTENT_URI_ORDERS          = Uri.parse("content://" + AUTHORITY + ORDERS_TABLE);
public static final Uri CONTENT_URI_SUITS           = Uri.parse("content://" + AUTHORITY + SUITS_TABLE);
public static final Uri CONTENT_URI_TAILORS         = Uri.parse("content://" + AUTHORITY + TAILORS_TABLE);
public static final Uri CONTENT_URI_STAFF           = Uri.parse("content://" + AUTHORITY + STAFF_TABLE);
public static final Uri CONTENT_URI_STATS           = Uri.parse("content://" + AUTHORITY + STATS_TABLE);

public static final Uri CONTENT_URI_ORDERS_BY_MERC  = Uri.parse("content://" + AUTHORITY + ORDERS_TABLE);

//Return value setup for Uri Matchers
private static final int ITEMS          = 10;
private static final int ITEM_ID        = 20;
private static final int MERCHANDISES   = 30;
private static final int MERCHANDISE_ID = 40;
private static final int ORDERS         = 50;
private static final int ORDERS_ID      = 60;
private static final int SUITS          = 70;
private static final int SUITS_ID       = 80;
private static final int TAILORS        = 90;
private static final int TAILORS_ID     = 100;
private static final int STAFF          = 110;
private static final int STAFF_ID       = 120;
private static final int STATS          = 130;
private static final int STATS_ID       = 140;

private static final int ORDERS_BY_MERC = 200;

//Custom Method
private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
    uriMatcher.addURI(AUTHORITY, ITEMS_TABLE,ITEMS);
    uriMatcher.addURI(AUTHORITY, ITEMS_TABLE + KEY_URI,ITEM_ID);
    uriMatcher.addURI(AUTHORITY, MERCHANDISES_TABLE,MERCHANDISES);
    uriMatcher.addURI(AUTHORITY, MERCHANDISES_TABLE + KEY_URI,MERCHANDISE_ID);
    uriMatcher.addURI(AUTHORITY, ORDERS_TABLE,ORDERS);
    uriMatcher.addURI(AUTHORITY, ORDERS_TABLE + KEY_URI,ORDERS_ID);
    uriMatcher.addURI(AUTHORITY, SUITS_TABLE,SUITS);
    uriMatcher.addURI(AUTHORITY, SUITS_TABLE + KEY_URI,SUITS_ID);
    uriMatcher.addURI(AUTHORITY, TAILORS_TABLE,TAILORS);
    uriMatcher.addURI(AUTHORITY, TAILORS_TABLE + KEY_URI,TAILORS_ID);
    uriMatcher.addURI(AUTHORITY, STAFF_TABLE , STAFF);
    uriMatcher.addURI(AUTHORITY, STAFF_TABLE + KEY_URI, STAFF_ID);
    uriMatcher.addURI(AUTHORITY, STATS_TABLE , STATS);
    uriMatcher.addURI(AUTHORITY, STATS_TABLE + KEY_URI, STATS_ID);

    uriMatcher.addURI(AUTHORITY,ORDERS_TABLE ,ORDERS);
}

public boolean onCreate()
{
    //Create Database
    database = new MasterSahabDatabaseHelper(getContext());
    return false;
}

/**
URI         uri         The URI of the object(s) to access. This is the only argument that must not be null
String[]    projection  This String array indicates which columns/attributes of the objects you want to access
String      selection   With this argument you can determine which records to return
String[]    selectionArgs   The binding parameters to the previous selection argument
String      sortOrder   If the result should be ordered you must use this argument to determine the sort order
*/
@Nullable
@Override
public Cursor query(Uri uri
        , String[] projection
        , String selection
        , String[] selectionArgs
        , String sortOrder)
{
    //Using SQLiteQueryBuilder instead of query() method
    SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
    SQLiteDatabase db = database.getWritableDatabase();
    Cursor cursor=null;

    int uriType = uriMatcher.match(uri);
    Log.d(Constants.APP_TAG,"URIType is : " + uriType);
    Log.d(Constants.APP_TAG,"URI is : " + uri.toString());

    switch (uriType){
        case ITEMS:
            //Set the table
            builder.setTables(ItemsContract.TABLE_ITEMS);
            //adding the ID to original Query
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
            break;
        case ITEM_ID:
            //Set the table
            builder.setTables(ItemsContract.TABLE_ITEMS);
            //adding the ID to original Query
            builder.appendWhere(ItemsContract.ITEM_ID + "=" + uri.getLastPathSegment());
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(), uri);
            break;
        case MERCHANDISES:
            //Set the table
            builder.setTables(MerchandisesContract.TABLE_MERCHANDISES);
            //adding the ID to original Query
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
            break;
        case MERCHANDISE_ID:
            //Set the table
            builder.setTables(MerchandisesContract.TABLE_MERCHANDISES);
            //adding the ID to original Query
            builder.appendWhere(MerchandisesContract.MERCHANDISE_ID + "=" + uri.getLastPathSegment());
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
            break;
        case ORDERS:
            //Set the table
            builder.setTables(OrdersContract.TABLE_ORDERS);
            //adding the ID to original Query
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
            break;
        case ORDERS_ID:
            //Set the table
            builder.setTables(OrdersContract.TABLE_ORDERS);
            //adding the ID to original Query
            builder.appendWhere(OrdersContract.ORDER_ID + "=" + uri.getLastPathSegment());
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
            break;
        case TAILORS:
            //Set the table
            builder.setTables(TailorsContract.TABLE_TAILORS);
            //adding the ID to original Query
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
            break;
        case TAILORS_ID:
            //Set the table
            builder.setTables(TailorsContract.TABLE_TAILORS);
            //adding the ID to original Query
            builder.appendWhere(TailorsContract.TAILOR_ID + "=" + uri.getLastPathSegment());
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
            break;
        case SUITS:
            //Set the table
            builder.setTables(SuitsContract.TABLE_SUITS);
            //adding the ID to original Query
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
            break;
        case SUITS_ID:
            //Set the table
            builder.setTables(SuitsContract.TABLE_SUITS);
            //adding the ID to original Query
            builder.appendWhere(SuitsContract.SUITS_ID + "=" + uri.getLastPathSegment());
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
            break;
        case STAFF:
            //Set the table
            builder.setTables(StaffContract.TABLE_STAFF);
            //adding the ID to original Query
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
            break;
        case STAFF_ID:
            //Set the table
            builder.setTables(StaffContract.TABLE_STAFF);
            //adding the ID to original Query
            builder.appendWhere(StaffContract.STAFF_ID + "=" + uri.getLastPathSegment());
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
            break;
        case STATS:
            //Set the table
            builder.setTables(StatsContract.TABLE_STATS);
            //adding the ID to original Query
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
            break;
        case STATS_ID:
            //Set the table
            builder.setTables(StatsContract.TABLE_STATS);
            //adding the ID to original Query
            builder.appendWhere(StatsContract.STATS_ID + "=" + uri.getLastPathSegment());
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
            break;
        case ORDERS_BY_MERC:
            //Set the table
            //builder.setTables("orders LEFT OUTER JOIN staff ON (orders.staff_id = staff._id)");
            builder.setTables("orders LEFT OUTER JOIN staff ON orders.staff_id = staff._id");
            //builder.setTables("orders,staff");
            //adding the ID to original Query
            cursor = builder.query(db,projection,selection,selectionArgs,null,null,sortOrder);
            // make sure that potential listeners are getting notified
            cursor.setNotificationUri(getContext().getContentResolver(),uri);
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }
    return cursor;
}

@Nullable
@Override
public String getType(Uri uri)
{
    return null;
}

@Nullable
@Override
public Uri insert(Uri uri
        , ContentValues values)
{
    int uriType = uriMatcher.match(uri);
    SQLiteDatabase db = database.getWritableDatabase();
    Log.d(Constants.APP_TAG,"URIType is : " + uriType);
    Log.d(Constants.APP_TAG,"URI is : " + uri.toString());

    long id = 0;
    switch (uriType){
        case ITEMS:
            id = db.insert(ItemsContract.TABLE_ITEMS, null, values);
            getContext().getContentResolver().notifyChange(uri,null);
            return Uri.parse(ITEMS_TABLE + "/" + id);

        case MERCHANDISES:
            id = db.insert(MerchandisesContract.TABLE_MERCHANDISES,null,values);
            getContext().getContentResolver().notifyChange(uri,null);
            return Uri.parse(MERCHANDISES_TABLE + "/" + id);

        case ORDERS:
            id = db.insert(OrdersContract.TABLE_ORDERS,null,values);
            getContext().getContentResolver().notifyChange(uri,null);
            return Uri.parse(ORDERS_TABLE + "/" + id);

        case SUITS:
            id = db.insert(SuitsContract.TABLE_SUITS,null,values);
            getContext().getContentResolver().notifyChange(uri,null);
            return Uri.parse(SUITS_TABLE + "/" + id);

        case STAFF:
            id = db.insert(StaffContract.TABLE_STAFF,null, values);
            getContext().getContentResolver().notifyChange(uri,null);
            return Uri.parse(STAFF_TABLE + "/" + id);

        case TAILORS:
            id = db.insert(TailorsContract.TABLE_TAILORS,null,values);
            getContext().getContentResolver().notifyChange(uri,null);
            return Uri.parse(TAILORS_TABLE + "/" + id);

        case STATS:
            id = db.insert(StatsContract.TABLE_STATS,null,values);
            getContext().getContentResolver().notifyChange(uri,null);
            return Uri.parse(STATS_TABLE + "/" + id);
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }
}

@Override
public int delete(Uri uri
        , String selection
        , String[] selectionArgs)
{
    int uriType = uriMatcher.match(uri);
    SQLiteDatabase sqlDB = database.getWritableDatabase();
    int rowsDeleted = 0;
    String id ="";

    Log.d(Constants.APP_TAG,"URIType is : " + uriType);
    Log.d(Constants.APP_TAG,"URI is : " + uri.toString());

    switch (uriType) {
        case ITEMS:
            rowsDeleted = sqlDB.delete(ItemsContract.TABLE_ITEMS, selection, selectionArgs);
            break;
        case ITEM_ID:
            id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = sqlDB.delete(ItemsContract.TABLE_ITEMS, ItemsContract.ITEM_ID + "=" + id, null);
            } else {
                rowsDeleted = sqlDB.delete(ItemsContract.TABLE_ITEMS, ItemsContract.ITEM_ID + "=" + id + " AND " + selection, selectionArgs);
            }
            break;
        case MERCHANDISES:
            rowsDeleted = sqlDB.delete(MerchandisesContract.TABLE_MERCHANDISES, selection, selectionArgs);
            break;
        case MERCHANDISE_ID:
            id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = sqlDB.delete(MerchandisesContract.TABLE_MERCHANDISES, MerchandisesContract.MERCHANDISE_ID+ "=" + id, null);
            } else {
                rowsDeleted = sqlDB.delete(MerchandisesContract.TABLE_MERCHANDISES, MerchandisesContract.MERCHANDISE_ID + "=" + id + " AND " + selection, selectionArgs);
            }
            break;
        case TAILORS:
            rowsDeleted = sqlDB.delete(TailorsContract.TABLE_TAILORS, selection, selectionArgs);
            break;
        case TAILORS_ID:
            id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = sqlDB.delete(TailorsContract.TABLE_TAILORS, TailorsContract.TAILOR_ID + "=" + id, null);
            } else {
                rowsDeleted = sqlDB.delete(TailorsContract.TABLE_TAILORS, TailorsContract.TAILOR_ID + "=" + id + " AND " + selection, selectionArgs);
            }
            break;
        case STAFF:
            rowsDeleted = sqlDB.delete(StaffContract.TABLE_STAFF, selection, selectionArgs);
            break;
        case STAFF_ID:
            id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = sqlDB.delete(StaffContract.TABLE_STAFF, StaffContract.STAFF_ID + "=" + id, null);
            } else {
                rowsDeleted = sqlDB.delete(StaffContract.TABLE_STAFF, StaffContract.STAFF_ID + "=" + id + " AND " + selection, selectionArgs);
            }
            break;
        case SUITS:
            rowsDeleted = sqlDB.delete(SuitsContract.TABLE_SUITS, selection, selectionArgs);
            break;
        case SUITS_ID:
            id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = sqlDB.delete(SuitsContract.TABLE_SUITS, SuitsContract.SUITS_ID + "=" + id, null);
            } else {
                rowsDeleted = sqlDB.delete(SuitsContract.TABLE_SUITS, SuitsContract.SUITS_ID + "=" + id + " AND " + selection, selectionArgs);
            }
            break;
        case ORDERS:
            rowsDeleted = sqlDB.delete(OrdersContract.TABLE_ORDERS, selection, selectionArgs);
            break;
        case ORDERS_ID:
            id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = sqlDB.delete(OrdersContract.TABLE_ORDERS, OrdersContract.ORDER_ID + "=" + id, null);
            } else {
                rowsDeleted = sqlDB.delete(OrdersContract.TABLE_ORDERS, OrdersContract.ORDER_ID + "=" + id + " AND " + selection, selectionArgs);
            }
            break;
        case STATS:
            rowsDeleted = sqlDB.delete(StatsContract.TABLE_STATS, selection, selectionArgs);
            break;
        case STATS_ID:
            id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = sqlDB.delete(StatsContract.TABLE_STATS, StatsContract.STATS_ID + "=" + id, null);
            } else {
                rowsDeleted = sqlDB.delete(StatsContract.TABLE_STATS, StatsContract.STATS_ID + "=" + id + " AND " + selection, selectionArgs);
            }
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return rowsDeleted;
}

@Override
public int update(Uri uri
        , ContentValues values
        , String selection
        , String[] selectionArgs)
{
    int uriType = uriMatcher.match(uri);
    SQLiteDatabase db = database.getWritableDatabase();
    int rowsUpdated=0;
    Log.d(Constants.APP_TAG,"URIType is : " + uriType);
    Log.d(Constants.APP_TAG,"URI is : " + uri.toString());

    switch (uriType){
        case ITEMS:
            rowsUpdated = db.update(ItemsContract.TABLE_ITEMS,values,selection,selectionArgs);
            break;
        case ITEM_ID:
            String id = uri.getLastPathSegment();
            if(TextUtils.isEmpty(selection)){
                rowsUpdated = db.update(ItemsContract.TABLE_ITEMS,values, ItemsContract.ITEM_ID + "=" + id,null);
            }else{
                rowsUpdated = db.update(ItemsContract.TABLE_ITEMS,values, ItemsContract.ITEM_ID + "=" + id + " AND " + selection,selectionArgs);
            }
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }
    getContext().getContentResolver().notifyChange(uri,null);
    return rowsUpdated;
    }
}

I've checked the above content provider code with Emulators and physical sets, and all are working fine (I've tried it on 5.0, 5.1 and 6.0 emulator).

And here is the Logcat For (JellyBean 4.2.2):

02-20 21:12:27.480 1796-1808/? D/PTI: URIType is : -1
02-20 21:12:27.480 1796-1808/? D/PTI: URI is : content://com.karacraft.security.mastersahab/items
02-20 21:12:27.480 1796-1808/? E/DatabaseUtils: Writing exception to parcel
    java.lang.IllegalArgumentException: Unknown URI: content://com.karacraft.security.mastersahab/items
at com.karacraft.security.MasterSahabProvider.query(MasterSahabProvider.java:260)
at android.content.ContentProvider.query(ContentProvider.java:652)
at android.content.ContentProvider$Transport.query(ContentProvider.java:189)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:113)
at android.os.Binder.execTransact(Binder.java:351)
at dalvik.system.NativeStart.run(Native Method)

On other systems, URI always comes out as intended.

Here is Logcat for KitKat 4.4.4:

02-21 01:06:51.591 1872-1884/? D/PTI: URIType is : 10
02-21 01:06:51.591 1872-1884/? D/PTI: URI is : content://com.karacraft.security.mastersahab/items
02-21 01:06:51.631 1872-1883/? D/PTI: URIType is : 50
02-21 01:06:51.631 1872-1883/? D/PTI: URI is : content://com.karacraft.security.mastersahab/orders
02-21 01:06:51.631 1872-1884/? D/PTI: URIType is : 70
02-21 01:06:51.631 1872-1884/? D/PTI: URI is : content://com.karacraft.security.mastersahab/suits
02-21 01:06:51.631 1872-1883/? D/PTI: URIType is : 90
02-21 01:06:51.631 1872-1883/? D/PTI: URI is : content://com.karacraft.security.mastersahab/tailors
02-21 01:06:51.631 1872-1884/? D/PTI: URIType is : 130
02-21 01:06:51.631 1872-1884/? D/PTI: URI is : content://com.karacraft.security.mastersahab/stats
02-21 01:06:51.641 1872-1883/? D/PTI: URIType is : 110
02-21 01:06:51.641 1872-1883/? D/PTI: URI is : content://com.karacraft.security.mastersahab/staff
02-21 01:06:51.641 1872-1884/? D/PTI: URIType is : 30
02-21 01:06:51.641 1872-1884/? D/PTI: URI is : content://com.karacraft.security.mastersahab/merchandises

It's showing proper URI's on Kitkat.

Solution found, thanks to @MARTEN answer

Changing the Leading Slash from Table Name to URI solved the problem.

//Table Names
private static final String ITEMS_TABLE         = "/" + ItemsContract.TABLE_ITEMS;
private static final String MERCHANDISES_TABLE  = "/" + MerchandisesContract.TABLE_MERCHANDISES;
private static final String ORDERS_TABLE        = "/" + OrdersContract.TABLE_ORDERS;
private static final String SUITS_TABLE         = "/" + SuitsContract.TABLE_SUITS;
private static final String TAILORS_TABLE       = "/" + TailorsContract.TABLE_TAILORS;
private static final String STAFF_TABLE         = "/" + StaffContract.TABLE_STAFF;
private static final String STATS_TABLE         = "/" + StatsContract.TABLE_STATS;

//Uri for Multiple Tables
public static final Uri CONTENT_URI_ITEMS           = Uri.parse("content://" + AUTHORITY + ITEMS_TABLE);
public static final Uri CONTENT_URI_MERCHANDISES    = Uri.parse("content://" + AUTHORITY + MERCHANDISES_TABLE);
public static final Uri CONTENT_URI_ORDERS          = Uri.parse("content://" + AUTHORITY + ORDERS_TABLE);
public static final Uri CONTENT_URI_SUITS           = Uri.parse("content://" + AUTHORITY + SUITS_TABLE);
public static final Uri CONTENT_URI_TAILORS         = Uri.parse("content://" + AUTHORITY + TAILORS_TABLE);
public static final Uri CONTENT_URI_STAFF           = Uri.parse("content://" + AUTHORITY + STAFF_TABLE);
public static final Uri CONTENT_URI_STATS           = Uri.parse("content://" + AUTHORITY + STATS_TABLE);

This

  //Table Names
private static final String ITEMS_TABLE         =  ItemsContract.TABLE_ITEMS;
private static final String MERCHANDISES_TABLE  =  MerchandisesContract.TABLE_MERCHANDISES;
private static final String ORDERS_TABLE        =  OrdersContract.TABLE_ORDERS;
private static final String SUITS_TABLE         =  SuitsContract.TABLE_SUITS;
private static final String TAILORS_TABLE       =  TailorsContract.TABLE_TAILORS;
private static final String STAFF_TABLE         =  StaffContract.TABLE_STAFF;
private static final String STATS_TABLE         =  StatsContract.TABLE_STATS;

//Uri for Multiple Tables
public static final Uri CONTENT_URI_ITEMS           = Uri.parse("content://" + AUTHORITY + "/" + ITEMS_TABLE);
public static final Uri CONTENT_URI_MERCHANDISES    = Uri.parse("content://" + AUTHORITY + "/" +MERCHANDISES_TABLE);
public static final Uri CONTENT_URI_ORDERS          = Uri.parse("content://" + AUTHORITY + "/" +ORDERS_TABLE);
public static final Uri CONTENT_URI_SUITS           = Uri.parse("content://" + AUTHORITY + "/" +SUITS_TABLE);
public static final Uri CONTENT_URI_TAILORS         = Uri.parse("content://" + AUTHORITY + "/" +TAILORS_TABLE);
public static final Uri CONTENT_URI_STAFF           = Uri.parse("content://" + AUTHORITY + "/" +STAFF_TABLE);
public static final Uri CONTENT_URI_STATS           = Uri.parse("content://" + AUTHORITY + "/" +STATS_TABLE);

Solution

  • Support for paths with leading slashes has been added in Android 4.3. See the description of addUri, which states

    Starting from API level JELLY_BEAN_MR2, this method will accept a leading slash in the path.

    So just remove the leading slashes in your paths.

    i.e. replace

    uriMatcher.addURI(AUTHORITY, ITEMS_TABLE,ITEMS);
    

    by

    uriMatcher.addURI(AUTHORITY, ItemsContract.TABLE_ITEMS);
    

    btw. the last case statement in your query method is missing a break; which means that Uri will always throw an exception.