2015-12-26 2 views
0

Привет Я строю содержание provider.Here я получаю UnsupportedOperationExceptionUnsupportedOperationException Content Provider ошибка

FATAL EXCEPTION: ModernAsyncTask #3 
Process: com.subbu.sunshine, PID: 24784 
java.lang.RuntimeException: An error occurred while executing doInBackground() 
at android.support.v4.content.ModernAsyncTask$3.done(ModernAsyncTask.java:142) 
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355) 
at java.util.concurrent.FutureTask.setException(FutureTask.java:222) 
at java.util.concurrent.FutureTask.run(FutureTask.java:242) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
at java.lang.Thread.run(Thread.java:818) 
Caused by: java.lang.UnsupportedOperationException: Unknown uri: content://com.subbu.sunshine/weather/500081/1450809000000 
at com.subbu.sunshine.data.WeatherProvider.query(WeatherProvider.java:214) 
at android.content.ContentProvider.query(ContentProvider.java:978) 
at android.content.ContentProvider$Transport.query(ContentProvider.java:213) 
at android.content.ContentResolver.query(ContentResolver.java:478) 
at android.support.v4.content.ContentResolverCompatJellybean.query(ContentResolverCompatJellybean.java:29) 
at android.support.v4.content.ContentResolverCompat$ContentResolverCompatImplJB.query(ContentResolverCompat.java:57) 
at android.support.v4.content.ContentResolverCompat.query(ContentResolverCompat.java:125) 
at android.support.v4.content.CursorLoader.loa 

Ниже мой класс провайдера код:

package com.subbu.sunshine.data; 

import android.annotation.TargetApi; 
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; 

public class WeatherProvider extends ContentProvider { 

    // The URI Matcher used by this content provider. 
    private static final UriMatcher sUriMatcher = buildUriMatcher(); 
    private WeatherDbHelper mOpenHelper; 

    static final int WEATHER = 100; 
    static final int WEATHER_WITH_LOCATION = 101; 
    static final int WEATHER_WITH_LOCATION_AND_DATE = 102; 
    static final int LOCATION = 300; 

    private static final SQLiteQueryBuilder sWeatherByLocationSettingQueryBuilder; 

    static { 
     sWeatherByLocationSettingQueryBuilder = new SQLiteQueryBuilder(); 

     //This is an inner join which looks like 
     //weather INNER JOIN location ON weather.location_id = location._id 
     sWeatherByLocationSettingQueryBuilder.setTables(
       WeatherContract.WeatherEntry.TABLE_NAME + " INNER JOIN " + 
         WeatherContract.LocationEntry.TABLE_NAME + 
         " ON " + WeatherContract.WeatherEntry.TABLE_NAME + 
         "." + WeatherContract.WeatherEntry.COLUMN_LOC_KEY + 
         " = " + WeatherContract.LocationEntry.TABLE_NAME + 
         "." + WeatherContract.LocationEntry._ID); 
    } 

    //location.location_setting = ? 
    private static final String sLocationSettingSelection = 
      WeatherContract.LocationEntry.TABLE_NAME + 
        "." + WeatherContract.LocationEntry.COLUMN_LOCATION_SETTING + " = ? "; 

    //location.location_setting = ? AND date >= ? 
    private static final String sLocationSettingWithStartDateSelection = 
      WeatherContract.LocationEntry.TABLE_NAME + 
        "." + WeatherContract.LocationEntry.COLUMN_LOCATION_SETTING + " = ? AND " + 
        WeatherContract.WeatherEntry.COLUMN_DATE + " >= ? "; 

    //location.location_setting = ? AND date = ? 
    private static final String sLocationSettingAndDaySelection = 
      WeatherContract.LocationEntry.TABLE_NAME + 
        "." + WeatherContract.LocationEntry.COLUMN_LOCATION_SETTING + " = ? AND " + 
        WeatherContract.WeatherEntry.COLUMN_DATE + " = ? "; 

    private Cursor getWeatherByLocationSetting(Uri uri, String[] projection, String sortOrder) { 
     String locationSetting = WeatherContract.WeatherEntry.getLocationSettingFromUri(uri); 
     long startDate = WeatherContract.WeatherEntry.getStartDateFromUri(uri); 

     String[] selectionArgs; 
     String selection; 

     if (startDate == 0) { 
      selection = sLocationSettingSelection; 
      selectionArgs = new String[]{locationSetting}; 
     } else { 
      selectionArgs = new String[]{locationSetting, Long.toString(startDate)}; 
      selection = sLocationSettingWithStartDateSelection; 
     } 

     return sWeatherByLocationSettingQueryBuilder.query(mOpenHelper.getReadableDatabase(), 
       projection, 
       selection, 
       selectionArgs, 
       null, 
       null, 
       sortOrder 
     ); 
    } 

    private Cursor getWeatherByLocationSettingAndDate(
      Uri uri, String[] projection, String sortOrder) { 
     String locationSetting = WeatherContract.WeatherEntry.getLocationSettingFromUri(uri); 
     long date = WeatherContract.WeatherEntry.getDateFromUri(uri); 

     return sWeatherByLocationSettingQueryBuilder.query(mOpenHelper.getReadableDatabase(), 
       projection, 
       sLocationSettingAndDaySelection, 
       new String[]{locationSetting, Long.toString(date)}, 
       null, 
       null, 
       sortOrder 
     ); 
    } 

    /* 
     Students: Here is where you need to create the UriMatcher. This UriMatcher will 
     match each URI to the WEATHER, WEATHER_WITH_LOCATION, WEATHER_WITH_LOCATION_AND_DATE, 
     and LOCATION integer constants defined above. You can test this by uncommenting the 
     testUriMatcher test within TestUriMatcher. 
    */ 
    static UriMatcher buildUriMatcher() { 
     // 1) The code passed into the constructor represents the code to return for the root 
     // URI. It's common to use NO_MATCH as the code for this case. Add the constructor below. 
     UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 

     // 2) Use the addURI function to match each of the types. Use the constants from 
     // WeatherContract to help define the types to the UriMatcher. 
     uriMatcher.addURI(WeatherContract.CONTENT_AUTHORITY, WeatherContract.PATH_WEATHER, WEATHER); 
     uriMatcher.addURI(WeatherContract.CONTENT_AUTHORITY, WeatherContract.PATH_WEATHER + "/#", WEATHER_WITH_LOCATION); 
     uriMatcher.addURI(WeatherContract.CONTENT_AUTHORITY, WeatherContract.PATH_WEATHER + "/*/#", WEATHER_WITH_LOCATION_AND_DATE); 
     uriMatcher.addURI(WeatherContract.CONTENT_AUTHORITY, WeatherContract.PATH_LOCATION, LOCATION); 

     // 3) Return the new matcher! 
     return uriMatcher; 
    } 

    /* 
     Students: We've coded this for you. We just create a new WeatherDbHelper for later use 
     here. 
    */ 
    @Override 
    public boolean onCreate() { 
     mOpenHelper = new WeatherDbHelper(getContext()); 
     return true; 
    } 

    /* 
     Students: Here's where you'll code the getType function that uses the UriMatcher. You can 
     test this by uncommenting testGetType in TestProvider. 

    */ 
    @Override 
    public String getType(Uri uri) { 

     // Use the Uri Matcher to determine what kind of URI this is. 
     final int match = sUriMatcher.match(uri); 

     switch (match) { 
      // Student: Uncomment and fill out these two cases 
      case WEATHER_WITH_LOCATION_AND_DATE: 
       return WeatherContract.WeatherEntry.CONTENT_ITEM_TYPE; 
      case WEATHER_WITH_LOCATION: 
       return WeatherContract.WeatherEntry.CONTENT_TYPE; 
      case WEATHER: 
       return WeatherContract.WeatherEntry.CONTENT_TYPE; 
      case LOCATION: 
       return WeatherContract.LocationEntry.CONTENT_TYPE; 
      default: 
       throw new UnsupportedOperationException("Unknown uri: " + uri); 
     } 
    } 

    @Override 
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 
         String sortOrder) { 
     // Here's the switch statement that, given a URI, will determine what kind of request it is, 
     // and query the database accordingly. 
     Cursor retCursor; 
     switch (sUriMatcher.match(uri)) { 
      // "weather/*/*" 
      case WEATHER_WITH_LOCATION_AND_DATE: { 
       retCursor = getWeatherByLocationSettingAndDate(uri, projection, sortOrder); 
       break; 
      } 
      // "weather/*" 
      case WEATHER_WITH_LOCATION: { 
       retCursor = getWeatherByLocationSetting(uri, projection, sortOrder); 
       break; 
      } 
      // "weather" 
      case WEATHER: { 
       retCursor = mOpenHelper.getReadableDatabase().query(
         WeatherContract.WeatherEntry.TABLE_NAME, 
         projection, 
         selection, 
         selectionArgs, 
         null, 
         null, 
         sortOrder 
       ); 
       break; 
      } 
      // "location" 
      case LOCATION: { 
       retCursor = mOpenHelper.getReadableDatabase().query(
         WeatherContract.LocationEntry.TABLE_NAME, 
         projection, 
         selection, 
         selectionArgs, 
         null, 
         null, 
         sortOrder 
       ); 
       break; 
      } 

      default: 
       throw new UnsupportedOperationException("Unknown uri: " + uri); 
     } 
     retCursor.setNotificationUri(getContext().getContentResolver(), uri); 
     return retCursor; 
    } 

    /* 
     Student: Add the ability to insert Locations to the implementation of this function. 
    */ 
    @Override 
    public Uri insert(Uri uri, ContentValues values) { 
     final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 
     final int match = sUriMatcher.match(uri); 
     Uri returnUri; 

     switch (match) { 
      case WEATHER: { 
       normalizeDate(values); 
       long _id = db.insert(WeatherContract.WeatherEntry.TABLE_NAME, null, values); 
       if (_id > 0) 
        returnUri = WeatherContract.WeatherEntry.buildWeatherUri(_id); 
       else 
        throw new android.database.SQLException("Failed to insert row into " + uri); 
       break; 
      } 
      case LOCATION: { 
       long _id = db.insert(WeatherContract.LocationEntry.TABLE_NAME, null, values); 
       if (_id > 0) 
        returnUri = WeatherContract.LocationEntry.buildLocationUri(_id); 
       else 
        throw new android.database.SQLException("Failed to insert row into " + uri); 
       break; 
      } 
      default: 
       throw new UnsupportedOperationException("Unknown uri: " + uri); 
     } 
     getContext().getContentResolver().notifyChange(uri, null); 
     db.close(); 
     return returnUri; 
    } 

    @Override 
    public int delete(Uri uri, String selection, String[] selectionArgs) { 
     // Student: Start by getting a writable database 
     SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 
     // Student: Use the uriMatcher to match the WEATHER and LOCATION URI's we are going to 
     // handle. If it doesn't match these, throw an UnsupportedOperationException. 

     // Student: A null value deletes all rows. In my implementation of this, I only notified 
     // the uri listeners (using the content resolver) if the rowsDeleted != 0 or the selection 
     // is null. 
     // Oh, and you should notify the listeners here. 

     // Student: return the actual rows deleted 
     int match = sUriMatcher.match(uri); 
     int rowsDeleted; 
     switch (match) { 
      case WEATHER: 
       rowsDeleted = db.delete(WeatherContract.WeatherEntry.TABLE_NAME, 
         selection, selectionArgs); 
       break; 
      case LOCATION: 
       rowsDeleted = db.delete(WeatherContract.LocationEntry.TABLE_NAME, 
         selection, selectionArgs); 
       break; 
      default: 
       throw new UnsupportedOperationException("Unknown uri:" + uri); 
     } 
     if (rowsDeleted != 0) { 
      getContext().getContentResolver().notifyChange(uri, null); 
     } 
     return rowsDeleted; 
    } 

    private void normalizeDate(ContentValues values) { 
     // normalize the date value 
     if (values.containsKey(WeatherContract.WeatherEntry.COLUMN_DATE)) { 
      long dateValue = values.getAsLong(WeatherContract.WeatherEntry.COLUMN_DATE); 
      values.put(WeatherContract.WeatherEntry.COLUMN_DATE, WeatherContract.normalizeDate(dateValue)); 
     } 
    } 

    @Override 
    public int update(
      Uri uri, ContentValues values, String selection, String[] selectionArgs) { 
     // Student: This is a lot like the delete function. We return the number of rows impacted 
     // by the update. 
     SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 
     int match = sUriMatcher.match(uri); 
     int rowsUpdated; 
     switch (match) { 
      case WEATHER: 
       normalizeDate(values); 
       rowsUpdated = db.update(WeatherContract.WeatherEntry.TABLE_NAME, values, 
         selection, selectionArgs); 
       break; 
      case LOCATION: 
       rowsUpdated = db.update(WeatherContract.LocationEntry.TABLE_NAME, values, 
         selection, selectionArgs); 
       break; 
      default: 
       throw new UnsupportedOperationException("Unknown uri:" + uri); 
     } 
     if (rowsUpdated != 0) { 
      getContext().getContentResolver().notifyChange(uri, null); 
     } 
     return rowsUpdated; 
    } 

    @Override 
    public int bulkInsert(Uri uri, ContentValues[] values) { 
     final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 
     final int match = sUriMatcher.match(uri); 
     switch (match) { 
      case WEATHER: 
       db.beginTransaction(); 
       int returnCount = 0; 
       try { 
        for (ContentValues value : values) { 
         normalizeDate(value); 
         long _id = db.insert(WeatherContract.WeatherEntry.TABLE_NAME, null, value); 
         if (_id != -1) { 
          returnCount++; 
         } 
        } 
        db.setTransactionSuccessful(); 
       } finally { 
        db.endTransaction(); 
       } 
       getContext().getContentResolver().notifyChange(uri, null); 
       return returnCount; 
      default: 
       return super.bulkInsert(uri, values); 
     } 
    } 

    // You do not need to call this method. This is a method specifically to assist the testing 
    // framework in running smoothly. You can read more at: 
    // http://developer.android.com/reference/android/content/ContentProvider.html#shutdown() 
    @Override 
    @TargetApi(11) 
    public void shutdown() { 
     mOpenHelper.close(); 
     super.shutdown(); 
    } 
} 

И я звоню объект cursorLoader из Fragement как показано ниже. Не могли бы вы помочь мне.

ответ

2

Я решил свой вопрос. Вопрос заключается в buildUriMatcher() метод, изменить эту строку

uriMatcher.addURI(WeatherContract.CONTENT_AUTHORITY, WeatherContract.PATH_WEATHER + "/#", WEATHER_WITH_LOCATION); 

к

uriMatcher.addURI(WeatherContract.CONTENT_AUTHORITY, WeatherContract.PATH_WEATHER + "/*", WEATHER_WITH_LOCATION);