2009-11-16 17 views
10

Ho avuto fortuna con SQLite con SQL diretto e diretto in Android, ma questa è la prima volta che eseguo il wrapping di un DB in un ContentProvider. Continuo a ricevere un'eccezione di puntatore nullo quando si chiama getWritableDatabase() o getReadableDatabase(). È solo uno stupido errore che ho fatto con le inizializzazioni nel mio codice o c'è un problema più grande?SQLiteOpenHelper.getWriteableDatabase() eccezione puntatore null su Android

public class DatabaseProvider extends ContentProvider { 
    ... 
    private DatabaseHelper     databaseHelper; 
    private SQLiteDatabase     db; 
    ... 
    @Override 
    public boolean onCreate() { 
    databaseHelper = new DatabaseProvider.DatabaseHelper(getContext()); 
    return (databaseHelper == null) ? false : true; 
    } 
    ... 
    @Override 
    public Uri insert(Uri uri, ContentValues values) { 
    db = databaseHelper.getWritableDatabase(); // NULL POINTER EXCEPTION HERE 
    ... 
    } 
    private static class DatabaseHelper extends SQLiteOpenHelper { 
    public static final String DATABASE_NAME = "cogsurv.db"; 
    public static final int DATABASE_VERSION = 1; 

    public static final String[] TABLES = { 
     "people", 
     "travel_logs", 
     "travel_fixes", 
     "landmarks", 
     "landmark_visits", 
     "direction_distance_estimates" 
    }; 

    // people._id does not AUTOINCREMENT, because it's set based on server's people.id 
    public static final String[] CREATE_TABLE_SQL = { 
     "CREATE TABLE people (_id INTEGER PRIMARY KEY," + 
       "server_id INTEGER," + 
       "name VARCHAR(255)," + 
       "email_address VARCHAR(255))", 
     "CREATE TABLE travel_logs (_id INTEGER PRIMARY KEY AUTOINCREMENT," + 
           "server_id INTEGER," + 
           "person_local_id INTEGER," + 
           "person_server_id INTEGER," + 
           "start DATE," + 
           "stop DATE," + 
           "type VARCHAR(15)," + 
           "uploaded VARCHAR(1))", 
     "CREATE TABLE travel_fixes (_id INTEGER PRIMARY KEY AUTOINCREMENT," + 
           "datetime DATE, " + 
           "latitude DOUBLE, " + 
           "longitude DOUBLE, " + 
           "altitude DOUBLE," + 
           "speed DOUBLE," + 
           "accuracy DOUBLE," + 
           "travel_mode VARCHAR(50), " + 
           "person_local_id INTEGER," + 
           "person_server_id INTEGER," + 
           "travel_log_local_id INTEGER," + 
           "travel_log_server_id INTEGER," + 
           "uploaded VARCHAR(1))", 
     "CREATE TABLE landmarks (_id INTEGER PRIMARY KEY AUTOINCREMENT," + 
           "server_id INTEGER," + 
           "name VARCHAR(150)," + 
           "latitude DOUBLE," + 
           "longitude DOUBLE," + 
           "person_local_id INTEGER," + 
           "person_server_id INTEGER," + 
           "uploaded VARCHAR(1))", 
     "CREATE TABLE landmark_visits (_id INTEGER PRIMARY KEY AUTOINCREMENT," + 
            "server_id INTEGER," + 
            "person_local_id INTEGER," + 
            "person_server_id INTEGER," + 
            "landmark_local_id INTEGER," + 
            "landmark_server_id INTEGER," + 
            "travel_log_local_id INTEGER," + 
            "travel_log_server_id INTEGER," + 
            "datetime DATE," + 
            "number_of_questions_asked INTEGER," + 
            "uploaded VARCHAR(1))", 
     "CREATE TABLE direction_distance_estimates (_id INTEGER PRIMARY KEY AUTOINCREMENT," + 
               "server_id INTEGER," + 
               "person_local_id INTEGER," + 
               "person_server_id INTEGER," + 
               "travel_log_local_id INTEGER," + 
               "travel_log_server_id INTEGER," + 
               "landmark_visit_local_id INTEGER," + 
               "landmark_visit_server_id INTEGER," + 
               "start_landmark_local_id INTEGER," + 
               "start_landmark_server_id INTEGER," + 
               "target_landmark_local_id INTEGER," + 
               "target_landmark_server_id INTEGER," + 
               "datetime DATE," + 
               "direction_estimate DOUBLE," + 
               "distance_estimate DOUBLE," + 
               "uploaded VARCHAR(1))" 
    }; 

    public DatabaseHelper(Context context) { 
     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
     Log.v(Constants.TAG, "DatabaseHelper()"); 
    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 
     Log.v(Constants.TAG, "DatabaseHelper.onCreate() starting"); 

     // create the tables 
     int length = CREATE_TABLE_SQL.length; 
     for (int i = 0; i < length; i++) { 
     db.execSQL(CREATE_TABLE_SQL[i]); 
     } 
     Log.v(Constants.TAG, "DatabaseHelper.onCreate() finished"); 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     for (String tableName : TABLES) { 
     db.execSQL("DROP TABLE IF EXISTS" + tableName); 
     } 
     onCreate(db); 
    } 
    } 
} 

Come sempre, grazie per l'assistenza!

-

Non sono sicuro se questo dettaglio aiuta, ma ecco LogCat che mostra l'eccezione:

collegamento rimosso ImageShack morti

+1

Hai mai trovato una soluzione a questo? –

risposta

6

Piuttosto che:

databaseHelper = new DatabaseProvider.DatabaseHelper(getContext()); 

prova:

databaseHelper = new DatabaseProvider.DatabaseHelper(this); 

e vedere se questo aiuta.

In caso contrario, è possibile pubblicare la traccia dello stack NullPointerException?

+0

Grazie per la risposta! Sfortunatamente questo non aiuta. "questo" è un ContentProvider piuttosto che un Contesto. Ho provato a pubblicare uno screenshot dell'errore. È ampio, quindi ti consigliamo di aprirlo in una nuova scheda. Non sono sicuro che quel dettaglio aiuti davvero, però ... –

+0

Oops, hai ragione - Continuo a pensare che ContentProvider erediti dal Contesto, e non lo fa. Per quanto riguarda la traccia dello stack, non sta caricando per me. È possibile utilizzare DDMS (o la prospettiva DDMS in Eclipse) per salvare una porzione di una traccia di stack come file di testo. Basta evidenziare le linee di interesse e fare clic sull'icona Salva nella barra degli strumenti della scheda LogCat. – CommonsWare

+0

Grazie per l'offerta di ulteriore aiuto! Proprio l'altro giorno, mi sono seduto con un professionista Android, ed è stato in grado di risolvere il mio problema: fare getWritableDatabase() come parte di onCreate() piuttosto che in insert() –

0

Assicurarsi che quando si crea l'AVD, specificare una certa quantità di spazio sulla scheda SD. Ho avuto lo stesso problema e questo lo ha risolto. Se questo non aiuta, puoi anche provare ad avviare l'emulatore con l'opzione -wipe-data.

+0

Grazie per il suggerimento, ma cerco sempre su un dispositivo reale, quindi non penso che questo sia il problema. –

+0

E l'opzione -wipe-data? Forse questo potrebbe aiutare a farlo funzionare. – jaxvy

2

Questo errore è quasi certamente di avere un contesto non valido passato in:

super(context, DATABASE_NAME, null, DATABASE_VERSION); 
2

Ho appena avuto questo problema con la NullPointerException SQLite in un non-attività e il problema era che aveva un contesto non valido.

La mia correzione stava passando il contesto su onCreate invece che sul costruttore. Prova a cercare un contesto da un altro posto per fare getApplicationContext().

1

uso prova getWritableDatabase() in un certo tempo dopo l'iniziale L'aiutante hai NullPointerException causa il database non è stato preparato completamente e non farlo nel thread UI, o può causare ANR

0

ho ottenuto questo stesso errore NullPointerException quando getReadableDatabase() viene chiamato all'interno di query() perché stavo interrogando impropriamente il mio fornitore di contenuti. Non riesco a vedere nulla di sbagliato nel modo in cui stai costruendo il tuo database. getContext() dovrebbe fornire l'oggetto contesto appropriato. Tuttavia, vorrei prestare attenzione a come stai facendo le tue domande al fornitore di contenuti. Dovresti assicurarti di avere un riferimento valido al tuo risolutore di contenuto (ad es. Chiamando getContentResolver(). Query (..)) e lo sta usando per eseguire la query.

1

Ho appena avuto questo problema e ho capito che era un po 'di falsa pista.

Il mio problema derivava dal modo in cui stavo usando ContentProvider.

In realtà stavo accedendo al ContentProvider direttamente anziché tramite ContentResolver. È essenzialmente un modo semplice per inciampare se il tuo nuovo ad usare ContentProviders.

Spero che questo aiuti :)

Problemi correlati