I make an application, the main content of which is in SQLite database. A quiz in which you are invited to guess the animal.

Began to study Room. Everything works, information is saved and retrieved from db in runtime (see through logs and Toast). But when I open the db itself (physically) in the browser (DB Browser), I see emptiness there. No tables, nothing. And there must be my notes.

What I want to do : open the newly installed application, add several entries to db, close the application, download the created db from the device to the PC and open it in the browser to see its structure.

Step by step what has been done and where the plug is:

Rutanul emulator.

Defined the path of the created Base database through:

Timber.d(getDatabasePath(AnimalDatabase.DATABASE_NAME).getPath());

Received:

/data/user/0/com.example.animalslibrary/databases/AnimalDB

Removed the application. With my hands, I com.example.animalslibrary entire com.example.animalslibrary package.

Install the application.

The application is open, no records have been added (the record is added by hand on the button). Nothing was created on the above path:

enter image description here

Add a record by button. Files are created with my base (?) And something else incomprehensible:

enter image description here

I continue to add entries with the button. My AnimalBD database AnimalBD not change the size, but the third file AnimalBD at a staggering speed (screen after adding five entries):

enter image description here

I close the application. I AnimalBD , I open - emptiness, a clean sheet. There are not even tables.

I run the application again. I try to get a record from the database - gets it.

What am I doing wrong at all? Is it possible to get the base? And if not, what should I do if I want the user to have a full database at the time of the first launch of the application? I won't add a lot of lines to the code. In the comments, I was advised to replace the base created by Room on my own when I first started it - but for this I need to understand how the Room creates what it needs to create an analogue.

Code. I'm not sure that he is needed here at all, because everything works. But let it be. Do not throw stones for overloaded architecture, learn MVC.

Activity

  HomeModel homeModel = new HomeModel(Room.databaseBuilder(this, AnimalDatabase.class, AnimalDatabase.DATABASE_NAME) .allowMainThreadQueries() .build()); HomePresenter presenter = new HomePresenter(homeModel); presenter.attachView(this); findViewById(R.id.add_animal_button).setOnClickListener(v -> presenter.buttonClicked()); findViewById(R.id.show_animal_button).setOnClickListener(v -> presenter.button1Clicked()); Timber.d(getDatabasePath(AnimalDatabase.DATABASE_NAME).getPath()); 

Homepresenter

 public class HomePresenter { private HomeActivity view; private HomeModel model; public HomePresenter(HomeModel homeModel) { this.model = homeModel; } public void attachView(HomeActivity activity) { this.view = activity; } public void detachView() { this.view = null; } public void viewIsReady() { } public void buttonClicked(){ model.addAnimal(); Toast.makeText(view,"ADDED",Toast.LENGTH_LONG).show(); } public void button1Clicked(){ Animal addedAnimal = model.getAnimalById(1); Toast.makeText(view,addedAnimal.getName(),Toast.LENGTH_LONG).show(); } 

Homemodel

 public class HomeModel { private AnimalDatabase animalDB; public HomeModel(AnimalDatabase animalDB) { this.animalDB = animalDB; } public void addAnimal() { Animal animal = new Animal(); animal.setName("TIGER"); animalDB.daoAccess().insertAnimal(animal); } public Animal getAnimalById(int id) { return animalDB.daoAccess().getAnimalById(id); } public void initDB(){} } 

DAO

 @Dao public interface DAO { @Insert void insertAnimal(Animal animal); @Insert void insertAnimals(List<Animal> animalList); @Query("SELECT*FROM animals WHERE animal_id =:animalId") Animal getAnimalById(int animalId); @Update void updateAnimal(Animal animal); @Delete void deleteAnimal(Animal animal); 

}

AnimalDatabase

 @Database(entities = {Animal.class, AnimalPack.class}, version = 1) @TypeConverters(Converters.class) public abstract class AnimalDatabase extends RoomDatabase { public abstract DAO daoAccess(); public static String DATABASE_NAME = "AnimalDB"; public static String DATABASE_NAME_WITH_PREFICS = "AnimalDB.db"; public static String TABLE_ANIMALS_NAME = "animals"; public static String TABLE_PACKS_NAME = "packs"; } 

Animal

 @Entity(tableName = "animals") public class Animal implements Serializable { @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "animal_id") private int animalId; @ColumnInfo(name = "animal_type") private int type; @ColumnInfo(name = "animal_name") private String name; @ColumnInfo(name = "animal_hints") private String hints; @ColumnInfo(name = "animal_opened_hints") private int hintsOpened; @ColumnInfo(name = "animal_hints_total") private int hintsTotal; @ColumnInfo(name = "animal_pack_id") private int packId; @ColumnInfo(name = "animal_answer_image") private String answerImagePath; public Animal() { } //Тьма геттеров и сеттеров //+ пустой конструктор //+ конструктор, содержащий все поля } 
  • database = Room.databaseBuilder (this, AppDatabase.class, "database.db") .allowMainThreadQueries () .openHelperFactory (new AssetSQLiteOpenHelperFactory ()) .build (); - Romanovich
  • Woesss, added an edit for you in response. Romanych, my application does not know anything about the AssetSQLiteOpenHelperFactory () class, and it does not google. What is it? The rest of the code is no different from what I already have. - KirstenLy
  • Looked at editing - If it is short, then your database is not copied and it is created clean. I tried somehow to remake my scribbles for the same needs, but in the end I left it as it was on SQLiteAsset Helper. Room, as I understand it, until it reached. When you first start, you need to copy the database from the resources and then not create a new one but read the ready one. - Romanovich
  • Romanych, googling deeper, I also came to a similar solution, just shove the database with content into assets and copy it to the "source" directory when you first start. Only I first need to make or get an "image" of my base, at least an empty "blank" that I could put in the assets . That's the trick, and for that I need to understand what the Room generates for me to do this. Of course, I’ll start by trying on random, with simple classes I can manage the mb and guess what the table looks like, but with sheets it’s most likely not, except if you're lucky ... - KirstenLy

2 answers 2

Additional files are SQLite log files. They are needed to ensure speed in multi-threaded access and data integrity in case of failures. Data from the journal is transferred to the database when a certain number of transactions accumulate and when the connection with the database is closed (which you apparently are not doing).

Database viewers should know these files and what to do with them, so you can copy all three into one folder and open the database file to see your records.

    Is it possible to get the base?

    The database can be pulled from the device and without any root, for this you need to open a file manager in the studio and connect a phone with an apk installed on it. You can emulator, but I work with the device. Bottom right Device File Explorer . The database itself will be located in the data/data/имя пакета/databases/имя базы данных So you can get it.

    Specifically, in your case, I see no reason to use the Room, although there is still a sense, but: You can create a ready-made database, I use the DB BROWSER for SQLITE

    Well, when you start the application, just copy it from the ASSETS folder and then check for the presence and read the ROOM itself. Here they gave a good answer how to copy and read the base with pens. Well, then having a base just to work with it.