2009-11-16 5 views
10

J'ai eu la chance fine en utilisant SQLite avec SQL droite, directement dans Android, mais c'est la première fois que je enroulant un DB dans un ContentProvider. Je reçois toujours une exception de pointeur nul lorsque j'appelle getWritableDatabase() ou getReadableDatabase(). Est-ce juste une erreur stupide que j'ai faite avec les initialisations dans mon code ou y at-il un plus gros problème?SQLiteOpenHelper.getWriteableDatabase() NullPointerException sur 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); 
    } 
    } 
} 

Comme toujours, merci pour l'aide!

-

Je ne sais pas si ce détail aide, mais voici LogCat montrant l'exception:

lien ImageShack mort enlevé

+1

Avez-vous déjà trouvé une solution? –

Répondre

6

Plutôt que:

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

essayer:

databaseHelper = new DatabaseProvider.DatabaseHelper(this); 

et voir si cela aide.

Si elle n'a pas, pourriez-vous poster la trace de la pile NullPointerException?

+0

Merci pour la réponse! Malheureusement, cela n'aide pas. "this" est un ContentProvider plutôt qu'un Context. J'ai essayé d'afficher une capture d'écran de l'erreur. Il est large, donc vous aurez envie de l'ouvrir dans un nouvel onglet. Je ne sais pas si ce détail est vraiment utile, bien que ... –

+0

Oups, vous avez raison - je continue à penser que ContentProvider hérite de Context, et ce n'est pas le cas. En ce qui concerne la trace de la pile, elle ne se charge pas pour moi. Vous pouvez utiliser DDMS (ou la perspective DDMS dans Eclipse) pour enregistrer une partie d'une trace de pile sous la forme d'un fichier texte. Sélectionnez simplement les lignes d'intérêt et cliquez sur l'icône Enregistrer dans la barre d'outils de l'onglet LogCat. – CommonsWare

+0

Merci pour l'offre de plus d'aide! Juste l'autre jour, je me suis assis avec un pro Android, et il a été en mesure de résoudre mon problème: faire le getWritableDatabase() dans le onCreate() plutôt que dans l'insert() –

0

Assurez-vous que lorsque vous créez l'AVD, spécifiez une certaine quantité d'espace de carte SD. J'ai eu le même problème et cela l'a résolu. Si cela ne vous aide pas, vous pouvez également essayer de démarrer l'émulateur avec l'option -wipe-data.

+0

Merci pour la suggestion, mais je vérifie toujours sur un appareil réel, donc je ne pense pas que ce soit le problème. –

+0

Qu'en est-il de l'option -wipe-data? Peut-être que cela pourrait aider à le faire fonctionner. – jaxvy

2

Cette erreur est presque certainement d'avoir un contexte non valide passé dans:

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

Je viens d'avoir ce problème avec le NullPointerException SQLite dans un non-activité et le problème était qu'il y avait un contexte non valide.

Mon solution passait le contexte à onCreate au lieu du constructeur. Essayez de trouver un contexte à partir d'un autre endroit à faire getApplicationContext().

1

utilisation try getWritableDatabase() dans un certain temps après parapher l'aide vous avez NullPointerException cause de la base de données n'a pas été préparée complètement et ne pas faire dans le thread d'interface, ou il peut provoquer des ANR

0

Je suis arrivé ce même erreur NullPointerException lorsque getReadableDatabase() est appelée dans query() parce que j'interrogeais mal mon fournisseur de contenu. Je ne vois rien de mal dans la façon dont vous construisez votre base de données. getContext() devrait vous donner l'objet de contexte approprié. Cependant, je ferais attention à la façon dont vous faites vos requêtes au fournisseur de contenu. Vous devez vous assurer que vous avez une référence valide à votre résolveur de contenu (c'est-à-dire en appelant getContentResolver(). Query (..)) et l'utilise pour exécuter la requête.

1

J'ai juste eu ce problème et j'ai réalisé que c'était un peu un hareng rouge.

Ma question découlait de la façon dont je l'utilise ContentProvider.

J'accédait en fait le ContentProvider directement plutôt que par l'ContentResolver. C'est essentiellement un moyen facile de trébucher si vous êtes nouveau à l'aide de ContentProviders.

Espérons que ça aide :)

Questions connexes