Bonjour,
Avant d'expliquer le problème, une mise en contexte s'impose. Pour apprendre les bases d'Android Studio (j'ai déjà celle de Java et MySQL), j'ai décidé de faire une application permettant d'enregistrer des animaux dans une base de donnée, stockant seulement le nom avec un identifiant.
Mon problème est que, dès que je tente d'appuyer sur le bouton ajouter, l'application crash et me donne ceci dans LogCat :
Tout cela étant géré par les classes Java suivantes :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 2019-12-20 13:25:18.471 22763-22763/com.example.animal E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.animal, PID: 22763 java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/user/0/com.example.animal/databases/animal.db at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55) at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1753) at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1698) at com.example.animal.AnimalManager.addAnimal(AnimalManager.java:45) at com.example.animal.MainActivity$3.onClick(MainActivity.java:99) at android.view.View.performClick(View.java:6608) at android.view.View.performClickInternal(View.java:6585) at android.view.View.access$3100(View.java:785) at android.view.View$PerformClick.run(View.java:25921) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:201) at android.app.ActivityThread.main(ActivityThread.java:6806) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128 package com.example.animal; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private Button mSupprimer; private Button mRechercher; private Button mAjouter; private EditText mId; private EditText mNom; private int id; private int nom; private Spinner spinnerListeServeurs; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // données du tableau //gestion éléments id = 0; mId = findViewById(R.id.editId); mNom = findViewById(R.id.editNom); mSupprimer = findViewById(R.id.supprimer); mRechercher = findViewById(R.id.rechercher); mAjouter = findViewById(R.id.ajouter); //Boutons grisés mAjouter.setEnabled(false); mSupprimer.setEnabled(false); //Ouverture de la base de données final AnimalManager m = new AnimalManager(this); // gestionnaire de la table "animal" m.open(); // ouverture de la table en lecture/écriture //spinner //griser le bouton ajouter tant que tout n'est pas rempli mId.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { //Peut permettre de garder le dernier caractère effacé ou l'avant dernier caractère noté } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { mAjouter.setEnabled(s.length() !=0 && nom != 0); mSupprimer.setEnabled(s.length() !=0 && nom != 0); id = s.length(); } @Override public void afterTextChanged(Editable s) { } }); mNom.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { //Peut permettre de garder le dernier caractère effacé ou l'avant dernier caractère noté } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { mAjouter.setEnabled(s.length() != 0 && id != 0); mSupprimer.setEnabled(s.length() != 0 && id != 0); nom=s.length(); } @Override public void afterTextChanged(Editable s) { } }); mAjouter.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Ajout dans bdd String ajoutNom = mNom.getText().toString(); String ajoutIdS = mId.getText().toString(); int ajoutId = Integer.valueOf(ajoutIdS); //problème add, crash m.addAnimal(new Animal(ajoutId, ajoutNom)); } }); mSupprimer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Supprimer } }); mRechercher.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //rechercher } }); m.close(); } public void onClick(View v) { String idR = mId.getText().toString(); String nomR = mNom.getText().toString(); } }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94 //Class AnimalManager package com.example.animal; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import com.example.animal.Animal; import com.example.animal.MySQLite; public class AnimalManager { private static final String TABLE_NAME = "animal"; public static final String KEY_ID_ANIMAL="id_animal"; public static final String KEY_NOM_ANIMAL="nom_animal"; public static final String CREATE_TABLE_ANIMAL = "CREATE TABLE "+TABLE_NAME+ " (" + " "+KEY_ID_ANIMAL+" INTEGER PRIMARY KEY AUTOINCREMENT," + " "+KEY_NOM_ANIMAL+" TEXT" + ");"; private MySQLite maBaseSQLite; // notre gestionnaire du fichier SQLite private SQLiteDatabase db; // Constructeur public AnimalManager(Context context) { maBaseSQLite = MySQLite.getInstance(context); } public void open() { //on ouvre la table en lecture/écriture db = maBaseSQLite.getWritableDatabase(); } public void close() { //on ferme l'accès à la BDD db.close(); } public void addAnimal(Animal animal) { // Ajout d'un enregistrement dans la table db.execSQL("INSERT INTO " + TABLE_NAME + "VALUES ("+ animal.getNom_animal() + ");"); } public int modAnimal(Animal animal) { // modification d'un enregistrement // valeur de retour : (int) nombre de lignes affectées par la requête ContentValues values = new ContentValues(); values.put(KEY_NOM_ANIMAL, animal.getNom_animal()); String where = KEY_ID_ANIMAL+" = ?"; //Remplace le ? String[] whereArgs = {animal.getId_animal()+""}; return db.update(TABLE_NAME, values, where, whereArgs); } public int supAnimal(Animal animal) { // suppression d'un enregistrement // valeur de retour : (int) nombre de lignes affectées par la clause WHERE, 0 sinon String where = KEY_ID_ANIMAL+" = ?"; String[] whereArgs = {animal.getId_animal()+""}; return db.delete(TABLE_NAME, where, whereArgs); } public Animal getAnimal(int id) { // Retourne l'animal dont l'id est passé en paramètre Animal a=new Animal(0,""); Cursor c = db.rawQuery("SELECT * FROM "+TABLE_NAME+" WHERE "+KEY_ID_ANIMAL+"="+id, null); if (c.moveToFirst()) { a.setId_animal(c.getInt(c.getColumnIndex(KEY_ID_ANIMAL))); a.setNom_animal(c.getString(c.getColumnIndex(KEY_NOM_ANIMAL))); c.close(); } return a; } public Cursor getAnimaux() { // sélection de tous les enregistrements de la table return db.rawQuery("SELECT * FROM "+TABLE_NAME, null); } } // class AnimalManager
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package com.example.animal; public class Animal { private int id_animal; private String nom_animal; // Constructeur public Animal(int id,String nom) { this.id_animal=id; this.nom_animal=nom; } public int getId_animal() { return id_animal; } public void setId_animal(int id) { this.id_animal = id; } public String getNom_animal() { return nom_animal; } public void setNom_animal(String nom) { this.nom_animal = nom; } } // class Animalet le code XML au cas où :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package com.example.animal; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class MySQLite extends SQLiteOpenHelper { private static final String DATABASE_NAME = "animal.db"; private static final int DATABASE_VERSION = 1; private static MySQLite sInstance; public static synchronized MySQLite getInstance(Context context) { if (sInstance == null) { sInstance = new MySQLite(context); } return sInstance; } private MySQLite(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { // Création de la base de données // on exécute ici les requêtes de création des tables sqLiteDatabase.execSQL(AnimalManager.CREATE_TABLE_ANIMAL); // création table "animal" } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i2) { // Mise à jour de la base de données // méthode appelée sur incrémentation de DATABASE_VERSION // on peut faire ce qu'on veut ici, comme recréer la base : sqLiteDatabase.execSQL("DROP TABLE " + AnimalManager.CREATE_TABLE_ANIMAL + ";"); onCreate(sqLiteDatabase); } } // class MySQLite
Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center"> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:columnCount="1" android:rowCount="2" android:layout_centerHorizontal="true" android:id="@+id/tableau" > <TableRow> <EditText android:id="@+id/editId" android:layout_width="350dp" android:layout_height="match_parent" android:hint="ID" android:inputType="number" /> </TableRow> <TableRow> <EditText android:id="@+id/editNom" android:layout_width="match_parent" android:layout_height="match_parent" android:hint="nom" android:inputType="textPersonName" /> </TableRow > </TableLayout> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="350dp" android:layout_height="wrap_content" android:columnCount="3" android:rowCount="1" android:id="@+id/tableauB" android:padding="10dp" android:layout_centerHorizontal="true" android:layout_below="@id/tableau" > <!--mettre les entrées au dessus des boutons --> <TableRow> <Button android:id="@+id/supprimer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Supprimer" android:layout_toRightOf="@id/ajouter" /> <Button android:id="@+id/ajouter" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ajouter" android:layout_toRightOf="@id/rechercher" /> <Button android:id="@+id/rechercher" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="rechercher" /> </TableRow> </TableLayout> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" android:layout_below="@id/idListe" /> <Spinner android:id="@+id/idListe" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/tableauB"/> </RelativeLayout>
ps : je sais pas du tout comment on fait pour utiliser correctement les balises code donc si vous pouviez me le dire en passant, ce serait pas de refus
Partager