Can't use suspend function in RoomDB Dao - android

What is going on with RoomDB and Kotlin coroutines? I am trying, again and again, to use suspend function in Room Dao but every time it shows an error. I even follow the android codelabs example. But it shows an error again. the app doesn't even build if I write suspend in Dao. But if I remove suspend keyword it builds successfully.
It shows the error below:
error: Type of the parameter must be a class annotated with #Entity or a collection/array of it.
kotlin.coroutines.Continuation<? super kotlin.Unit> continuation);
My Entity:
import androidx.room.Entity
import androidx.room.PrimaryKey
#Entity(tableName = "vocabulary")
class Vocabulary(
#PrimaryKey(autoGenerate = true)
val vocabularyId: Long,
val word: String,
val meaning: String,
val definition: String,
val example: String,
val partsOfSpeech: String,
val synonyms: String,
val antonyms: String,
val phonetics: String,
val folderId: Long,
val isLearned: Int
)
My Dao:
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
#Dao
interface VocabuilderDao {
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertVocab(vocabulary: Vocabulary)
}
My Database class:
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
#Database(entities = [Vocabulary::class], version = 1, exportSchema = false)
public abstract class VocabuilderRoomDb : RoomDatabase(){
abstract fun vocabuilderDao(): VocabuilderDao
companion object{
#Volatile
private var INSTANCE: VocabuilderRoomDb? = null
fun getRoomDatabase(context: Context): VocabuilderRoomDb{
return INSTANCE ?: synchronized(this){
val instance = Room.databaseBuilder(
context.applicationContext,
VocabuilderRoomDb::class.java,
"vocabuilder_roomdb"
).build()
INSTANCE = instance
instance
}
}
}
}
My build.gradle (project level):
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.6.0'
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
ext {
activityVersion = '1.2.3'
appCompatVersion = '1.3.0'
constraintLayoutVersion = '2.0.4'
coreTestingVersion = '2.1.0'
coroutines = '1.5.0'
lifecycleVersion = '2.3.1'
materialVersion = '1.3.0'
roomVersion = '2.3.0'
// testing
junitVersion = '4.13.2'
espressoVersion = '3.1.0'
androidxJunitVersion = '1.1.2'
}
task clean(type: Delete) {
delete rootProject.buildDir
}
My build.gradle(module):
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.domesoft.vocabuilder"
minSdk 21
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
packagingOptions {
exclude 'META-INF/atomicfu.kotlin_module'
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation "androidx.appcompat:appcompat:$rootProject.appCompatVersion"
implementation "androidx.activity:activity-ktx:$rootProject.activityVersion"
// Dependencies for working with Architecture components
// You'll probably have to update the version numbers in build.gradle (Project)
// Room components
implementation "androidx.room:room-ktx:$rootProject.roomVersion"
kapt "androidx.room:room-compiler:$rootProject.roomVersion"
androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"
// Lifecycle components
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$rootProject.lifecycleVersion"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$rootProject.lifecycleVersion"
implementation "androidx.lifecycle:lifecycle-common-java8:$rootProject.lifecycleVersion"
// Kotlin components
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$rootProject.coroutines"
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$rootProject.coroutines"
// UI
implementation "androidx.constraintlayout:constraintlayout:$rootProject.constraintLayoutVersion"
implementation "com.google.android.material:material:$rootProject.materialVersion"
// Testing
testImplementation "junit:junit:$rootProject.junitVersion"
androidTestImplementation "androidx.arch.core:core-testing:$rootProject.coreTestingVersion"
androidTestImplementation ("androidx.test.espresso:espresso-core:$rootProject.espressoVersion", {
exclude group: 'com.android.support', module: 'support-annotations'
})
androidTestImplementation "androidx.test.ext:junit:$rootProject.androidxJunitVersion"
}

If you using kotlin version (1.7.0) shoud work with room latest alpha version (2.5.0-alpha02)
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.0"
implementation "androidx.room:room-runtime:2.5.0-alpha02"
implementation "androidx.room:room-ktx:2.5.0-alpha02"
kapt "androidx.room:room-compiler:2.5.0-alpha02"
If you want using room in stable version (2.4.2) should work with kotlin version (1.6.20)
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.20"
implementation "androidx.room:room-runtime:2.4.2"
implementation "androidx.room:room-ktx:2.4.2"
kapt "androidx.room:room-compiler:2.4.2"
I have tried both and they work. this is the reference: issue tracker

Update the Room version to 2.4.0-rc01.
In my case it solved the problem, and it works with Kotlin 1.6.0.

For me, kotlin-gradle-plugin 1.6.0 didn't work:
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0"
but 1.5.31 worked:
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31'
Kotlin 1.6.0 with Room 2.4.0-rc01 worked too.
Thanks Stefano.

Related

'dagger.hilt.android.internal.lifecycle.DefaultActivityViewModelFactory' could not be resolved

I have spent the hole week trying to add hilt dependency injection to my sample note application, android studio have been throwing on me error after an error.It got me mad, any way, in AppModule i have been trying to inject my room database to app repository and then my app repo to my use cases class and at the end injecting use cases class to my sharedViewModel
so this is my AppModule object:
#Module
#InstallIn(SingletonComponent::class)
object AppModule {
#Provides
#Singleton
fun provideNoteDatabase(app: Application): NoteDatabase {
return Room.databaseBuilder(
app,
NoteDatabase::class.java,
NoteDatabase.DATABASE_NAME
).build()
}
#Provides
#Singleton
fun provideNoteRepository(db: NoteDatabase): NotesRepo {
return RepoImplementation(db.noteDao())
}
#Provides
#Singleton
fun provideNoteUseCase(repo: NotesRepo): NoteUseCase {
return NoteUseCase(
getNotesUseCase = GetNotesUseCase(repo),
deleteNoteUseCase = DeleteNoteUseCase(repo),
updateNoteUseCase = UpdateNoteUseCase(repo),
insertNoteUseCase = InsertNoteUseCase(repo)
)
}
}
and this my Application class:
#HiltAndroidApp
class Application : Application()
my edit fragment:
#AndroidEntryPoint
class EditFragment : Fragment() {
private var _binding: FragmentEditBinding? = null
private val binding get() = _binding!!
private val viewModel: SharedViewModel by activityViewModels()
//...
}
my other fragment:
#AndroidEntryPoint
class MainFragment : Fragment() {
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
private val viewModel: SharedViewModel by activityViewModels()
//...
}
by the way also my MainActivity is annotated with #AndroidEntryPoint
my famous viewModel :
#HiltViewModel
class SharedViewModel #Inject constructor(private val noteUseCase: NoteUseCase) :
ViewModel() {...}
this is project level build.gradle:
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
def nav_version = "2.5.2"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.44'
}
}
plugins {
id 'com.android.application' version '7.3.0' apply false
id 'com.android.library' version '7.3.0' apply false
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}
and module level build.gradle:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-android'
id 'kotlin-kapt'
id "androidx.navigation.safeargs"
id 'com.google.dagger.hilt.android'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.stayin"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
dataBinding true
viewBinding true
}
namespace 'com.example.stayin'
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
def lifecycle_version = "2.4.1"
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
// coroutines for getting off the UI thread
def coroutines = "1.6.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
//shared preferences dependency
implementation 'androidx.preference:preference-ktx:1.2.0'
// Room dependency
def room_version = "2.4.3"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
// Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
//navigation component dependency
implementation "androidx.navigation:navigation-fragment-ktx:2.5.2"
implementation "androidx.navigation:navigation-ui-ktx:2.5.2"
//Dagger - Hilt
implementation 'com.google.dagger:hilt-android:2.44'
kapt 'com.google.dagger:hilt-compiler:2.44'
// For instrumentation tests
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.44'
kaptAndroidTest 'com.google.dagger:hilt-compiler:2.44'
// For local unit tests
testImplementation 'com.google.dagger:hilt-android-testing:2.44'
kaptTest 'com.google.dagger:hilt-compiler:2.44'
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
}
if can any one help me to find what is wrong and explained why, i will be so thankful towards him. i rally need to pass this so i can level up in my career.
Remove below deprecated dependency:
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
(It was deprecated since dagger-2.34 version)
proof:
https://github.com/google/dagger/releases/tag/dagger-2.34
Also Try to upgrade your lifecycle version as below:
def lifecycle_version = "2.5.1"
add below lines after dependency section in build.gradle(app):
kapt { correctErrorTypes true }
follow official documentation:
https://developer.android.com/training/dependency-injection/hilt-android
https://dagger.dev/hilt/view-model.html

Creating a ViewModel causes the app to crash. (Kotlin/Android Studio)

I have been following a tutorial from Geeks for Geeks on how to make a simple note app for Android. I've practically copied to code word-by-word (except for a minor fix in the gradle file as advised from a Stack Overflow post and a comment in the YouTube comment section), yet the app crashes every time I open it even after clearing all the caches and rebuilding the project.
Links:
https://www.geeksforgeeks.org/how-to-build-a-simple-note-android-app-using-mvvm-and-room-database/
https://www.youtube.com/watch?v=D2F5t-phP04
Now, I know the problem with the code stems from the below command line.
viewModel = ViewModelProvider(
this,
ViewModelProvider.AndroidViewModelFactory.getInstance(application)
).get(NoteViewModel::class.java)
Every time I include the above line and launch the app, the app crashes, and my phone cannot open it. Commenting out the above line and the code below it allows the app to be opened without an issue.
(App gradle)
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.notepractice"
minSdk 26
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
packagingOptions {
exclude 'META-INF/atomicfu.kotlin_module'
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation "androidx.appcompat:appcompat:$rootProject.appCompatVersion"
implementation "androidx.activity:activity-ktx:$rootProject.activityVersion"
// Dependencies for working with Architecture components
// You'll probably have to update the version numbers in build.gradle (Project)
implementation 'androidx.fragment:fragment-ktx:1.1.0'
// Room components
implementation "androidx.room:room-ktx:$rootProject.roomVersion"
annotationProcessor "androidx.room:room-compiler:$rootProject.roomVersion"
androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"
// Lifecycle components
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-common-java8:$rootProject.lifecycleVersion"
// Kotlin components
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$rootProject.coroutines"
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$rootProject.coroutines"
// UI
implementation "androidx.constraintlayout:constraintlayout:$rootProject.constraintLayoutVersion"
implementation "com.google.android.material:material:$rootProject.materialVersion"
// Testing
testImplementation "junit:junit:$rootProject.junitVersion"
androidTestImplementation "androidx.arch.core:core-testing:$rootProject.coreTestingVersion"
androidTestImplementation ("androidx.test.espresso:espresso-core:$rootProject.espressoVersion", {
exclude group: 'com.android.support', module: 'support-annotations'
})
androidTestImplementation "androidx.test.ext:junit:$rootProject.androidxJunitVersion"
}
(Project gradle)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.5.31"
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle-api:7.2.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id 'com.android.application' version '7.2.0' apply false
id 'com.android.library' version '7.2.0' apply false
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}
allprojects {
repositories {
google()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
/*
ext {
activityVersion = '1.4.0'
appCompatVersion = '1.4.0'
constraintLayoutVersion = '2.1.2'
coreTestingVersion = '2.1.0'
coroutines = '1.5.2'
lifecycleVersion = '2.4.0'
materialVersion = '1.4.0'
roomVersion = '2.3.0'
// testing
junitVersion = '4.13.2'
espressoVersion = '3.4.0'
androidxJunitVersion = '1.1.3'
}
*/
ext {
activityVersion = '1.2.3'
appCompatVersion = '1.3.0'
constraintLayoutVersion = '2.0.4'
coreTestingVersion = '2.1.0'
coroutines = '1.5.0'
lifecycleVersion = '2.3.1'
materialVersion = '1.3.0'
roomVersion = '2.3.0'
// testing
junitVersion = '4.13.2'
espressoVersion = '3.1.0'
androidxJunitVersion = '1.1.2'
}
(Main Activity)
package com.example.notepractice
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton
import java.util.*
class MainActivity : AppCompatActivity(), NoteClickInterface, NoteClickDeleteInterface {
lateinit var viewModel: NoteViewModel
lateinit var notesRV: RecyclerView
lateinit var addFAB: FloatingActionButton
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
notesRV = findViewById(R.id.RVNotes)
addFAB = findViewById(R.id.FABAddNote)
notesRV.layoutManager = LinearLayoutManager(this)
val noteRVAdapter = NoteRVAdapter(this, this, this)
notesRV.adapter = noteRVAdapter
viewModel = ViewModelProvider(
this,
ViewModelProvider.AndroidViewModelFactory.getInstance(application)
).get(NoteViewModel::class.java)
/*
viewModel.allNotes.observe(this, Observer { list ->
list?.let {
noteRVAdapter.updateList(it)
}
})
addFAB.setOnClickListener {
val intent = Intent(this#MainActivity, AddEditNoteActivity::class.java)
startActivity(intent)
this.finish()
}
*/
}
override fun onNoteClick(note: Note) {
val intent = Intent(this#MainActivity, AddEditNoteActivity::class.java)
intent.putExtra("noteType", "Edit")
intent.putExtra("noteTitle", note.noteTitle)
intent.putExtra("noteDescription", note.noteDescription)
intent.putExtra("noteId", note.id)
startActivity(intent)
}
override fun onDeleteIconClick(note: Note) {
viewModel.deleteNote(note)
Toast.makeText(this, "${note.noteTitle} Deleted", Toast.LENGTH_LONG).show()
}
}
(ViewModel)
package com.example.notepractice
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class NoteViewModel(application: Application): AndroidViewModel(application) {
val allNotes: LiveData<List<Note>>
val repository: NoteRepository
init {
val dao = NoteDatabase.getDatabase(application).getNotesDao()
repository = NoteRepository(dao)
allNotes = repository.allNotes
}
fun deleteNote (note: Note) = viewModelScope.launch(Dispatchers.IO) {
repository.delete(note)
}
fun updateNote(note: Note) = viewModelScope.launch(Dispatchers.IO) {
repository.update(note)
}
fun addNote(note: Note) = viewModelScope.launch(Dispatchers.IO) {
repository.insert(note)
}
}
I'd like to end my question post with an actual question, but I am very inexperienced and cannot specify the problem. What would be the correct way to set up a ViewModel in Android with Kotlin?
Try initialising NoteViewModel like this inside your Activity.
private val viewModel: NoteViewModel by lazy {
ViewModelProvider(this).get(NoteViewModel::class.java)
}

Room Persistance Library: Cannot find implementation for ContactAppDatabase (ContactAppDatabase_Impl does not exist)

I am implementing Room database for storing contacts for the jetpack compose project on Android Studio Bumblebee 2021.1.1 Canary 10. But I am getting an error as shown below
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.tana.contactapp, PID: 8843
java.lang.RuntimeException: cannot find implementation for com.tana.contactapp.data.ContactAppDatabase. ContactAppDatabase_Impl does not exist
Here is my app-level Gradle file
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdk 30
defaultConfig {
applicationId "com.tana.contactapp"
minSdk 22
targetSdk 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion compose_version
}
packagingOptions {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.6.0'
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation "androidx.compose.material:material-icons-core:$compose_version"
implementation "androidx.compose.material:material-icons-extended:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.3.0'
implementation 'androidx.room:room-ktx:2.3.0'
implementation 'androidx.compose.runtime:runtime-livedata:1.0.2'
implementation 'androidx.navigation:navigation-compose:2.4.0-alpha06'
annotationProcessor 'androidx.room:room-compiler:2.3.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
}
Here is the project-level Gradle file
task clean(type: Delete) {
delete rootProject.buildDir
}
buildscript {
ext {
compose_version = '1.0.2'
}
}
Here is settings.gradle file
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
plugins {
id 'com.android.application' version '7.1.0-alpha10'
id 'com.android.library' version '7.1.0-alpha10'
id 'org.jetbrains.kotlin.android' version '1.5.21'
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "ContactApp"
include ':app'
Here is my Entity File
package com.tana.contactapp.data
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Person
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
#Entity(tableName = "contacts")
data class Contact(
#PrimaryKey(autoGenerate = true) val id: Long = 0,
val name: String,
val number: String,
#Ignore val imageDp: ImageVector = Icons.Default.Person
)
Here is my DAO File
package com.tana.contactapp.data
import androidx.lifecycle.LiveData
import androidx.room.*
#Dao
interface ContactAppDao {
#Query("SELECT * FROM contacts")
fun getContacts(): LiveData<List<Contact>>
#Insert
suspend fun addContact(contact: Contact)
#Update
suspend fun updateContact(contact: Contact)
#Delete
suspend fun deleteContact(contact: Contact)
#Query("DELETE FROM contacts")
suspend fun deleteContacts()
}
Here is my Database File
package com.tana.contactapp.data
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
#Database(entities = [Contact::class], version = 1, exportSchema = false)
abstract class ContactAppDatabase : RoomDatabase() {
abstract fun contactsDao(): ContactAppDao
companion object {
private var INSTANCE: ContactAppDatabase? = null
fun getDatabase(context: Context): ContactAppDatabase {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
ContactAppDatabase::class.java,
"contact_app_database"
).build()
}
return instance
}
}
}
}
I have tried a lot of solutions from the previous questions similar to this but none seems to work for my case
You need to remove
annotationProcessor 'androidx.room:room-compiler:2.3.0'
and add room compiler using kapt
kapt androidx.room:room-compiler:$room_version
https://developer.android.com/jetpack/androidx/releases/room#kts
and kapt plugin, on top of your root gradle file
apply plugin: "kotlin-kapt"
I solved this by adding id 'org.jetbrains.kotlin.kapt' version '1.5.21' in settings.gradle file plugins section, and then adding id 'org.jetbrains.kotlin.kapt' in app gradle file instead of 'kotlin-kapt'

Android Tests failing when using Hilt caused by ClassCastException

I have been writing kotlin code for android apps for quite some time, but I decided to also start writing testing code too for my apps. I have been facing some problems though with the use of Hilt. What I tried is :
import android.app.Application
open class AbstractApplication: Application()
#HiltAndroidApp
class IgmeApplication : IgmeAbstractApplication() {
#Inject
lateinit var authenticationManager: AuthenticationManager
....
}
and then in the Android Test Directory:
import dagger.hilt.android.testing.CustomTestApplication
#CustomTestApplication(AbstractApplication::class)
open class HiltTestApplication
import android.app.Application
import android.content.Context
import androidx.test.runner.AndroidJUnitRunner
class HiltTestRunner : AndroidJUnitRunner() {
override fun newApplication(
cl: ClassLoader?,
className: String?,
context: Context?
): Application {
return super.newApplication(cl,HiltTestApp::class.java.name, context)
}
}
my Test class :
#HiltAndroidTest
class AuthenticationTest{
#get:Rule
var hiltRule = HiltAndroidRule(this)
#Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
Assert.assertEquals("com.crowdpolicy.onext.igme", appContext.packageName)
}
#Before
fun setUp() {
// Populate #Inject fields in test class
hiltRule.inject()
}
#After
fun tearDown() {
}
}
my app level gradle file :
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'com.google.gms.google-services'
id 'com.google.firebase.crashlytics'
id 'com.google.firebase.firebase-perf' // Firebase Performance monitoring
id 'androidx.navigation.safeargs.kotlin'
id 'dagger.hilt.android.plugin'
id 'kotlin-parcelize'
id 'com.google.protobuf'
}
Properties localProperties = new Properties()
localProperties.load(new FileInputStream(rootProject.file('local.properties')))
Properties keyStoreProperties = new Properties()
keyStoreProperties.load(new FileInputStream(rootProject.file('keystore.properties')))
android {
buildToolsVersion "30.0.3"
ndkVersion localProperties['ndk.version']
signingConfigs {
release {
storeFile file(keyStoreProperties['key.release.path'])
keyAlias 'igme-key'
storePassword keyStoreProperties['key.release.keystorePassword']
keyPassword keyStoreProperties['key.release.keyPassword']
}
}
compileSdkVersion 30
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
freeCompilerArgs += '-Xopt-in=kotlin.RequiresOptIn'
}
defaultConfig {
applicationId "com.crowdpolicy.onext.igme"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "com.crowdpolicy.onext.igme.HiltTestRunner"
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
debuggable false
//signingConfig signingConfigs.release
firebaseCrashlytics {
// Enable processing and uploading o FirebaseCrashlytics.getInstance()f native symbols to Crashlytics
// servers. By default, this is disabled to improve build speeds.
// This flag must be enabled to see properly-symbolicated native
// stack traces in the Crashlytics dashboard.
nativeSymbolUploadEnabled true
unstrippedNativeLibsDir "$buildDir/ndklibs/libs"
}
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
ndk.debugSymbolLevel = "FULL" // Generate native debug symbols
}
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/rxjava.properties'
}
kotlinOptions {
jvmTarget = '1.8'
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
android.buildFeatures.viewBinding = true
dependencies {
// Testing-only dependencies
testImplementation 'junit:junit:4.13.2'
// Core library
androidTestImplementation 'androidx.test:core:1.4.0'
// AndroidJUnitRunner and JUnit Rules
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test:rules:1.4.0'
// Assertions
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.ext:truth:1.4.0'
// Espresso dependencies
androidTestImplementation "androidx.test.espresso:espresso-core:$espresso_version"
androidTestImplementation "androidx.test.espresso:espresso-intents:$espresso_version"
androidTestImplementation "androidx.test.espresso:espresso-web:$espresso_version"
androidTestImplementation "androidx.test.espresso.idling:idling-concurrent:$espresso_version"
// The following Espresso dependency can be either "implementation"
// or "androidTestImplementation", depending on whether you want the
// dependency to appear on your APK's compile classpath or the test APK
// classpath.
androidTestImplementation "androidx.test.espresso:espresso-idling-resource:$espresso_version"
//Dagger
implementation "com.google.dagger:dagger:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"
// region Hilt
implementation "com.google.dagger:hilt-android:$hilt_version"
implementation "androidx.hilt:hilt-navigation-fragment:$hilt_fragment_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version" // or : kapt 'com.google.dagger:hilt-compiler:2.37'
// Testing Navigation
androidTestImplementation("androidx.navigation:navigation-testing:$nav_version")
// region Hilt testing - for instrumentation tests
androidTestImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
// Make Hilt generate code in the androidTest folder
kaptAndroidTest "com.google.dagger:hilt-android-compiler:$hilt_version"
// endregion
// For local unit tests
testImplementation 'com.google.dagger:hilt-android-testing:2.37'
kaptTest 'com.google.dagger:hilt-compiler:2.37'
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.37'
}
}
kapt {
correctErrorTypes true
javacOptions {
// These options are normally set automatically via the Hilt Gradle plugin, but we
// set them manually to workaround a bug in the Kotlin 1.5.20: https://github.com/google/dagger/issues/2684
option("-Adagger.fastInit=ENABLED")
option("-Adagger.hilt.android.internal.disableAndroidSuperclassValidation=true")
}
}
// https://github.com/google/protobuf-gradle-plugin
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:$protobuf_version"
// path = localProperties["protoc.dir"]
}
// Generates the java Protobuf-lite code for the Protobufs in this project. See
// https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
// for more information.
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option 'lite'
}
}
}
}
}
dependencies {
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
}
(Above I added only the dependencies used for testing )
project gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.5.20"
ext.google_version = '4.3.4'
ext.timberVersion = '4.7.1'
ext.event_bus = '3.2.0'
ext.gson_version = '2.8.6'
ext.retrofit2_version = '2.9.0'
ext.datastore_version = '1.0.0-rc02'
ext.rxkotlin_version = '3.0.1'
ext.rxandroid_version = '3.0.0'
ext.lifecycle_version = '2.3.1'
ext.dagger_version = '2.37'
ext.hilt_version = '2.37'
ext.hilt_fragment_version = '1.0.0'
ext.nav_version = '2.3.5'
ext.fragment_version = '1.3.6'
ext.androidXTestCoreVersion = '1.4.0'
ext.espresso_version = '3.4.0'
ext.lottie_version = '3.6.1'
ext.facebook_version = '9.0.0'
ext.protobuf_version = '3.15.8'
ext.protobuf_gradle_plugin_version = '0.8.16'
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.google.gms:google-services:$google_version"
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.7.1'
classpath 'com.google.firebase:perf-plugin:1.4.0'
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
classpath "com.google.protobuf:protobuf-gradle-plugin:$protobuf_gradle_plugin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
I followed the official documentation from dagger-hilt in this page : https://dagger.dev/hilt/testing.html, but I am still getting this error :
Caused by: java.lang.ClassCastException: com.crowdpolicy.onext.igme.HiltTestApplication cannot be cast to android.app.Application
at android.app.Instrumentation.newApplication(Instrumentation.java:997)
at android.app.Instrumentation.newApplication(Instrumentation.java:982)
at com.crowdpolicy.onext.igme.HiltTestRunner.newApplication(HiltTestRunner.kt:14)
at android.app.LoadedApk.makeApplication(LoadedApk.java:617)
and I do not know how to fix it, because I am really new to testing and it is the first time facing it !
line 14 in HIltTestRunner is :
return super.newApplication(cl,HiltTestApp::class.java.name, context)
I had the same Problem, while Testing i got a ClassCastException: HiltTestApplication cannot be cast to AbcApp (my Application class).
Solution is the #CustomTestApplication annotation, see Dagger Docs or Android Dev Docs and the use of the generated class
<interfacename>_Application.
Further on be aware that just using IgmeApplication (or AbcApp in my case) is not possible when it uses the #HiltAndroidApp annotation, see open Issue. Then you have to make an open class AbstractApplication: Application() like the questioner did. Which is then subclassed by your Application (AbcApp in my case or IgmeApplication in questioners case) and subclassed by the created class from annotation #CustomTestApplication. like:
#CustomTestApplication(AbstractApplication::class)
interface CustomTestApplicationForHilt
Note that interface is used instead of open class, but it also works with open class like the questioner did.
The created class is then CustomTestApplicationForHilt_Application which has to be used, when calling newApplication in your Testrunner class, like:
class HiltTestRunner : AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application {
return super.newApplication(cl, CustomTestApplicationForHilt_Application::class.java.name, context)
}
}
Note that you can choose the name of the interface for the #CustomTestApplication annotation (here CustomTestApplicationForHilt) like you want, but the ending _Application will be added to the class name when the annotation is processed while building the app. Also note that the class will not be available before the build.

Starting out with Room, encountered this error: incompatible types: NonExistentClass cannot be converted to Annotation

I have looked at the solutions presented at each of these links.
NonExistentClass cannot be converted to Annotation - app:kaptDebugAndroidTestKotlin
-- Not relevant as I am not using JUnit5.
error: incompatible types: NonExistentClass cannot be converted to Annotation #error.NonExistentClass()
-- Two issues, one is I don't know where to put kapt { } and I tried leaving it as a global, but that didn't do anything and putting it in dependency caused a error.
NonExistentClass cannot be converted to Annotation
-- Unsure where to set generateStubs to true and where to set correctErrorTypes to true in my build.gradle file. I don't know if I can use annotationProcessor on it's own.
On my own I tried to implement android.arch before realizing it is deprecated.
I tried to use ksp but that returned an error stating that the complier doesn't know where the ksp() method is. Using
implementation("com.google.devtools.ksp:symbol-processing-api:1.5.0-1.0.0-alpha10")
did not resolve the error with ksp.
The error message exactly: "error: incompatible types: NonExistentClass cannot be converted to Annotation"
#error.NonExistentClass()
Here is my module build.gradle
plugins {
id 'com.android.application'
// id 'com.android.feature'
id 'kotlin-android'
id 'kotlin-kapt'
//id 'dagger.hilt.android.plugin'
//id 'kotlin-ksp'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android'
//apply plugin: 'dagger.hilt.android.plugin'
//apply plugin: 'com.android.feature'
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.testingdatabases"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
kapt {
correctErrorTypes = true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
// ROOM - -- - --- - - - >
def room_version = "2.3.0"
implementation("androidx.room:room-runtime:$room_version")
annotationProcessor "androidx.room:room-compiler:$room_version"
// To use Kotlin annotation processing tool (kapt)
kapt("androidx.room:room-compiler:$room_version")
// To use Kotlin Symbolic Processing (KSP)
// ksp("androidx.room:room-compiler:$room_version")
// optional - Kotlin Extensions and Coroutines support for Room
implementation("androidx.room:room-ktx:$room_version")
api("io.grpc:grpc-kotlin-stub:1.0.0")
// implementation("com.google.devtools.ksp:symbol-processing-api:1.5.0-1.0.0-alpha10")
// < -- - - - End of Room stuff
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
Here is the project's build.gradle file,
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.5.0"
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
def nav_version = "2.3.0-alpha01"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Here is the applications code,
package com.example.testingdatabases
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.room.RoomDatabase;
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
#Entity
data class User(
#PrimaryKey val uid: Int,
#ColumnInfo(name = "first_name") val firstName: String?,
#ColumnInfo(name = "last_name") val lastName: String?
)
#Dao
interface UserDao {
#Query("SELECT * FROM user")
fun getAll(): List<User>
#Query("SELECT * FROM user WHERE uid IN (:userIds)")
fun loadAllByIds(userIds: IntArray): List<User>
#Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
"last_name LIKE :last LIMIT 1")
fun findByName(first: String, last: String): User
#Insert
fun insertAll(vararg users: User)
#Delete
fun delete(user: User)
}
#Database(entities = arrayOf(User::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
in gradle implementation "a-b-x" is used and in kotlin dsl implemntation("a-b-x") is used ,don't mix
Your database is not build properly (According to me) Here

Categories

Resources