0

我正在嘗試爲用戶編寫自己的內容提供程序。當我試圖驗證用戶是否存在時,當DBHelper嘗試創建數據庫時,它會拋出一個空異常。DBHelper.getWirtableDatabse拋出空異常

以下是內容提供商:

public class MyUserProvider extends ContentProvider { 
    private UserDBHelper db; 

    private static final int USERS = 10; 
    private static final int USER_ID = 20; 

    private static final String AUTHORITY = 
      "net.ifo420.ritc.agenda.userprovider"; 

    private static final String BASE_PATH = "users"; 
    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY 
             + "/" + BASE_PATH); 

    public static final String CONTENT_TYPE = 
      ContentResolver.CURSOR_DIR_BASE_TYPE + "/users"; 

    public static final String CONTENT_ITEM_TYPE = 
      ContentResolver.CURSOR_ITEM_BASE_TYPE + "/user"; 

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

    static { 
     uriMatcher.addURI(AUTHORITY, BASE_PATH, USERS); 
     uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", USER_ID); 
    } 

    public MyUserProvider() { 
    } 

    @Override 
    public boolean onCreate() { 
     db = new UserDBHelper(getContext()); 
     return false; 
    } 

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

     checkColumns(projection); 

     queryBuilder.setTables(UserTable.TABLE); 

     int uriType = uriMatcher.match(uri); 
     switch (uriType) { 
      case USERS: 
       break; 
      case USER_ID: 
       queryBuilder.appendWhere(UserTable.COLUMN_ID + " = " + uri.getLastPathSegment()); 
       break; 
      default: 
       throw new IllegalArgumentException("Uknown uri " + uri); 
     } 
     SQLiteDatabase db1 = db.getReadableDatabase(); 
     Cursor cursor = queryBuilder.query(db1, projection, selection, selectionArgs, 
       null, null, sortOrder); 

     cursor.setNotificationUri(getContext().getContentResolver(), uri); 

     return cursor; 
    } 

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

    @Override 
    public Uri insert(Uri uri, ContentValues values) { 
     int uriType = uriMatcher.match(uri); 
     SQLiteDatabase database = db.getReadableDatabase(); 
     long id = 0; 
     switch (uriType) { 
      case USERS: 
       id = database.insert(UserTable.TABLE, null, values); 
       break; 
      default: 
       throw new IllegalArgumentException("Unknown URI: " + uri); 
     } 
     getContext().getContentResolver().notifyChange(uri, null); 
     return Uri.parse(BASE_PATH + "/" + id); 
    } 

    @Override 
    public int delete(Uri uri, String selection, String[] selectionArgs) { 
     int uriType = uriMatcher.match(uri); 
     SQLiteDatabase sqLiteDatabase = db.getReadableDatabase(); 
     int rowsDeleted = 0; 
     switch (uriType) { 
      case USERS: 
       rowsDeleted = sqLiteDatabase.delete(UserTable.TABLE, selection, 
         selectionArgs); 
       break; 
      case USER_ID: 
       String id = uri.getLastPathSegment(); 
       if(TextUtils.isEmpty(selection)) { 
        rowsDeleted = sqLiteDatabase.delete(UserTable.TABLE, 
          UserTable.COLUMN_ID + " = " + id, null); 
       } else { 
        rowsDeleted = sqLiteDatabase.delete(UserTable.TABLE, 
          UserTable.COLUMN_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 sqLiteDatabase = db.getReadableDatabase(); 
     int rowsUpdated = 0; 
     switch (uriType) { 
      case USERS: 
       rowsUpdated = sqLiteDatabase.update(UserTable.TABLE, 
         values, 
         selection, 
         selectionArgs); 
       break; 
      case USER_ID: 
       String id = uri.getLastPathSegment(); 
       if (TextUtils.isEmpty(selection)) { 
        rowsUpdated = sqLiteDatabase.update(UserTable.TABLE, 
          values, 
          UserTable.COLUMN_ID + "=" + id, 
          null); 
       } else { 
        rowsUpdated = sqLiteDatabase.update(UserTable.TABLE, 
          values, 
          UserTable.COLUMN_ID + "=" + id 
            + " and " 
            + selection, 
          selectionArgs); 
       } 
       break; 
      default: 
       throw new IllegalArgumentException("Unknown URI: " + uri); 
     } 
     getContext().getContentResolver().notifyChange(uri, null); 
     return rowsUpdated; 
    } 

    private void checkColumns(String[] projection) { 
     String[] available = {UserTable.COLUMN_USERNAME, UserTable.COLUMN_PASSWORD, 
          UserTable.COLUMN_ID}; 

     if (projection != null) { 

      HashSet<String> requestedColumns = 
        new HashSet<String>(Arrays.asList(projection)); 
      HashSet<String> availableColumns = 
        new HashSet<String>(Arrays.asList(available)); 

      if (!availableColumns.containsAll(requestedColumns)) { 
       throw new IllegalArgumentException("Unknown columns in projection"); 
      } 
     } 
    } 

這裏是我的DBHelper

public class UserDBHelper extends SQLiteOpenHelper { 
    private static final String DB_NAME = "agenda.db"; 
    private static final int DB_VERSION = 1; 

    public UserDBHelper (Context context) { 
     super(context, DB_NAME, null, DB_VERSION); 
    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 
     UserTable.onCreate(db); 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     UserTable.onUpgrade(db, oldVersion, newVersion); 
    } 

Here is the sample code I am using to verify if the user exists (sorry a bit is in french): 

     public void onClick(View view) { 
     switch (view.getId()) { 
      case R.id.boutonLogin: 
       if (userExists()) { 
        Toast.makeText(this, "L'utilisateur existe.", Toast.LENGTH_SHORT).show(); 
       } else { 
        Toast.makeText(this, "L'utilisateur n'existe pas.", Toast.LENGTH_SHORT).show(); 
       } 
    } 

    private boolean userExists() { 
     String username = nomUtilisateur.getText().toString(); 
     String password = motPasse.getText().toString(); 

     Cursor users = userProvider.query(MyUserProvider.CONTENT_URI, 
       null, 
       " WHERE username = " + nomUtilisateur.getText().toString() + 
       " AND password = " + motPasse.getText().toString(), null, null); 

     if (users.getCount() != 0) { 
      return true; 
     } else { 
      return false; 
     } 

這裏有什麼logcat的給我:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase net.info420.ritc.agendacegep.UserDBHelper.getReadableDatabase()' on a null object reference 
    at net.info420.ritc.agendacegep.MyUserProvider.query(MyUserProvider.java:70) 
    at net.info420.ritc.agendacegep.LoginActivity.utilisateurExiste(LoginActivity.java:69) 
    at net.info420.ritc.agendacegep.LoginActivity.onClick(LoginActivity.java:57) 
    at android.view.View.performClick(View.java:5610) 
    at android.view.View$PerformClick.run(View.java:22260) 
    at android.os.Handler.handleCallback(Handler.java:751) 
    at android.os.Handler.dispatchMessage(Handler.java:95) 
    at android.os.Looper.loop(Looper.java:154) 
    at android.app.ActivityThread.main(ActivityThread.java:6077) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) 
+0

嘗試在'onCreate'返回true' –

+0

它仍然不起作用 –

回答

0

那麼,我有我自己的答案。是的,我無法實例化我的ContentProvider,但不僅如此。我改變了我的代碼,並意識到我只是沒有真正地查詢查詢中的選擇和選擇參數。

所以它去從:

private boolean userExists() { 
    String username = nomUtilisateur.getText().toString(); 
    String password = motPasse.getText().toString(); 

    Cursor users = userProvider.query(MyUserProvider.CONTENT_URI, 
      null, 
      " WHERE username = " + nomUtilisateur.getText().toString() + 
      " AND password = " + motPasse.getText().toString(), null, null); 

    if (users.getCount() != 0) { 
     return true; 
    } else { 
     return false; 
    } 
} 

要:

private boolean userExists() { 
    String username = nomUtilisateur.getText().toString(); 
    String password = motPasse.getText().toString(); 
    String[] selection = {username, password}; 

    Cursor users = getApplicationContext().getContentResolver().query 
      (Agenda.UserEntry.CONTENT_URI, 
      null, 
      "username = ? AND password = ?", selection, null); 

    if (users.getCount() != 0) { 
     return true; 
    } else { 
     return false; 
    } 
} 

因此,光標是零,因爲我沒有做出正確的查詢,這就是爲什麼沒有創建我的數據庫:因爲我在代碼中最後並不需要它。

0

你不能直接實例化和調用一個ContentProvider-你必須通過一個內容解析器。否則,它不會通過提供程序的生命週期,並且不會調用onCreate。

+0

當我嘗試獲取遊標返回的結果數時,它現在會引發異常。它說它是空的,當我試圖去看數據庫時,它不會被創建。 –

+0

好的,所以我一直在運行一些帶有標記的測試,並且我注意到onCreate方法在我的應用程序開始時被調用,而不是當我想使用getWritableDatabase()。即使我調用query()方法也不會被調用,所以正常情況下游標爲空,但數據庫仍未創建。 –

+0

得到了我的答案,問題的一部分就是你提到的。謝謝 ! –