it's my first time diving in with protobuf and jetpack's DataStore but I've encountered an issue which is quite confusing.
I've created my .proto file in src/main/java/proto, it's really simple:
syntax = "proto3";
option java_package = "com.test.appname.proto";
option java_multiple_files = true;
message WalkInfo {
float distance = 1;
bool run = 2;
}
Then I've written in kotlin a serializer class for some data in my app.
object WalkInfoSerializer : Serializer<Walker.WalkInfo>{
override val defaultValue: Walker.WalkInfo
get() = WalkInfo.getDefaultInstance()
override fun readFrom(input: InputStream): Walker.WalkInfo {
try {
return WalkInfo.parseFrom(input)
} catch (exception: InvalidProtocolBufferException) {
throw CorruptionException("Cannot read proto.", exception)
}
}
override fun writeTo(t: Walker.WalkInfo, output: OutputStream) {
t.writeTo(output)
}
}
I've also set up my build.gradle file like this:
plugins {
id 'com.android.application'
id 'kotlin-android'
id "com.google.protobuf" version "0.8.14"
}
...
dependencies {
...
//DataStore
implementation "androidx.datastore:datastore:1.0.0-alpha05"
implementation 'com.google.protobuf:protobuf-javalite:3.14.0'
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.10.0"
}
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option 'lite'
}
}
}
}
}
Everything works fine, the classes seem to be generated correctly and they even pop up in android studio's autocomplete.
The problem is that I can't get the project to compile as I can't seem to find a way to resolve the "Unresolved Reference" for the methods generated (like getDefaultInstance(), parseFrom(), writeTo()
Even by writing the full class path it won't work.
Am I missing something? I've tried to play around with build.gradle and the proto file with some settings I found in their documentation but I still couldn't get it to work
Thank you!
Went to sleep, woke up, and knew the answer to my problems.
Dumb brain managed to do 1 + 1 during the night.
I realized that if the proto classes are being generated, I should not be defining them myself in kotlin code.
I had a WalkInfo message that generated a WalkInfo class, but I also had a WalkInfo class already with some methods in it. This is what was confusing the compiler.
After further research I realized that classes generated by proto are not even meant to be extended, they are supposed to be just data containers.
What I ended up doing is renaming my message to WalkInfoStorage while also keeping my WalkInfo kotlin class, I'll then be handling generating WalkInfo instances from the serialized data
All of sudden I start getting this error, and I am not getting idea why if anyone just let me know where this error is, will be enough helpful. As much I am able to get is this because of new update of android studio.
Detailed summary of error I am getting.
Task :app:kaptDebugKotlin
ANTLR Tool version 4.5.3 used for code generation does not match the current runtime version 4.7.1ANTLR Runtime version 4.5.3 used for parser compilation does not match the current runtime version 4.7.1ANTLR Tool version 4.5.3 used for code generation does not match the current runtime version 4.7.1ANTLR Runtime version 4.5.3 used for parser compilation does not match the current runtime version 4.7.1C:\Users\shubh\Downloads\MarginCalculator\app\build\generated\source\kapt\debug\com\kotlin_developer\margincalculator\DataBinderMapperImpl.java:10: error: cannot find symbol
import com.kotlin_developer.margincalculator.databinding.FragmentCalculatorScreenBindingImpl;
symbol: class FragmentCalculatorScreenBindingImpl
Task :app:kaptDebugKotlin FAILED
location: package com.kotlin_developer.margincalculator.databinding
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:kaptDebugKotlin'.
> A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution
> java.lang.reflect.InvocationTargetException (no error message)
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 17s
29 actionable tasks: 27 executed, 2 up-to-date
Android Studio's UI was just hiding the error...
when the error occurred, it highlighted the item in the list view, and showed an unhelpful message in the terminal view.
to find the real error, select the root item in the list view so that Android Studio would display the whole build output in the terminal view, then scroll to find error.
Maybe I am a bit late for the answer but, anyways, I was getting the same error. The build failure can be caused by some error that Android Studio fails to point out probably due the the project size being very large.
Here is the easy way to point out the exact error.
In Android studio go to Analyze menu and click on Inspect Code; check whole project, click OK and wait for the inspection to finish.
Now you will see a tab that will point all the errors, warnings etc and you can now resolve the real issue.
The way to find out what the underlying issue is, is to run the following command :
./gradlew assembleDebug --stacktrace
Change
implementation "android.arch.persistence.room:runtime:1.1.1"
kapt "android.arch.persistence.room:compiler:1.1.1"
To
(updated 4 - September-2021)
implementation "androidx.room:room-runtime:2.3.0"
annotationProcessor "androidx.room:room-compiler:2.3.0"
I started getting this after upgrading my Android Studio to Arctic Fox(2020.3.1).
I resolved it by updating my JDK version from 1.8 to Embedded JDK.
To change the JDK:
Open your project in Android Studio and select File > Settings... > Build, Execution, Deployment > Build Tools > Gradle
On Mac: Android Studio > Preferences... > Build, Execution, Deployment > Build Tools > Gradle.
Under Gradle JDK, choose the Embedded JDK option.
As mentioned here
Click on --stacktrace on the terminal to see the error in details. You can find it here:
M1 Chip Solution
If you have a MacBook Pro chances are that adding kapt "org.xerial:sqlite-jdbc:3.34.0" before the room-compiler will solve your problem.
kapt "org.xerial:sqlite-jdbc:3.36.0" // Only for computer with M1 CPU
implementation("androidx.room:room-ktx:$room_version")
kapt "androidx.room:room-compiler:$room_version"
See more here.
I got the same issue, so I tried to get more information, by doing
gradle->app->Tasks->Build->assemble
After this I got exact error saying "Error while annotation processing".
I checked my recently tweaked DAO class and found that one of the method return type was not defined.
//Before
#Query("SELECT countryName FROM country_table WHERE countryCode= :code")
fun getCountryNameForCode(code: String)
//After
#Query("SELECT countryName FROM country_table WHERE countryCode= :code")
fun getCountryNameForCode(code: String): String
I had the same error for a while then I started checking the other packages I came to know that I've made a typo mistake in my database code. So,
"Go through your database and other activity class files u may find some mistakes there."
After a lot of pain, I decided to try annotationProcessor instead of kapt hoping it may at least show an error message or anything that can help me locate the source. But fortunately (or unfortunately; because of the wasted time), it was built successfully without any errors.
It's mostly a bug in kapt itself. So, try this solution and it may help.
For me, a bunch of reference errors and an error in the XML expressions with DataBinding produced this error.
I have deleted a <variable/> in a layout file, because I thought, I don't need it anymore. I forgot that I had the variable referenced in the layout file.
After building the project, this produced an error, where it was not possible to import the BindingImpl class, because it does not exist and this error was only shown as a warning parallel to the above KaptExecution error.
After searching for a while, I found this error and resolved it. Then, a bunch of reference errors where shown, because I renamed something and it did not rename it in the Fragment files. After resolving these errors too, the build finished for me without errors or warnings.
Okay, this issue also occurs if you are using Android Studio 4.1.2.
So, what you have to do is:
Download jdk 11 (Search and download)
In Android Studio, go to File -> Project Structure -> Jdk Location -> Change to the path of the Jdk you just downloaded.
try to build your project with
kapt.use.worker.api=false
in your gradle.properties settings file
Reference: https://youtrack.jetbrains.com/issue/KT-40750
The same problem for me here. In my case, the reason is that I've forgot a #Module annotation in one of my dagger module.
To find the real problem of such an AS alert, it's necessary going deep: the messagge in the title it's only the final one, the 1 or more causes of the error are shown selecting the root element on the left, that shows you the exact problems, check my printscreen below :
I had the same problem. In my case the problem was about Database. i had to change this line of code
#Database(entities = [SearchedLocation::class, FavoriteLocation::class], version = 1)
I added another table in Database but forgot to add table in the line above.
I had the same problem. Let me walk you through the example on how I ended up to the problem and the way I resolved it perhaps you can get a bigger picture.
Before resolving
#Entity(tableName = "modules")
data class Module
(
#PrimaryKey val id: Int,
val name: String
)
#Entity(tableName = "sessions")
data class Session
(
#PrimaryKey(autoGenerate = true) var id: Int,
#ColumnInfo(name = "module_id") val moduleId: Int,
#ColumnInfo(name = "start_time") val startTime: String,
#ColumnInfo(name = "end_time") val endTime: String
)
data class ModuleSession
(
#Embedded val module: Module,
#Relation(
parentColumn = "id",
entityColumn = "module_id"
)
val sessions: List<Session>,
#ColumnInfo(name = "is_updated") val isUpdated: Boolean = false // The problem
)
In the DAO
#Transaction
#Query("SELECT * FROM modules")
abstract suspend fun getModuleSession(): List<ModuleSession>
The error I got was
A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution
So I dug deeper and found the below message
The columns returned by the query does not have the fields [isUpdated] in com.gmanix.oncampusprototype.Persistence.ModuleSession even though they are annotated as non-null or primitive. Columns returned by the query: [id,name]
public abstract java.lang.Object getModuleSession(#org.jetbrains.annotations.NotNull()
I removed the field IsUpdated from the POJO ModuleSession and added it to the session table
After changes
#Entity(tableName = "sessions")
data class Session
(
#PrimaryKey(autoGenerate = true) var id: Int,
#ColumnInfo(name = "module_id") val moduleId: Int,
#ColumnInfo(name = "start_time") val startTime: String,
#ColumnInfo(name = "end_time") val endTime: String,
#ColumnInfo(name = "is_updated") val isUpdated: Boolean = false
)
data class ModuleSession
(
#Embedded val module: Module,
#Relation(
parentColumn = "id",
entityColumn = "module_id"
)
val sessions: List<Session>
)
On the other hand crosscheck if there is any field on the SELECT statement that is a suspect causing issues or you can annotate it with #Ignore
However you can post your code if you're still not comfortable.
I hope that might help
In my case I forget adding #PrimaryKey in Entity class.
In my case I got this error when moving from jcenter() to mavenCentral(), one of my dependencies was available only on jcenter() and not mavenCentral().
So i submitted issue to the owner for the same on github and will wait to remove jcenter() until its moved.
I got the same problem when I added ROOM to my App(Kotlin).
I had a hard time finding out what was wrong and finally figured out that i was using the following for adding ROOM to my app.
//room
implementation 'android.arch.persistence.room:runtime:1.1.1'
kapt "android.arch.persistence.room:compiler:1.1.1"
So i changed the above two lines with the following and got rid of the pain.
def room_version = "2.2.6"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
Hit the up button if it helped you :D
If you have upgraded to classpath 'com.android.tools.build:gradle:4.0.0'
Replace it previous version
dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
}
And Change gradle-wrapper.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4- all.zip`
In my case, I used room and one of my databasDao methods has an unused parameter and unfortunately android studio doesn't warn me correctly
This problem also happens if you installed new kotlin plugin (1.4.20-release-Studio4.1-1) and have dagger (kapt 'com.google.dagger:dagger-compiler:2.30'). In such a case one solution might be replacing deprecated plugin: 'kotlin-android-extensions' with view binding (https://developer.android.com/topic/libraries/view-binding)
Looks like there is an issue with room library and apple M1 chips.
Update your room lib version to 2.4.0-alpha03 or above and resync project.
Worked for me!
In my case there were older dependencies which needed an upgradation,
So you can follow this :
1.FILE -> PROJECT STRUCTURE ->
2.Go to SUGGESSIONS ->
3.Under the WARNING SECTION Android Studio will show you which dependencies
needs to be upgraded->
4.Just upgrade it directly from there ->
5.CLICK APPLY->
It will work now!
Thanks!
In my case I was using Coroutines but I forget to add Kotlin Extensions and Coroutines support for Room
def room_version = "2.2.6"
implementation "androidx.room:room-ktx:$room_version"
In my case adding new fragments always resulted in this error popping up, I investigated my commit changes on git and it turns out that Android keeps auto-updating the gradle plugin whenever I create a new Fragment despite not giving it permissions to do so, so I had to rollback to my original gradle-plugin version inside the project level's build.gradle file:
from
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.0'
to
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21"
Monitor your git changes to figure out what Android is doing to your gradle files that's causing it to crash.
Shout Out to #Rene Spies' answer above, I also got this error while working with databinding. It turns out the build engine doesn't like it when you put the #Bindable annotation on a field in the primary constructor of a data class in Kotlin.
So never do the following,
data class MyAwesomePojo(
#Bindable
var firstname: String,
var lastname: String
)
instead what you need to do is
data class MyCorrectAwesomePojo(
var lastname: String
):{
#get:Bindable
var firstname: String
set(value){
field = value
}
}
Bonus: remember to check for same values before setting value to field if you are trying to use two-way binding like me to prevent infinite looping of setting and getting.
In my case it was because I was not implementing Observable in my ViewModel. I added an EditText to the constraint layout with android:text="#={addProductViewModel.inputProductName}"
Once I implemented Observable in my ViewModel class the error was gone
ViewModel
class AddProductViewModel (
private val repository: ProductRepository,
private val context: Context
): ViewModel(), Observable {
#Bindable
val inputProductName = MutableLiveData<String>()
fun addProduct() {
//inputProductName.value
}
override fun removeOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) {
TODO("Not yet implemented")
}
override fun addOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) {
TODO("Not yet implemented")
}
}
Complete example for MVVM Databinding using Fragments
Layout - add_product.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android" >
<data class=".AddProductBinding">
<variable
name="addProductViewModel"
type="com.rao.iremind.AddProductViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="#+id/editTextTextProductName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Product name"
android:inputType="textPersonName"
android:text="#={addProductViewModel.inputProductName}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
AddProductFragment
class AddProductFragment: Fragment() {
private lateinit var binding: AddProductBinding
private lateinit var addProductViewModel: AddProductViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.add_product, container, false)
val dao = SubscriberDatabase.getInstance(requireActivity().applicationContext).productDAO
val repository = ProductRepository(dao)
val factory = AddProductViewModelFactory(repository, requireActivity().applicationContext)
addProductViewModel = ViewModelProvider(this, factory).get(AddProductViewModel::class.java)
binding.addProductViewModel = addProductViewModel
binding.lifecycleOwner = this
val view = binding.root
return view
}
}
AddProductViewModel
class AddProductViewModel (
private val repository: ProductRepository,
private val context: Context
): ViewModel(), Observable {
#Bindable
val inputProductName = MutableLiveData<String>()
fun addProduct() {
//inputProductName.value
}
override fun removeOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) {
TODO("Not yet implemented")
}
override fun addOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) {
TODO("Not yet implemented")
}
}
Hope this helps
R
In My Case: Issue resolved
Steps:
Remove viewModel variable - In XML.
<variable
name="viewModel"
type="com.xx.AppViewModel" / >
Removed all viewModel binding references - In XML.
android:text="#{viewModel.simName}"
Removed viewModel instance reference to the binding mapping - In Activity
binding.viewModel = viewModel
Clean project and recompile.
Add viewModel variable - In XML & Build project.
< variable
name="viewModel"
type="com.xx.AppViewModel" / >
Add viewModel instance reference to the binding mapping - In Activity & Build project
binding.viewModel = viewModel
Add all viewModel binding references - In XML & Build project..
android:text="#{viewModel.simName}"
It will work now.
-- I hope it will work for you also.
I had same problem with Room and i was not using viewBinding.
I Fixed it with using exportSchema to false in my database class.
#Database(entities = [ModelClass::class], version = 1, exportSchema = false)
abstract class ModelDatabase: RoomDatabase() {}
Remember: exportScehma could be vary according to your use case, generally it stays false so i put it to false.
In my case I have changed globally one variable UserManager to NetWorkManager and everywhere where there were UserManager classes they turned to be NetworkManager.
Because I'm using Hilt, I had to build the project again.
I cleaned the Project and Kotlin showed where the errors were.
I have a project for which I am using Room for storage, and am currently trying to set up a test for a simple migration.
I followed the steps described at https://medium.com/androiddevelopers/testing-room-migrations-be93cdb0d975 and have a test that looks like this:
#RunWith(AndroidJUnit4::class)
class MigrationsTest {
private val DB_NAME = "test.db"
private lateinit var testHelper: MigrationTestHelper
#Before
fun setup() {
testHelper = MigrationTestHelper(
androidx.test.platform.app.InstrumentationRegistry.getInstrumentation(),
MyDatabase::class.java.canonicalName,
FrameworkSQLiteOpenHelperFactory()
)
}
#Test
fun testMigrate1_2() {
val db = testHelper.createDatabase(DB_NAME, 1)
db.close()
testHelper.runMigrationsAndValidate(DB_NAME, 2, true, MyDatabase.MIGRATION_1_2)
}
}
However, when running the test on a physical device, I get the following exception:
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/gson/GsonBuilder;
The MigrationTestHelper itself seems fine, and if I try to create a Gson or GsonBuilder object within the test, I get the same error.
In my dependencies, I also added these lines (using Kotlin DSL):
dependencies {
...
androidTestImplementation("android.arch.persistence.room:testing:1.1.1")
androidTestImplementation("com.google.code.gson:gson:2.8.0")
}
Running the app itself is fine, storage works as expected.
What is the proper way to include Gson and avoid this error? Not being able to easily test transactions is an issue for me.
Okay I figured it out. It was just a proguard issue. Whenever a class isn't found, you just need to make sure it isn't stripped out.
In my case, I added this line to my proguard file
-keep class com.google.gson.** { *; }
And then keep adding more instructions whenever it complains.
I implemented Jacoco in my Android project using the following tutorial https://proandroiddev.com/unified-code-coverage-for-android-revisited-44789c9b722f to cater for test coverage in the kotlin classes.
For some unknown reason, it's not reporting coverage for static methods declared under the Companion block.
class Meh {
companion object {
fun test () {
// logic to test
}
}
However if I convert the class to an instance rather than a singleton that I am able to see the coverage completely fine.
Has anyone came across this problem ? and what did you do ?
following tutorial https://proandroiddev.com/unified-code-coverage-for-android-revisited-44789c9b722f
after cloning of example from the same tutorial in its state as of today (HEAD commit)
git clone https://github.com/rafaeltoledo/unified-code-coverage-android.git
cd unified-code-coverage-android
git checkout kotlin-coverage
addition of companion object into MainActivity
class MainActivity : AppCompatActivity() {
+ companion object {
+ fun executed() {
+ }
+
+ fun notExecuted() {
+ }
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
+ executed()
start of virtual device Pixel XL with API 28 and target Android 9.0 (Google APIs) in freshly downloaded Android Studio 3.2.1
and execution of
./gradlew jacocoTestReport
following report is produced in directory app/build/reports/jacoco/jacocoTestReport/html/ as expected
Given the amount of factors that influence result (such as versions of all involved components - Android SDK, Device, Kotlin compiler, Gradle, JaCoCo, etc, etc), attempts to guess what is different in your case are IMO counterproductive, and so that the best advice - is to perform very careful comparison of differences between your setup and above example.
Update
As was figured out during comparison by #HeWhoProtects , problem was in
exclusion of **/*$*
that refers to exclusion of class files from analysis. Single source file can compile into multiple class files, e.g. in case of nested classes in Java and exactly in case of companion in Kotlin and in both cases name of class and class file will contain $.
I found the the cause of the problem but not sure why it caused it yet, my excludes rules includes more rules than the one in the tutorial above, in different jacoco tutorial for ignoring autogenerated files, it was suggested to include '**/*$*' as rule, as soon as I removed it, it showed coverage for static methods in kotlin.
My understanding of Jacoco that these rules ignore files and will not show it in the report, and before I made the change, it was showing that this class is covered in the test coverage.... is it weird or am I missing a fundamental thing about how kotlin generates methods or how jacoco excludes rules work ?
Anyway I hope this helps..
I am attempting to create an Android application using Scala 2.9.2. So far, I have got everything to compile.
However, I am running into problems when I perform the following in my activity:
override def onCreateDialog(id: Int) {
The compiler complains of an incompatible type as Activity.onCreateDialog() takes a primitive int yet I am passing a scala.Int.
The folowing is the compilation error:
error: overriding method onCreateDialog in class Activity of type (x$1: Int)android.app.Dialog;
[INFO] method onCreateDialog has incompatible type
[INFO] override def onCreateDialog(id: Int) {
[INFO] ^
[ERROR] one error found
I thought these would be compatible.
Can anyone advise how to get around this problem?
The following is for Scala 2.10, but I think that the cause of the error is exactly the same for Scala 2.9.x.
By the way, the onCreateDialog(int) method from the type Activity is deprecated, but it's beside the point.
Now, I'm not a Scala expert by any means, but from what I have noticed, functions that do not return anything tend do look like def fun(arg) {}, and ones that do: def fun(arg) = {}. Notice the =. You can also spell out the return type if you want.
So I tried to override the method you mention, and here's the (trivial) implementation:
override def onCreateDialog(id : Int) = {
super.onCreateDialog(id)
}
And it compiles and runs just fine. When you remove the =, you'll get the error you have right now:
overriding method onCreateDialog in class Activity of type (x$1: Int)android.app.Dialog; method onCreateDialog has
incompatible type
The whole MainActivity:
class MainActivity extends Activity {
override def onCreate(savedInstanceState : Bundle) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main_activity)
}
override def onCreateDialog(id : Int) = {
super.onCreateDialog(id)
}
}
Notes: I'm using ADT with bundled Eclipse (Juno), created a default Android project, including Scala-IDE (Scala nature) and AndroidProguardScala (AndroidProguardScala nature)