I am working one project using kotlin + Rxjava + MVVM. During development facing issue of importing view ids in Fragment or viewholder.
import kotlinx.android.synthetic.main.layout.* unused with kotlin.
Normaly view id should used from kotlin synthetic layout imports but it directly import it from R.id that should not happen.
Kotlin plugin version : org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.40
My gradle file :
apply plugin: 'com.android.feature'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'idea'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 27
baseFeature true
defaultConfig {
minSdkVersion 23
targetSdkVersion 27
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}
dependencies {
api "com.android.support:design:$rootProject.support_library_version"
api "com.android.support:appcompat-v7:$rootProject.support_library_version"
api "com.android.support:recyclerview-v7:$rootProject.support_library_version"
api "com.android.support:support-dynamic-animation:$rootProject.support_library_version"
api "com.android.support:cardview-v7:$rootProject.support_library_version"
api "com.android.support:customtabs:$rootProject.support_library_version"
api "com.android.support.constraint:constraint-layout:1.1.0-beta5"
api 'android.arch.lifecycle:extensions:1.1.0'
api 'androidx.core:core-ktx:0.2'
api "com.google.dagger:dagger:$rootProject.dagger_version"
kapt "com.google.dagger:dagger-compiler:$rootProject.dagger_version"
api "android.arch.persistence.room:runtime:$rootProject.room_version"
kapt "android.arch.persistence.room:compiler:$rootProject.room_version"
testImplementation "android.arch.persistence.room:testing:$rootProject.room_version"
api "android.arch.persistence.room:rxjava2:$rootProject.room_version"
androidTestImplementation "android.arch.core:core-testing:$rootProject.room_version"
testImplementation "android.arch.core:core-testing:$rootProject.room_version"
api "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
api "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
api 'com.jakewharton.timber:timber:4.5.1'
api "com.android.support:multidex:1.0.3"
api "com.github.bumptech.glide:glide:$rootProject.glide_version"
api "jp.wasabeef:glide-transformations:$rootProject.glide_transformation_version"
api 'com.github.bumptech.glide:okhttp3-integration:1.5.0#aar'
api "io.reactivex.rxjava2:rxandroid:$rootProject.rxAndroid_version"
api "io.reactivex.rxjava2:rxjava:$rootProject.rxJava_version"
api "com.google.code.gson:gson:$rootProject.gson_version"
api("com.squareup.retrofit2:retrofit:$rootProject.retrofit_version") {
// exclude Retrofit’s OkHttp peer-dependency module and define your own module import
exclude module: 'okhttp'
}
api "com.squareup.okhttp3:okhttp:$rootProject.okhttp_version"
api "com.squareup.okhttp3:logging-interceptor:$rootProject.okhttp_version"
api "com.squareup.retrofit2:adapter-rxjava2:$rootProject.retrofit_version"
api "com.squareup.retrofit2:converter-gson:$rootProject.retrofit_version"
api 'com.jakewharton.threetenabp:threetenabp:1.0.5'
api "com.google.firebase:firebase-invites:$rootProject.play_services_version"
api "com.google.firebase:firebase-core:$rootProject.play_services_version"
api "com.google.firebase:firebase-config:$rootProject.play_services_version"
api "com.google.firebase:firebase-perf:$rootProject.play_services_version"
api "com.google.firebase:firebase-auth:$rootProject.play_services_version"
api "com.google.firebase:firebase-firestore:$rootProject.play_services_version"
api("com.firebaseui:firebase-ui-auth:$rootProject.firebase_ui_version") {
// exclude Retrofit’s OkHttp peer-dependency module and define your own module import
exclude module: 'play-services-auth'
exclude module: 'firebase-auth'
}
// Required only if Facebook login support is required
api('com.facebook.android:facebook-android-sdk:4.31.0')
api "com.google.android.gms:play-services-auth:$rootProject.play_services_version"
// Required only if Twitter login support is required
api("com.twitter.sdk.android:twitter-core:3.0.0#aar") { transitive = true }
api 'com.jakewharton.rxbinding2:rxbinding-kotlin:2.0.0'
api 'com.jakewharton.rxbinding2:rxbinding-support-v4-kotlin:2.0.0'
api 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7-kotlin:2.0.0'
api 'com.jakewharton.rxbinding2:rxbinding-design-kotlin:2.0.0'
api('com.crashlytics.sdk.android:crashlytics:2.9.1#aar') {
transitive = true
}
}
I have also tried clean build and Rebuild project.
Any idea how can i resolve this issue ?
I have tried several approaches including the solutions reported in this thread. I also found out that a lot of folks are facing this annoying problem as you can see here
Nevertheless, the most closest solution to this problem which has worked for me so far is removing apply plugin: kotlin-android-extensions from gradle, Sync gradle plugin and then add it again.
I'm using Android Studio 3.1.3 and I encountered the same issue. I managed to solve this by moving all my codes from java/ to kotlin/ directory inside main/.
app/
|-- src/
| |-- main/
| | |-- java/
| | | |-- com.example.android.app
| | |-- kotlin/ <-- (use this)
| | | |-- com.example.android.app
Then, add the kotlin/ as part of the source sets:
app/build.gradle
android {
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
Sometimes, it still requires to sync and rebuild the project to properly import the kotlinx.android....
Reference: Add kotlin code
I have the same problem and I am trying to solve it for too many days...
One trick you can do is to Exclude from Import and Completion <package-name>.R.id.* for project scope.
Go to Settings/Editor/Auto Import to add it.
It improves our issue and if you do this and clean the project, it will work but it does not resolve the issue completely. Many times the imports reappear as unused imports and there is to clean the project over and over :-(.
EDITED
Also, another improvement I have achieved is working with includes on XML. For example, if I am going to use "the same" button in several screens, I make a specific layout for this button and I re-use it on several activities / fragments. You can set the id within this specific layout and synthetic will auto-import it without generating conflicts, due to you have the content view reference declared before.
I show you a simple example:
activity_main.xml
<!-- ... -->
<include layout="#layout/btn_foo"/>
<!-- ... -->
btn_foo.xml
<?xml version="1.0" encoding="utf-8"?>
<Button
android:id="#+id/btnFoo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"/>
MainActivity.kt
// ...
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.btn_foo.*
// ...
setContentView(R.layout.activity_main)
// ...
btnFoo.setOnClickListener { }
I have to admit that in the other cases I have returned to the typical Hungarian convention whatWhereDescription(Size) to set the ids due to is too much annoying to deal with imports among activities / fragments / view all the time.
I've solved similar issues for ViewHolder implementations:
We have to inherit our ViewHolder class implementation from LayoutContainer. LayoutContainer is an interface available in kotlinx.android.extensions package.
You will have some code similar with this:
class TaskVH(override val containerView: View, val itemListener: TasksFragment.TaskItemListener) : RecyclerView.ViewHolder(containerView), LayoutContainer {
fun bindItem(task: Task) {
item_title.text = ""
item_complete.isChecked = task.isCompleted
itemView.setBackgroundResource(rowViewBackground)
itemView.setOnClickListener { itemListener.onTaskClick(task) }
}
}
I don't know if this tripped anyone else up, but I was having problems because I didn't realize the synthetic objects are only available if you're inside an Activity, Dialog, or Fragment. If you're in some other class (like using Conductor's Controller) you're out of luck.
Cross-posting my bug report with workaround from here: https://issuetracker.google.com/issues/145888144
Original bug was closed as "fixed" by google, but it is definitely not fixed: https://issuetracker.google.com/issues/78547457
SUMMARY:
For some modules in a multi-module project, the IDE does not properly recognize imports for "synthetic" symbols that abstract view ids, a feature provided by the plugin 'kotlin-android-extensions'. This results in class files using these symbols appearing full of errors, as the imports are "unresolved", the symbols are then unknown, and of course anything using these symbols fail because the types are unknown.This is solely an IDE problem though; everything compiles normally and works as expected.
ROOT CAUSE
The kotlin-language facet is not being applied to the errant modules.
BACKGROUND
Facets in IntelliJ IDEA projects are configurable on a module-by-module basis in Project settings. In Android Studio, this part of the Project settings UI is missing (or suppressed.) Presumably, Android Studio is attempting to apply the correct facets based on the gradle plugins applied to each module. This process is /sometimes/ FAILING for this particular case; I have not been able to determine what triggers the success/failure of the process.
TEMPORARY WORKAROUND
This workaround works consistently, and has since 3.5.2 when I discovered it:
Open the ".iml" file for the module you are trying to "fix" in Android Studio editor. (In AS > 4, the iml file is in .idea/modules, earlier than that it was in top-level of your module.) Find the <component name="FacetManager"> block, and notice that there is no facet called "kotlin-language" there. Paste the contents of the text block below so it appears within the <component name="FacetManager"> block. Save the file.
Re-import gradle.
This is a clumsy workaround, and has to be applied on a module-by-module basis. What's more, it may be required to sometimes re-apply the workaround after making changes to the build.gradle file for an affected module. The hope is that Google (or JetBrains, if it turns out it is their problem) will fix this problem properly.
Given that kotlin-android-extensions has fallen out of favor, I don't expect this bug will ever be fixed.
Text to use for the fix
<facet type="kotlin-language" name="Kotlin">
<configuration version="3" platform="JVM 1.8" allPlatforms="JVM [1.8]" useProjectSettings="false">
<compilerSettings />
<compilerArguments>
<option name="jvmTarget" value="1.8" />
<option name="pluginOptions">
<array>
<option value="plugin:org.jetbrains.kotlin.android:enabled=true" />
<option value="plugin:org.jetbrains.kotlin.android:defaultCacheImplementation=hashMap" />
</array>
</option>
</compilerArguments>
</configuration>
</facet>
There is an existing issue (which is assigned) on Google tracker regarding synthetic imports.
https://issuetracker.google.com/issues/78547457
For Conductor:
Create this base class.
import android.os.Bundle
import android.view.View
import com.bluelinelabs.conductor.Controller
import com.bluelinelabs.conductor.RestoreViewOnCreateController
abstract class BaseController(
bundle: Bundle? = null
) : RestoreViewOnCreateController(bundle){
init {
addLifecycleListener(object : LifecycleListener() {
override fun postCreateView(controller: Controller, view: View) {
onViewCreated(view)
}
})
}
open fun onViewCreated(view: View) { }
}
Then in your controller:
import kotlinx.android.synthetic.main.controller_example.view.*
class ProfileController : BaseController() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedViewState: Bundle?): View {
return inflater.inflate(R.layout.controller_example, container, false)
}
override fun onViewCreated(view: View) {
view.txtName.text = "Example"
}
}
I try every other solution bu no one worked for me. At the and I cloned project again and now it's working. I love android studio
Add id kotlin-android-extensions in your build.gradle file in the plugins block.
Google removed this feature by default
Related
What I'm trying to achieve
I'm trying to generate my REST API client for Android using OpenAPI Generator from the build.gradle script. That way, I wouldn't have to run the generator command line every time the specs change. Ideally, this would be generated when I build/assemble my app, and the sources would end up in the java (generated) folder, where generated sources are then accessible from the code (this is what happens with the BuildConfig.java file for example).
What I've tried so far
Following this link from their official GitHub, here's the build.gradle file I ended up with:
apply plugin: 'com.android.application'
apply plugin: 'org.openapi.generator'
...
openApiValidate {
inputSpec = "$rootDir/app/src/main/openapi/my-api.yaml"
recommend = true
}
openApiGenerate {
generatorName = "java"
inputSpec = "$rootDir/app/src/main/openapi/my-api.yaml"
outputDir = "$buildDir/generated/openapi"
groupId = "$project.group"
id = "$project.name-openapi"
version = "$project.version"
apiPackage = "com.example.mypackage.api"
invokerPackage = "com.example.mypackage.invoker"
modelPackage = "com.example.mypackage.model"
configOptions = [
java8 : "true",
dateLibrary : "java8",
library : "retrofit2"
]
}
...
First, I've never managed to get the API generated with the build/assemble task, even when I tried adding:
compileJava.dependsOn tasks.openApiGenerate
or
assemble.dependsOn tasks.openApiGenerate
The only way I could generate the sources was by manually triggering the openApiGenerate task:
Then, when I do generate my sources this way, they end up in the build folder but aren't accessible from my code, and aren't visible in the java (generated) folder:
I then have to manually copy/paste the generated source files to my project sources in order to use the API.
Even though I'm able to work around these issues by adding manual procedures, it would be way more maintainable if the whole process was simply automatic. I was able to achieve a similar result with another tool, Protobuf. Indeed, my gradle task gets triggered every time I build the app, and the sources end up in the java (generated) folder, so I don't have to do any additional work. The task is much simpler though, so I assume the main work that I'm not able to replicate with OpenAPI Generator is handled by the Protobuf plugin itself.
You have to specify path to the generated sources as a custom source set for your Gradle module, which is app in this case, as described here – https://developer.android.com/studio/build/build-variants#configure-sourcesets. That way Gradle will treat your sources as accessible from your code.
Something like this:
android {
...
sourceSets {
main {
java.srcDirs = ['build/generated/openapi/src/main/java']
}
}
...
}
I solved the issue you described like this, I'm using gradle.kts however.
See my build.gradle.kts
plugins {
// Your other plugins
id("org.openapi.generator") version "5.3.0"
}
openApiGenerate {
generatorName.set("kotlin")
inputSpec.set("$rootDir/app/src/main/openapi/my-api.yaml")
outputDir.set("$buildDir/generated/api")
// Your other specification
}
application {
// Your other code
sourceSets {
main {
java {
// TODO: Set this path according to what was generated for you
srcDir("$buildDir/generated/api/src/main/kotlin")
}
}
}
}
tasks.compileKotlin {
dependsOn(tasks.openApiGenerate)
}
You need to build the application at least once for the IDE to detect the library (at least this is the case for me in Intellij)
Your build should automatically generate the open api classes , to refer the generated classes in your java project you should add the generated class path to your source directory like it was mentioned in the other answers
https://developer.android.com/studio/build/build-variants#configure-sourcesets
As far as the task dependency goes , in android tasks are generated after configuration thus for gradle to recognize the task , wrap it inside afterEvaluate block like
afterEvaluate {
tasks.compileDebugJavaWithJavac.dependsOn(tasks.openApiGenerate)
}
I had this issue, and this answer https://stackoverflow.com/a/55646891/14111809 led me to a more informative error:
error: incompatible types: Object cannot be converted to Annotation
#java.lang.Object()
Taking a look at the generated files that were causing this error, noticed:
import com.squareup.moshi.Json;
After including a Moshi in the app build.gradle, the build succeeded and the generated code was accessible.
implementation("com.squareup.moshi:moshi-kotlin:1.13.0")
Based on Android docs (https://developers.google.com/games/services/android/quickstart#before_you_begin) for learning how to configure Google Play game APIs onto a sample app such as TypeANumber, I was wondering why I get the following resource errors from the BaseGameUtils library after importing the project, BasicSamples, from their GitHub's (https://github.com/playgameservices/android-basic-samples) source files:
... Based on the directory in the left panel, did I import it properly? All I did was import it straight from the directory: android-basic-samples/BasicSamples/build.gradle as stated in Step 1 of the link.
Here's my (untouched) Gradle file for the library, BaseGameUtils:
apply plugin: 'com.android.library'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
}
}
dependencies {
// Set defaults so that BaseGameUtils can be used outside of BasicSamples
if (!project.hasProperty('appcompat_library_version')) {
ext.appcompat_library_version = '20.0.+'
}
if (!project.hasProperty('support_library_version')) {
ext.support_library_version = '20.0.+'
}
if (!project.hasProperty('gms_library_version')) {
ext.gms_library_version = '8.1.0'
}
compile "com.android.support:appcompat-v7:${appcompat_library_version}"
compile "com.android.support:support-v4:${support_library_version}"
compile "com.google.android.gms:play-services-games:${gms_library_version}"
compile "com.google.android.gms:play-services-plus:${gms_library_version}"
}
android {
// Set defaults so that BaseGameUtils can be used outside of BasicSamples
if (!project.hasProperty('android_compile_version')) {
ext.android_compile_version = 23
}
if (!project.hasProperty('android_version')) {
ext.android_version = '23'
}
compileSdkVersion android_compile_version
buildToolsVersion android_version
}
... Did anyone else experience this issue before?
EDIT AS OF 4/7, 3:37PM:
So I ended up importing the project again, but within the AndroidStudioProjects directory this time (does that really make a difference?) and I actually ended up making some progress since then. However, for part 3 under step 1 within the docs:
... I ended up changing not only the package name in TypeANumber's manifest file, but also the package directory along with the classes in it as follows:
... So my question now is, am I on the right track so far in terms of the navigation directory panel at the left? :)
Yes. The package attribute in the manifest should always match the directories. Plain and simple. That's why changing it would require you to do a complete refactor. Just keep on going with the tutorial accordingly and I think you'll be good.
I'm trying to develop apps for EPSON Moverio BT-2000.
I'm new to android studio and I don't understand why I can't use some methods from a library which I have imported (correctly, I supposed).
So, I have add my lib in a folder name libs, right click on it, add as Library.
I checked in builds.gradle
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile files('libs/H725Ctrl.jar') // this lib
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:21.0.3'
}
Moreover, I can use some elements (Methods, String definitions etc..) but some not. I don't understand why and how it's possible.
If it's necessary I can publish my source code.
Have you some ideas.?
Thanks.
Franck
NB: the lib I use is depreciated by android
NB2: Exemple
Camera.Parameters params = l_pCamera.getParameters();
// I can do this and getParameters() works
List<String> Supported = params.getSupportedEpsonCameraModes();
//I can't invoke getSupportedEpsonCameraModes() or methods are in the same file
I contacted EPSON and they said it's a common problem.
So they send me a pdf which indicate how solve the problem..
It's strange..
NB the content of the PDF: sorry for the presentation but it will be helpful for someone..
1/2
Remark for using Android Studio
In case of using BT-2000 SDK with Android Studio, there may happen to have a failure during a build process. It may cause the conflict of the name between standard SDK and Epson expanded SDK. It is happened especially with “android.hardware.Camera” class.
It may resolve a failure with following action.
1. Sore H725Ctrl.jar at designated folder which is created by user like C:\Users\<user name\AndroidStudioProjects\<application name>\app\libs
2. Set change of gradle by selecting “Sync Project with Gradle Files” button which is located upper of Android Studio screen.
3. Open “build.gradle” for specified project with specified application name by selecting left side button on Android Studio screen. Then edit with following contents.
allprojects { repositories { jcenter() } gradle.projectsEvaluated { tasks.withType(JavaCompile) { options.compilerArgs.add('-Xbootclasspath/p:C:/Users/<user name>/AndroidStudioProjects/<application name>/app/libs/H725Ctrl.jar') } } }
4. Execute “Clean Project” then “Make Project” in Android Studio Build menu.
5. If error occurs in Make project process, end Android Studio and restart it.
2/2
6. There may still remain several name conflicts with Android standard API like “getSupportedEpsonCameraModes()”. Ignore and “run application” to set it into target BT-2000.
[ Caution ]
It works temporally with following action;
Open
C:\Users\<user name>\AndroidStudioProjects\<application name>\app\app.iml
Move line of
<orderEntry type="library" exported="" name="H725Ctrl" level="project" />
to upper line of
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
This will help H725Ctrl.jar to be higher priority, however performing rebuild function will affect to reset name conflict issue.
Object which is performed build function already works well.
It's weird. Epson tries to override some Android specific classes in their jar:
android.hardware.Camera
android.hardware.Camera.Parameters
These classes are part of the Android SDK (http://developer.android.com/reference/android/hardware/Camera.html). I do not know Epson would like to achieve, if they bundle the classes with their SDK. Maybe you could change the packagename in the H725Ctrl.jar to something like
com.epson.hardware
with JarJar (https://github.com/shevek/jarjar)?
Add the following code to your build.gradle file. The problem could be that the Moverio Camera class uses the same namespace as the Android sdk and there is an ordering issue
allprojects {
repositories {
jcenter()
}
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs.add('-Xbootclasspath/p:C:/Source/EPSONProBT-2000ServiceMaintenance/app/libs/H725Ctrl.jar')
}
}
}
I want to use Android Data Binding and has configured according to the official document.
the error message is :
error: cannot find symbol import net.juude.droidviews.BR;
the top level build.gradle file is:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:1.3.0-beta2"
classpath 'me.tatarka:gradle-retrolambda:3.0.1'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
classpath "com.android.databinding:dataBinder:1.0-rc0"
}
}
allprojects {
repositories {
jcenter()
mavenCentral()
}
}
and the build.gradle file in app module is
apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'
apply plugin: 'com.neenbedankt.android-apt'
apply plugin: 'com.android.databinding'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
lintOptions {
abortOnError false
}
defaultConfig {
applicationId "net.juude.droidviews"
minSdkVersion 15
targetSdkVersion 22
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
retrolambda {
println("JAVA_HOME: " + System.getenv("JAVA_HOME"))
println("JAVA7_HOME: " + System.getenv("JAVA7_HOME"))
println("JAVA8_HOME: " + System.getenv("JAVA8_HOME"))
javaVersion JavaVersion.VERSION_1_7
}
}
dependencies {
compile project(':ptr-lib-debug')
compile project(':library')
compile 'com.android.support:support-v4:22.1.0'
compile 'com.mcxiaoke.volley:library:1.0.+'
compile files('libs/droidmocks.jar')
compile 'com.android.support:support-annotations:22.1.1'
compile 'com.facebook.fresco:fresco:0.5.0'
compile 'com.android.support:recyclerview-v7:22.1.1'
compile 'io.reactivex:rxandroid:0.24.0'
compile 'io.reactivex:rxjava:1.0.6'
compile 'com.google.dagger:dagger:2.0'
apt 'com.google.dagger:dagger-compiler:2.0'
}
the layout file is
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type=" net.juude.droidviews.databinding.User" />
</data>
<LinearLayout
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{user.mName}"/>
<TextView
android:id="#+id/user_sex"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{user.sex}"/>
</LinearLayout>
</layout>
the fragment is
package net.juude.droidviews.databinding;
import android.databinding.DataBindingUtil;
import android.databinding.ViewDataBinding;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import net.juude.droidviews.BR;
import net.juude.droidviews.R;
/**
* Created by juude on 15-6-9.
*/
public class DataBindingFragment extends Fragment{
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewDataBinding dataBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_data_binding, container, false);
//dataBinding.setVariable(BR.)
User user = new User();
user.setSex("男");
user.setName("Juude");
dataBinding.setVariable(BR.user, user);
return dataBinding.getRoot();
}
}
since I did not get syntax error in Android Studio, I can assume that the Android Studio can recognize the BR class;
But when I compile the project, It tells me that
error:cannot find symbol class BR.
so I want to know what should I do to make it generate the right BR.java file?
In case someone still has this problem. I solved this by invalidating the cache in Android Studio. And I'm using Android Studio 2 with API 23
File > Invalidate Caches/Restart
It is a problem caused by android-apt plugin. It ignores the provided dependency that data binding plugin adds.
https://bitbucket.org/hvisser/android-apt/issue/38/android-apt-breaks-brand-new-data-binding#comment-18504545
You can work around it by adding:
apt 'com.android.databinding:compiler:1.0-rc0 to your gradle file.
If you are using Kotlin, try applying the following plugin to your app build.gradle file:
apply plugin: 'kotlin-kapt'
Clean your project and build it again. This solved the issue for me.
I find the cause of the problem in my case. I find in the import statements of my Data Object class contains:
import static android.databinding.tool.util.GenerationalClassUtil.ExtensionFilter.BR;
The problem gets solved after I removed that. Android Studio somehow resolved BR class wrongly for me.
The Bindable annotation generates an entry in the BR class file during compilation. The BR class file will be generated in the module package.
#Bindable
public String getFirstName() {
return this.firstName;
}
I ran into this issue too. The problem was that I changed the class name and didn't update the values in the XML file. This includes the variable names and where they are accessed in the xml file.
For my case the issue was caused by
"error: variable MyVariable was already defined in class MyModel"
The annoying thing was Android Studio gradle build did not display this error at the bottom. I had to comment each databinding error > Rebuild Project until I reach the error. Lesson learnt was to scan through each error from bottom to top and notice anything you may have changed recently.
I too got the same error message, but my root cause was different from what has been shared here.
In my case the issue was that after I resolved a merge conflict, I had by mistake left an extra #Override annotation on a method. Thus the JVM preprocessor failed and then also the data binding classes were not generated.
The irritating part for me was that I was unable to see any error message related to this, or it was hard to spot among all the other compiler errors. And Android Studio does not show the extra annotation as an error either. So in case someone else struggles with the same error, check that you don't haven an error in some annotation that prevents the APT preprocessor from kicking in.
You need to add this to your gradle.properties file
android.databinding.enableV2=true
From developer.android.com
you might get multiple errors reporting that the binding classes aren't found. The new data binding compiler prevents these errors by generating the binding classes before the managed compiler builds your app.
Just restarting Android Studio, without invalidating cache, did the trick for me (I'm using version 2.2.3).
I had this plus 29 other errors suddenly crop up from one moment to the next. I tried clean, rebuild, invalidate caches / restart and no luck. In the end I removed changes I had made and redid them one by one. Found that I had #Injected a service in the wrong class. Once I removed that all 30 errors were gone. The errors gave no clue to what I had done wrong.
If you use Android Studio 2.3 release and your project configuration is as follow:
Gradle version: 3.3
Android plugin version:2.3.0
Compile sdk Version:23+
build tools Version:25+
All need to do is add
dataBinding{enabled=true}
to build.gradle, then sync gradle file.
For me it helped to run ./gradlew clean build in the project folder. It showed an error which android studio didn't.
Generally BR class Generate automatically when you Rebuild your project and I have resolved the problem using this technique Still have issue you can try another solution.
You need to double-check the following steps:
GradleFile:
dataBinding {enabled = true}
Your class Model.
import androidx.databinding.BaseObservable
import androidx.databinding.Bindable
import androidx.databinding.library.baseAdapters.BR
class User2(
private var firstName: String,
private var lastName: String
) : BaseObservable() {
fun setFirstName(firstName: String) {
this.firstName = firstName
notifyPropertyChanged(BR.firstName)
}
#Bindable
fun getFirstName(): String {
return this.firstName
}
}
If you are using Dagger 2, the problem may be caused by dagger's components. Although two libraries are not related, in my case, fixing errors in Dagger reported in the compiler makes the BR class properly appear again.
BR gets generated during compilation, Build -> Rebuild project should do the trick. But for me it failed with error:
e:/home/xx/File.kt: (24, 46): Expecting an element because on that line I had an incompleted BR.. Just commenting or adding anything after . and rebuilding solved it.
Just follow the steps below,
1.Extend your class with BaseObservable class
2.Add #Bindable annotation to each getter methods.
3.Rebuild the project.
Now you'll be able to access BR
In my case, I tried just running the project and it fixed the issue.
Add dependency
implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"
Then sync project. Even if not works, invalidate cache and restart then clean & rebuild project.
In my case i haven't provided #PrimaryKey annotation on one of the entity and it was really difficult to find this error as in logs there are no clue to find it. so be sure to give your Entity a primary key, else this error occurs.
Check your room database related file, because of that class gradle build get failed, and will not get idea actually. issue is in room classes.
what ever androidx.databinding.library.baseAdapters.BR error your getting those file is not generating because of room database class have some syntax error
I have seen various versions of the dex erros before, but this one is new. clean/restart etc won't help. Library projects seems intact and dependency seems to be linked correctly.
Unable to execute dex: method ID not in [0, 0xffff]: 65536
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536
or
Cannot merge new index 65950 into a non-jumbo instruction
or
java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
tl;dr: Official solution from Google is finally here!
http://developer.android.com/tools/building/multidex.html
Only one small tip, you will likely need to do this to prevent out of memory when doing dex-ing.
dexOptions {
javaMaxHeapSize "4g"
}
There's also a jumbo mode that can fix this in a less reliable way:
dexOptions {
jumboMode true
}
Update: If your app is fat and you have too many methods inside your main app, you may need to re-org your app as per
http://blog.osom.info/2014/12/too-many-methods-in-main-dex.html
Update 3 (11/3/2014)
Google finally released official description.
Update 2 (10/31/2014)
Gradle plugin v0.14.0 for Android adds support for multi-dex. To enable, you just have to declare it in build.gradle:
android {
defaultConfig {
...
multiDexEnabled true
}
}
If your application supports Android prior to 5.0 (that is, if your minSdkVersion is 20 or below) you also have to dynamically patch the application ClassLoader, so it will be able to load classes from secondary dexes. Fortunately, there's a library that does that for you. Add it to your app's dependencies:
dependencies {
...
compile 'com.android.support:multidex:1.0.0'
}
You need to call the ClassLoader patch code as soon as possible. MultiDexApplication class's documentation suggests three ways to do that (pick one of them, one that's most convenient for you):
1 - Declare MultiDexApplication class as the application in your AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.multidex.myapplication">
<application
...
android:name="android.support.multidex.MultiDexApplication">
...
</application>
</manifest>
2 - Have your Application class extend MultiDexApplication class:
public class MyApplication extends MultiDexApplication { .. }
3 - Call MultiDex#install from your Application#attachBaseContext method:
public class MyApplication {
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
....
}
....
}
Update 1 (10/17/2014):
As anticipated, multidex support is shipped in revision 21 of Android Support Library. You can find the android-support-multidex.jar in /sdk/extras/android/support/multidex/library/libs folder.
Multi-dex support solves this problem. dx 1.8 already allows generating several dex files.
Android L will support multi-dex natively, and next revision of support library is going to cover older releases back to API 4.
It was stated in this Android Developers Backstage podcast episode by Anwar Ghuloum. I've posted a transcript (and general multi-dex explanation) of the relevant part.
As already stated, you have too many methods (more than 65k) in your project and libs.
Prevent the Problem: Reduce the number of methods with Play Services 6.5+ and support-v4 24.2+
Since often the Google Play services is one of the main suspects in "wasting" methods with its 20k+ methods. Google Play services version 6.5 or later, it is possible for you to include Google Play services in your application using a number of smaller client libraries. For example, if you only need GCM and maps you can choose to use these dependencies only:
dependencies {
compile 'com.google.android.gms:play-services-base:6.5.+'
compile 'com.google.android.gms:play-services-maps:6.5.+'
}
The full list of sub libraries and it's responsibilities can be found in the official google doc.
Update: Since Support Library v4 v24.2.0 it was split up into the following modules:
support-compat, support-core-utils, support-core-ui, support-media-compat and support-fragment
dependencies {
compile 'com.android.support:support-fragment:24.2.+'
}
Do note however, if you use support-fragment, it will have dependencies to all the other modules (ie. if you use android.support.v4.app.Fragment there is no benefit)
See here the official release notes for support-v4 lib
Enable MultiDexing
Since Lollipop (aka build tools 21+) it is very easy to handle. The approach is to work around the 65k methods per dex file problem to create multiple dex files for your app. Add the following to your gradle build file (this is taken from the official google doc on applications with more than 65k methods):
android {
compileSdkVersion 21
buildToolsVersion "21.1.0"
defaultConfig {
...
// Enabling multidex support.
multiDexEnabled true
}
...
}
dependencies {
compile 'com.android.support:multidex:1.0.1'
}
The second step is to either prepare your Application class or if you don't extend Application use the MultiDexApplication in your Android Manifest:
Either add this to your Application.java
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
or use the provided application from the mutlidex lib
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.myapplication">
<application
...
android:name="android.support.multidex.MultiDexApplication">
...
</application>
</manifest>
Prevent OutOfMemory with MultiDex
As further tip, if you run into OutOfMemory exceptions during the build phase you could enlarge the heap with
android {
...
dexOptions {
javaMaxHeapSize "4g"
}
}
which would set the heap to 4 gigabytes.
See this question for more detail on the dex heap memory issue.
Analyze the source of the Problem
To analyze the source of the methods the gradle plugin https://github.com/KeepSafe/dexcount-gradle-plugin can help in combination with the dependency tree provided by gradle with e.g.
.\gradlew app:dependencies
See this answer and question for more information on method count in android
Your project is too large. You have too many methods. There can only be 65536 methods per application. see here https://code.google.com/p/android/issues/detail?id=7147#c6
The below code helps, if you use Gradle. Allows you to easily remove unneeded Google services (presuming you're using them) to get back below the 65k threshold. All credit to this post: https://gist.github.com/dmarcato/d7c91b94214acd936e42
Edit 2014-10-22: There's been a lot of interesting discussion on the gist referenced above. TLDR? look at this one: https://gist.github.com/Takhion/10a37046b9e6d259bb31
Paste this code at the bottom of your build.gradle file and adjust the list of google services you do not need:
def toCamelCase(String string) {
String result = ""
string.findAll("[^\\W]+") { String word ->
result += word.capitalize()
}
return result
}
afterEvaluate { project ->
Configuration runtimeConfiguration = project.configurations.getByName('compile')
ResolutionResult resolution = runtimeConfiguration.incoming.resolutionResult
// Forces resolve of configuration
ModuleVersionIdentifier module = resolution.getAllComponents().find { it.moduleVersion.name.equals("play-services") }.moduleVersion
String prepareTaskName = "prepare${toCamelCase("${module.group} ${module.name} ${module.version}")}Library"
File playServiceRootFolder = project.tasks.find { it.name.equals(prepareTaskName) }.explodedDir
Task stripPlayServices = project.tasks.create(name: 'stripPlayServices', group: "Strip") {
inputs.files new File(playServiceRootFolder, "classes.jar")
outputs.dir playServiceRootFolder
description 'Strip useless packages from Google Play Services library to avoid reaching dex limit'
doLast {
copy {
from(file(new File(playServiceRootFolder, "classes.jar")))
into(file(playServiceRootFolder))
rename { fileName ->
fileName = "classes_orig.jar"
}
}
tasks.create(name: "stripPlayServices" + module.version, type: Jar) {
destinationDir = playServiceRootFolder
archiveName = "classes.jar"
from(zipTree(new File(playServiceRootFolder, "classes_orig.jar"))) {
exclude "com/google/ads/**"
exclude "com/google/android/gms/analytics/**"
exclude "com/google/android/gms/games/**"
exclude "com/google/android/gms/plus/**"
exclude "com/google/android/gms/drive/**"
exclude "com/google/android/gms/ads/**"
}
}.execute()
delete file(new File(playServiceRootFolder, "classes_orig.jar"))
}
}
project.tasks.findAll { it.name.startsWith('prepare') && it.name.endsWith('Dependencies') }.each { Task task ->
task.dependsOn stripPlayServices
}
}
I've shared a sample project which solve this problem using custom_rules.xml build script and a few lines of code.
I used it on my own project and it is runs flawless on 1M+ devices (from android-8 to the latest android-19). Hope it helps.
https://github.com/mmin18/Dex65536
Faced the same problem and solved it by editing my build.gradle file on the dependencies section, removing:
compile 'com.google.android.gms:play-services:7.8.0'
And replacing it with:
compile 'com.google.android.gms:play-services-location:7.8.0'
compile 'com.google.android.gms:play-services-analytics:7.8.0'
Try adding below code in build.gradle, it worked for me -
compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
multiDexEnabled true
}
The perfect solution for this would be to work with Proguard. as aleb mentioned in the comment.
It will decrease the size of the dex file by half.
You can analyse problem (dex file references) using Android Studio:
Build -> Analyse APK ..
On the result panel click on classes.dex file
And you'll see:
gradle + proguard solution:
afterEvaluate {
tasks.each {
if (it.name.startsWith('proguard')) {
it.getInJarFilters().each { filter ->
if (filter && filter['filter']) {
filter['filter'] = filter['filter'] +
',!.readme' +
',!META-INF/LICENSE' +
',!META-INF/LICENSE.txt' +
',!META-INF/NOTICE' +
',!META-INF/NOTICE.txt' +
',!com/google/android/gms/ads/**' +
',!com/google/android/gms/cast/**' +
',!com/google/android/gms/games/**' +
',!com/google/android/gms/drive/**' +
',!com/google/android/gms/wallet/**' +
',!com/google/android/gms/wearable/**' +
',!com/google/android/gms/plus/**' +
',!com/google/android/gms/topmanager/**'
}
}
}
}
}
Remove some jar file from Libs folder and copy to some other folder, And Go to _Project Properties > Select Java Build Path, Select Libraries, Select Add External Jar, Select the Removed jar to your project, Click save, this will be added under Referenced Library instead of Libs folder. Now clean and Run your project. You dont need to add Any code for MultDex. Its simply worked for me.
I was facing the same issue today what worked for is below down
For ANDROID STUDIO... Enable Instant Run
In File->Preferences->Build, Execution, Deployment->Instant Run-> Check Enable Instant run for hot swap...
Hope it helps