I have the following Entity:
@Entity(tableName = "game_regions",
primaryKeys = {"_game", "_region_area"},
foreignKeys = {
@ForeignKey(
entity = GameEntity.class,
parentColumns = "_id",
childColumns = "_game"
),
@ForeignKey(
entity = RegionAreaEntity.class,
parentColumns = "_id",
childColumns = "_region_area"
)})
public class GameRegionsEntity {
@NonNull
@ColumnInfo(name = "_game")
private String game;
@NonNull
@ColumnInfo(name = "_region_area")
private String regionArea;
public GameRegionsEntity(@NonNull String game, @NonNull String regionArea) {
this.game = game;
this.regionArea = regionArea;
}
@NonNull
public String getGame() {
return game;
}
public void setGame(@NonNull String game) {
this.game = game;
}
@NonNull
public String getRegionArea() {
return regionArea;
}
public void setRegionArea(@NonNull String regionArea) {
this.regionArea = regionArea;
}
}
Which is represented in this way in SQL:
CREATE TABLE "game_regions" (
"_game" TEXT NOT NULL,
"_region_area" TEXT NOT NULL,
PRIMARY KEY("_game","_region_area"),
FOREIGN KEY("_region_area") REFERENCES "region_areas"("_id"),
UNIQUE("_game","_region_area"),
FOREIGN KEY("_game") REFERENCES "games"("_id")
);
When using a device with Android 6 or higher, everything works without any error, however, when using Android Lollipop 5.1, it throws the following exception when the schema gets validated the first time:
java.lang.IllegalStateException: Pre-packaged database has an invalid schema: game_regions(GameRegionsEntity).
Expected:
TableInfo{name='game_regions', columns={_region_area=Column{name='_region_area', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=2, defaultValue='undefined'}, _game=Column{name='_game', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='undefined'}}, foreignKeys=[ForeignKey{referenceTable='games', onDelete='NO ACTION +', onUpdate='NO ACTION', columnNames=[_game], referenceColumnNames=[_id]}, ForeignKey{referenceTable='region_areas', onDelete='NO ACTION +', onUpdate='NO ACTION', columnNames=[_region_area], referenceColumnNames=[_id]}], indices=[]}
Found:
TableInfo{name='game_regions', columns={_game=Column{name='_game', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='undefined'}, _region_area=Column{name='_region_area', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='undefined'}}, foreignKeys=[ForeignKey{referenceTable='region_areas', onDelete='NO ACTION +', onUpdate='NO ACTION', columnNames=[_region_area], referenceColumnNames=[_id]}, ForeignKey{referenceTable='games', onDelete='NO ACTION +', onUpdate='NO ACTION', columnNames=[_game], referenceColumnNames=[_id]}], indices=null}
If we compare the EXPECTED and the FOUND schema results: we notice that the only thing that changes is that primaryKeyPosition for both primary keys are 1.
I don't know what is causing this error and why this is crashing ONLY in Android Lollipop 5.1 (SDK 22) and its working on every version from 23 until 33.
Any hint?
I would suggest not providing/using your SQL for the asset BUT instead using the SQL that room creates.
However, it is ALWAYS suggested to utilise the SQL that room provides/generates for the creation of the SQLite components for a pre-existing database.
The Room SQL being (from a test):-
@Databasebut suffixed with_ImplcreateAllTablesmethod which includes the actual SQL for the expected tables (noting that the UNIQUE constraint isn't directly supported by Room annotations).INSERT INTO game_regions SELECT * FROM game_regions_renamed(not tested)The test (aka reason for the suggested answer)
Initially a project as created using your code plus the following supportive code (to mimic the code you have not supplied):-
GameEntity class
RegionAreaEntity class
TheDatabase abstract class (i.e. the @Database annotated class)
Main Activity (to test)
Test Part 1
The
createFromAssetmethod call was removed and run on an API 22 device (emulator in Android Studio). It ran fine. Thus eliminating any issue that API 22 is blatantly not compatible with Room.Test Part 2
The App was uninstalled,
createFromAssetwas reinstated. Using Navicat (an SQLite tool) created the database with the two supportive tables (GameEntity and RegionAreaEnntity using the SQL generated by room) using:-Ran the SQL:-
Saved the database (closed the database and the connection and then quit Navicat). Copied the file into the assets folder (renaming the file to the_database.db). Ran the App and:-
Test Part 3 (using Room's SQL)
Uninstalled the App. Used the following in Navicat (Room's SQL):-
Resulting in:-
Closed the database and connection and quit Navicat. Copied the database into the assets directory (renaming the previous used db file). Ran the App and it ran fine. Device Explorer showing (App Inspection only good for API 26+):-
Finally just to show the generated java (and also the assets) :-