SQLite
 sql >> Base de Dados >  >> RDS >> SQLite

como iniciar o aplicativo com SQLite darabase no emulador do Android Studio?


Como você está tendo dificuldades, o seguinte é um tutorial montado às pressas junto com o código.

  1. Crie o banco de dados e as tabelas em uma ferramenta SQLite, adicionando os dados conforme necessário e depois salve.

  2. Feche o banco de dados e abra-o novamente para verificar se as tabelas e os dados estão conforme o esperado. Caso contrário, faça as alterações e repita 2 até ter certeza de que o banco de dados salvo corresponde.

  3. Obtenha o nome do arquivo do banco de dados salvo e registre-o incluindo a extensão do arquivo.

  4. Se você ainda não criou um projeto para o aplicativo, faça isso e salve o projeto.

  5. Fora do IDE, navegue até a pasta app/src/main de projetos e crie uma pasta chamada assets se ainda não existir.

  6. Copie o arquivo de banco de dados na pasta de ativos.

  7. Abra o projeto no Android Studio.

  8. Crie uma nova classe Java chamada DatabaseHelper com SuperClass como SQLiteOpenHelper (resolverá para android.database.sqlite.SQLiteOpenHelper ) e marque Mostrar substituições de seleção Caixa de diálogo. O clique em OK.

Deve ficar assim:-
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. Adicione uma linha, como uma variável de classe, após public class DatabaseHelper extends SQLiteOpenHelper { é como :-
    public static final String DBNAME = "my_dic.db";
    
    • Observando que é importante que o valor entre aspas seja exatamente o mesmo que o nome do arquivo que foi copiado para a pasta de recursos.

.
  1. Adicione as seguintes variáveis ​​de classe

:-
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;
  • Observando que os valores entre aspas precisam corresponder aos nomes de tabela/coluna de referência que foram definidos no banco de dados para TB_BOOKMARK, COL_BOOKMARK_KEY, COL_BOOKMARK_VALUE e COl_BOOKMARK_DATE.
    • DBVERSION será o número da versão armazenado no campo user_version do banco de dados.
    • SQliteDatabase mDB é uma declaração para uma variável manter o SQLiteDatabase quando ele for aberto. OBSERVE atualmente seu valor é nulo até que seja definido.

.

  1. Altere o construtor para a classe Databasehelper de:-

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

para :-
public DatabaseHelper(Context context) {
    super(context, DBNAME, null, DBVERSION);
}
  • Isso faz com que uma instância da classe Databasehelper possa ser criada com apenas um parâmetro, o context. Os outros valores foram definidos ou no caso da fábrica nenhum será usado, então null significa isso.

.
  1. Adicione um método, ifDBExists para a classe DatabaseHelper para verificar se o banco de dados existe (você só deseja copiá-lo do arquivo de ativos uma vez)

:-
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();
}
  • Além de verificar se o arquivo de banco de dados existe (observe que é considerado um arquivo de banco de dados válido),
  • Além disso, se o banco de dados não existir, pode ser que o diretório do banco de dados não exista, isso o criará se não existir.

.
  1. Adicione outro método copyDBFromAssets para copiar o arquivo de ativos para o banco de dados

:-
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;
}
  • Observe que isso é intencionalmente prolixo, para que qualquer falha possa ser identificada.

A classe completa do DatabaseHelper agora seria:-
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. Altere o construtor para executar o copyDBFromAssets método quando/se o banco de dados não existir (usando o método ifDBExists método)

:-
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();
}
  • Observe se houver um problema ao copiar o banco de dados, o aplicativo será interrompido devido ao RunTimeExcpetion emitido.

.
  1. Última alteração do método onCreate de uma atividade (normalmente seria a atividade principal) para criar uma instância da classe DatabaseHelper. Em seguida, execute o aplicativo (se o aplicativo foi executado, seria melhor excluir os dados do aplicativo antes de fazer isso, caso um banco de dados, talvez vazio, tenha sido criado.)

O código a seguir também inclui uma consulta que informará quais tabelas existem no banco de dados:-
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();
    }
}

Com base na captura de tela e em um arquivo de banco de dados chamado my_dic.db . A saída no log é:-
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
  • Isso indica que:-
    • O banco de dados não existia e o diretório de bancos de dados foi criado (ou seja, data/data/<package name>/databases )
    • 12.288 bytes foram copiados do arquivo de recurso para o arquivo de banco de dados (ou seja, uma cópia bem-sucedida foi feita).
    • O banco de dados resultante tem três entradas na tabela sqlite_master, a tabela BookMark, uma tabela chamada android_metadata (uma tabela criada automaticamente para dispositivos Android pelo SDK que armazena a localidade) e um índice gerado automaticamente para a tabela BookMark.
    • l>

Edição subsequente


Basicamente, o objeto não tem um método chamado getClass, em vez disso você precisa usar o método getClass herdado do Fragment. Então você precisa colocar o fragmento retornado entre parênteses.

Então, em vez de:-
String activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();

Você poderia usar:-
String activeFragment = (getSupportFragmentManager().findFragmentById(R.id.fragment_container)).getClass().getSimpleName();

Alternativamente, você pode usar:-
Fragment activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);

junto com o uso:-
if (activeFragment instanceOf BookmarkFragment) { ...... rest of your code

em vez de usar if (activeFragment.equals(BookmarkFragment.class.getSimpleName())) { ......