SQLite
 sql >> Base de données >  >> RDS >> SQLite

comment lancer l'application avec SQLite darabase sur l'émulateur Android Studio ?

Comme vous rencontrez des difficultés, voici un tutoriel assemblé à la hâte avec du code.

  1. Créez la base de données et les tables dans un outil SQLite, en ajoutant les données nécessaires, puis enregistrez-les.

  2. Fermez la base de données et rouvrez-la pour vérifier que les tables et les données sont comme prévu. Si ce n'est pas le cas, apportez des modifications, puis répétez 2 jusqu'à ce que vous soyez sûr que la base de données enregistrée correspond.

  3. Obtenez le nom de fichier de la base de données enregistrée et enregistrez-le, y compris l'extension de fichier.

  4. Si vous n'avez pas encore créé de projet pour l'application, faites-le et enregistrez le projet.

  5. En dehors de l'IDE, accédez au dossier app/src/main des projets et créez un dossier nommé assets s'il n'existe pas déjà.

  6. Copiez le fichier de base de données dans le dossier assets.

  7. Ouvrez le projet dans Android Studio.

  8. Créez une nouvelle classe Java nommée DatabaseHelper avec SuperClass comme SQLiteOpenHelper (sera résolu en android.database.sqlite.SQLiteOpenHelper ) et cochez la case Afficher les remplacements de sélection Case à cocher de dialogue. Le clic OK.

Cela devrait ressembler à :-

public class DatabaseHelper extends SQLiteOpenHelper {
    public Databasehelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}
  1. Ajoutez une ligne, en tant que variable de classe, après public class DatabaseHelper extends SQLiteOpenHelper { c'est comme :-

    public static final String DBNAME = "my_dic.db";
    
    • Notez qu'il est important que la valeur entre guillemets soit exactement la même que le nom de fichier qui a été copié dans le dossier des éléments.

.

  1. Ajoutez les variables de classe suivantes

:-

public static final int DBVERSION = 1;
public static final String TB_BOOKMARK = "Bookmark";
public static final String COL_BOOKMARK_KEY = "key";
public static final String COL_BOOKMARK_VALUE = "value";
public static final String COL_BOOKMARK_DATE = "date";
SQLiteDatabase mDB;
  • Notez que les valeurs entre guillemets doivent correspondre aux noms de table/colonne respectifs qui ont été définis dans la base de données pour TB_BOOKMARK, COL_BOOKMARK_KEY, COL_BOOKMARK_VALUE et COl_BOOKMARK_DATE.
    • DBVERSION sera le numéro de version stocké dans le champ user_version de la base de données.
    • SQliteDatabase mDB est une déclaration pour qu'une variable contienne la SQLiteDatabase lorsqu'elle a été ouverte. REMARQUE actuellement, sa valeur est nulle jusqu'à ce qu'elle soit définie.

.

  1. Changez le constructeur de la classe Databasehelper de :-

    public DatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {super(context, name, factory, version);}

à :-

public DatabaseHelper(Context context) {
    super(context, DBNAME, null, DBVERSION);
}
  • Cela permet de créer une instance de la classe Databasehelper avec un seul paramètre, le contexte. Les autres valeurs ont été définies ou dans le cas de l'usine, aucune ne sera utilisée, donc null signifie cela.

.

  1. Ajouter une méthode, ifDBExists à la classe DatabaseHelper pour vérifier si la base de données existe (vous ne voulez la copier qu'une seule fois à partir du fichier d'assets)

:-

private boolean ifDBExists(Context context) {
    String dbparent = context.getDatabasePath(DBNAME).getParent();
    File f = context.getDatabasePath(DBNAME);
    if (!f.exists()) {
        Log.d("NODB MKDIRS","Database file not found, making directories."); //<<<< remove before the App goes live.
        File d = new File(dbparent);
        d.mkdirs();
        //return false;
    }
    return f.exists();
}
  • En plus de vérifier que le fichier de base de données existe (notez qu'il est supposé être un fichier de base de données valide),
  • De plus, si la base de données n'existe pas, il se peut que le répertoire de la base de données n'existe pas, cela le créera s'il n'existe pas.

.

  1. Ajouter une autre méthode copyDBFromAssets pour copier le fichier d'actif dans la base de données

:-

private boolean copyDBFromAssets(Context context) {
    Log.d("CPYDBINFO","Starting attemtpt to cop database from the assets file.");
    String DBPATH = context.getDatabasePath(DBNAME).getPath();
    InputStream is;
    OutputStream os;
    int length = 8192;
    long bytes_read = 0;
    long bytes_written = 0;
    byte[] buffer = new byte[length];

    try {

        is = context.getAssets().open(DBNAME);
    } catch (IOException e) {
        Log.e("CPYDB FAIL - NO ASSET","Failed to open the Asset file " + DBNAME);
        e.printStackTrace();
        return false;
    }

    try {
        os = new FileOutputStream(DBPATH);
    } catch (IOException e) {
        Log.e("CPYDB FAIL - OPENDB","Failed to open the Database File at " + DBPATH);
        e.printStackTrace();
        return false;
    }
    Log.d("CPYDBINFO","Initiating copy from asset file" + DBNAME + " to " + DBPATH);
    while (length >= 8192) {
        try {
            length = is.read(buffer,0,length);
        } catch (IOException e) {
            Log.e("CPYDB FAIL - RD ASSET",
                    "Failed while reading in data from the Asset. " +
                            String.valueOf(bytes_read) +
                            " bytes read ssuccessfully."
            );
            e.printStackTrace();
            return false;
        }
        bytes_read = bytes_read + length;
        try {
            os.write(buffer,0,length);
        } catch (IOException e) {
            Log.e("CPYDB FAIL - WR ASSET","failed while writing Database File " +
                    DBPATH +
                    ". " +
            String.valueOf(bytes_written) +
                    " bytes written successfully.");
            e.printStackTrace();
            return false;

        }
        bytes_written = bytes_written + length;
    }
    Log.d("CPYDBINFO",
            "Read " + String.valueOf(bytes_read) + " bytes. " +
                    "Wrote " + String.valueOf(bytes_written) + " bytes."
    );
    try {
        os.flush();
        is.close();
        os.close();
    } catch (IOException e ) {
        Log.e("CPYDB FAIL - FINALISING","Failed Finalising Database Copy. " +
                String.valueOf(bytes_read) +
                " bytes read." +
                String.valueOf(bytes_written) +
                " bytes written."
        );
        e.printStackTrace();
        return false;
    }
    return true;
}
  • Notez que ceci est intentionnellement long, afin que toute défaillance puisse être identifiée avec précision.

La classe DatabaseHelper complète serait maintenant :-

public class DatabaseHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "my_dic.db"; // <<<< VERY IMPORTANT THAT THIS MATCHES DATABASE FILE NAME
    public static final int DBVERSION = 1;
    public static final String TB_BOOKMARK = "Bookmark";
    public static final String COL_BOOKMARK_KEY = "key";
    public static final String COL_BOOKMARK_VALUE = "value";
    public static final String COL_BOOKMARK_DATE = "date";
    SQLiteDatabase mDB;

    public DatabaseHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
        if (!ifDBExists(context)) {
            if (!copyDBFromAssets(context)) {
                throw new RuntimeException("Failed to Copy Database From Assets Folder");
            }
        }
        mDB = this.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    }

    private boolean ifDBExists(Context context) {
        String dbparent = context.getDatabasePath(DBNAME).getParent();
        File f = context.getDatabasePath(DBNAME);
        if (!f.exists()) {
            Log.d("NODB MKDIRS","Database file not found, making directories.");
            File d = new File(dbparent);
            d.mkdirs();
            //return false;
        }
        return f.exists();
    }

    private boolean copyDBFromAssets(Context context) {
        Log.d("CPYDBINFO","Starting attemtpt to cop database from the assets file.");
        String DBPATH = context.getDatabasePath(DBNAME).getPath();
        InputStream is;
        OutputStream os;
        int length = 8192;
        long bytes_read = 0;
        long bytes_written = 0;
        byte[] buffer = new byte[length];

        try {

            is = context.getAssets().open(DBNAME);
        } catch (IOException e) {
            Log.e("CPYDB FAIL - NO ASSET","Failed to open the Asset file " + DBNAME);
            e.printStackTrace();
            return false;
        }

        try {
            os = new FileOutputStream(DBPATH);
        } catch (IOException e) {
            Log.e("CPYDB FAIL - OPENDB","Failed to open the Database File at " + DBPATH);
            e.printStackTrace();
            return false;
        }
        Log.d("CPYDBINFO","Initiating copy from asset file" + DBNAME + " to " + DBPATH);
        while (length >= 8192) {
            try {
                length = is.read(buffer,0,length);
            } catch (IOException e) {
                Log.e("CPYDB FAIL - RD ASSET",
                        "Failed while reading in data from the Asset. " +
                                String.valueOf(bytes_read) +
                                " bytes read ssuccessfully."
                );
                e.printStackTrace();
                return false;
            }
            bytes_read = bytes_read + length;
            try {
                os.write(buffer,0,length);
            } catch (IOException e) {
                Log.e("CPYDB FAIL - WR ASSET","failed while writing Database File " +
                        DBPATH +
                        ". " +
                String.valueOf(bytes_written) +
                        " bytes written successfully.");
                e.printStackTrace();
                return false;

            }
            bytes_written = bytes_written + length;
        }
        Log.d("CPYDBINFO",
                "Read " + String.valueOf(bytes_read) + " bytes. " +
                        "Wrote " + String.valueOf(bytes_written) + " bytes."
        );
        try {
            os.flush();
            is.close();
            os.close();
        } catch (IOException e ) {
            Log.e("CPYDB FAIL - FINALISING","Failed Finalising Database Copy. " +
                    String.valueOf(bytes_read) +
                    " bytes read." +
                    String.valueOf(bytes_written) +
                    " bytes written."
            );
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

.

  1. Modifier le constructeur pour exécuter le copyDBFromAssets méthode quand/si la base de données n'existe pas (en utilisant le ifDBExists méthode)

:-

public DatabaseHelper(Context context) {
    super(context, DBNAME, null, DBVERSION);
    if (!ifDBExists(context)) {
        if (!copyDBFromAssets(context)) {
            throw new RuntimeException("Failed to Copy Database From Assets Folder");
        }
    }
    mDB = this.getWritableDatabase();
}
  • Notez que s'il y a eu un problème lors de la copie de la base de données, l'application sera arrêtée en raison de la RunTimeExcpetion émis.

.

  1. Modifier en dernier lieu la méthode onCreate d'une activité (qui serait normalement l'activité principale) pour créer une instance de la classe DatabaseHelper. Exécutez ensuite l'application (si l'application a été exécutée, il serait préférable de supprimer les données de l'application avant de le faire, juste au cas où une base de données, peut-être vide, aurait été créée.)

Le code suivant inclut également une requête qui vous indiquera quelles tables existent dans la base de données :-

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DatabaseHelper mDBHlpr = new DatabaseHelper(this);
        Cursor csr = mDBHlpr.getWritableDatabase().query(
                "sqlite_master",
                null,null,null,null,null,null
        );
        while (csr.moveToNext()) {
            Log.d("DB TABLES", csr.getString(csr.getColumnIndex("name")));
        }
        csr.close();
    }
}

Basé sur la capture d'écran et un fichier de base de données nommé my_dic.db . La sortie dans le journal est :-

06-16 02:28:45.208 4467-4467/? D/NODB MKDIRS: Database file not found, making directories.
06-16 02:28:45.208 4467-4467/? D/CPYDBINFO: Starting attemtpt to cop database from the assets file.
    Initiating copy from asset filemy_dic.db to /data/data/com.mydictionaryapp.mydictionaryapp/databases/my_dic.db
    Read 12288 bytes. Wrote 12288 bytes.
06-16 02:28:45.224 4467-4467/? D/DB TABLES: Bookmark
    sqlite_autoindex_Bookmark_1
    android_metadata
  • Ceci indique que :-
    • La base de données n'existait pas et le répertoire des bases de données a été créé (c'est-à-dire data/data/<package name>/databases )
    • 12 288 octets ont été copiés du fichier d'actif vers le fichier de base de données (c'est-à-dire qu'une copie a été effectuée avec succès).
    • La base de données résultante comporte trois entrées dans la table sqlite_master, la table BookMark, une table appelée android_metadata (une table créée automatiquement pour les appareils Android par le SDK qui stocke les paramètres régionaux) et un index généré automatiquement pour la table BookMark.

Problème ultérieur

Fondamentalement, l'objet n'a pas de méthode appelée getClass, vous devez plutôt utiliser la méthode getClass héritée du Fragment. Vous devez donc mettre le fragment renvoyé entre parenthèses.

Donc au lieu de :-

String activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();

Vous pouvez utiliser :-

String activeFragment = (getSupportFragmentManager().findFragmentById(R.id.fragment_container)).getClass().getSimpleName();

Alternativement, vous pouvez utiliser :-

Fragment activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);

en plus d'utiliser :-

if (activeFragment instanceOf BookmarkFragment) { ...... rest of your code

au lieu d'utiliser if (activeFragment.equals(BookmarkFragment.class.getSimpleName())) { ......