11

My team and I develop Android apps and have decided on coding guidelines that all should follow. I therefore started implementing custom lint rules which can be found here, and have added it to our automated build process in Jenkins.

The problem we are now having is that these rules no longer work after upgrading our Android projects from
'com.android.tools.build:gradle:2.2.0' to 'com.android.tools.build:gradle:2.3.0'

We continually get the error: java.lang.NoSuchMethodError: com.android.tools.lint.detector.api.JavaContext.getContents()Ljava/lang/String;

When switching back to gradle 2.2.0 all is fine, the custom rules are checked and the app builds.

I tried updating gradle in the lint repository and unfortunately have the exact same issue in my TodoDetector at line 72. In Android studio all dependencies are resolved fine, but when trying to build and deploy the library with ./gradlew clean build test install, We get the error listed above.

I've been searching all day and have yet to find a viable solution for this problem. Any help, tips or advice is greatly appreciated.

Terminal output

:clean
:aarWrapper:clean
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses
:test
:check
:build
:aarWrapper:preBuild UP-TO-DATE
:aarWrapper:preDebugBuild UP-TO-DATE
:aarWrapper:checkDebugManifest
:aarWrapper:prepareDebugDependencies
:aarWrapper:compileDebugAidl
:aarWrapper:compileDebugNdk UP-TO-DATE
:aarWrapper:compileLint
:aarWrapper:copyDebugLint UP-TO-DATE
:aarWrapper:mergeDebugShaders
:aarWrapper:compileDebugShaders
:aarWrapper:generateDebugAssets
:aarWrapper:mergeDebugAssets
:aarWrapper:mergeDebugProguardFiles UP-TO-DATE
:aarWrapper:packageDebugRenderscript UP-TO-DATE
:aarWrapper:compileDebugRenderscript
:aarWrapper:generateDebugResValues
:aarWrapper:generateDebugResources
:aarWrapper:packageDebugResources
:aarWrapper:processDebugManifest
:aarWrapper:generateDebugBuildConfig
:aarWrapper:processDebugResources
:aarWrapper:generateDebugSources
:aarWrapper:incrementalDebugJavaCompilationSafeguard
:aarWrapper:javaPreCompileDebug
:aarWrapper:compileDebugJavaWithJavac
:aarWrapper:processDebugJavaRes UP-TO-DATE
:aarWrapper:transformResourcesWithMergeJavaResForDebug
:aarWrapper:transformClassesAndResourcesWithSyncLibJarsForDebug
:aarWrapper:mergeDebugJniLibFolders
:aarWrapper:transformNativeLibsWithMergeJniLibsForDebug
:aarWrapper:transformNativeLibsWithStripDebugSymbolForDebug
:aarWrapper:transformNativeLibsWithSyncJniLibsForDebug
:aarWrapper:bundleDebug
:aarWrapper:compileDebugSources
:aarWrapper:assembleDebug
:aarWrapper:preReleaseBuild UP-TO-DATE
:aarWrapper:checkReleaseManifest
:aarWrapper:prepareReleaseDependencies
:aarWrapper:compileReleaseAidl
:aarWrapper:compileReleaseNdk UP-TO-DATE
:aarWrapper:copyReleaseLint UP-TO-DATE
:aarWrapper:mergeReleaseShaders
:aarWrapper:compileReleaseShaders
:aarWrapper:generateReleaseAssets
:aarWrapper:mergeReleaseAssets
:aarWrapper:mergeReleaseProguardFiles UP-TO-DATE
:aarWrapper:packageReleaseRenderscript UP-TO-DATE
:aarWrapper:compileReleaseRenderscript
:aarWrapper:generateReleaseResValues
:aarWrapper:generateReleaseResources
:aarWrapper:packageReleaseResources
:aarWrapper:processReleaseManifest
:aarWrapper:generateReleaseBuildConfig
:aarWrapper:processReleaseResources
:aarWrapper:generateReleaseSources
:aarWrapper:incrementalReleaseJavaCompilationSafeguard
:aarWrapper:javaPreCompileRelease
:aarWrapper:compileReleaseJavaWithJavac
:aarWrapper:processReleaseJavaRes UP-TO-DATE
:aarWrapper:transformResourcesWithMergeJavaResForRelease
:aarWrapper:transformClassesAndResourcesWithSyncLibJarsForRelease
:aarWrapper:mergeReleaseJniLibFolders
:aarWrapper:transformNativeLibsWithMergeJniLibsForRelease
:aarWrapper:transformNativeLibsWithStripDebugSymbolForRelease
:aarWrapper:transformNativeLibsWithSyncJniLibsForRelease
:aarWrapper:bundleRelease
:aarWrapper:compileReleaseSources
:aarWrapper:assembleRelease
:aarWrapper:assemble
:aarWrapper:lint FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':aarWrapper:lint'.
> com.android.tools.lint.detector.api.JavaContext.getContents()Ljava/lang/String;

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

gradle file

apply plugin: 'java'

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.0'
    }
}

repositories {
    jcenter()
}

allprojects {
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
}

dependencies {
    compile 'com.android.tools.lint:lint:24.3.1'
    compile 'com.android.tools.lint:lint-api:24.3.1'
    compile 'com.android.tools.lint:lint-checks:24.3.1'
    testCompile 'junit:junit:4.11'
    testCompile 'org.assertj:assertj-core:3.0.0'
    testCompile 'org.mockito:mockito-core:1.9.5'
    testCompile 'com.android.tools.lint:lint:24.3.1'
    testCompile 'com.android.tools.lint:lint-tests:24.3.1'
    testCompile 'com.android.tools:testutils:24.3.1'
}

jar {
    baseName 'com.bignerdranch.linette'
    version '1.0'

    manifest {
        attributes 'Manifest-Version': 1.0
        attributes('Lint-Registry': 'com.bignerdranch.linette.registry.CustomIssueRegistry')
    }
}

sourceSets {
    main {
        java {
            srcDirs = ["lint/src/main/java"]
        }
    }
    test {
        java {
            srcDirs = ["lint/src/test/java"]
        }
    }
}

configurations {
    lintChecks
}

dependencies {
    lintChecks files(jar)
}

defaultTasks 'assemble'

task install(type: Copy) {
    from configurations.lintChecks
    into System.getProperty('user.home') + '/.android/lint/'
}

aarWrapper gradle

apply plugin: 'com.android.library'

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.0'
    }
}

android {

    compileSdkVersion 25
    buildToolsVersion '25.0.2'

    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 25
        versionCode 1
        versionName '1.0'
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

project.afterEvaluate {
    def compileLint = project.tasks.getByPath(':aarWrapper:compileLint')
    compileLint.dependsOn parent.tasks.getByName("jar")
    compileLint << {
        copy {
            from '../build/libs'
            into 'build/intermediates/lint'
        }
    }
}
hopeman
  • 2,778
  • 3
  • 18
  • 33
  • Did you tried rebuild your project and run after disabling instant run? – pRaNaY Mar 13 '17 at 11:13
  • @pRaNaY I currently am not a big fan of instant run and have it deactivated. Unfortunately the problem still exists. – hopeman Mar 13 '17 at 12:11

5 Answers5

1

If your deactivation of instant run not works then add it on your build.gradle file.

android {
    lintOptions {
        // if true, stop the gradle build if errors are found
        abortOnError false
    }
}

Then clean your project and run.

if abortOnError false not resolve your issue, then you can try the following

lintOptions {
    checkReleaseBuilds false
}

Hope it will solve your issue.

Resource Link:

  1. https://android.googlesource.com/platform/tools/base/+/e6a5b9c7c1bca4da402de442315b5ff1ada819c7
  2. gradle build fails on lint task
Community
  • 1
  • 1
SkyWalker
  • 28,384
  • 14
  • 74
  • 132
1

I was trying out the same code and bumped into the same issue.

There are new versions available for com.android.tools.lint. Try 25.2.0 or above, and you will notice that the example code TodoDetector uses deprecated methods.

Basically, you need to make your class implement Detector.JavaPsiScanner instead of Detector.JavaScanner.

http://static.javadoc.io/com.android.tools.lint/lint-api/25.3.0/com/android/tools/lint/detector/api/Detector.JavaPsiScanner.html

Ryuichi
  • 11
  • 2
  • Thanks for your reply, I have updated to `'com.android.tools.lint:lint:25.2.0'` and replaced the `Detector.JavaScanner` with `Detector.JavaPsiScanner`. Unfortunately, I still have the same error message. The only difference however is that it now references the new method `createPsiVisitor` – hopeman Mar 16 '17 at 09:54
0

Daniel Passos has given a solution here in this tutorial

Ignoring Erros

Lint is part of Gradle build process, by default if it fail your build will stop and you will get a message like it:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:lint'.
> Lint found errors in the project; aborting build.

In 99% of the cases people will start ignore lint instead of fix the problems, adding this on build.gradle app

lintOptions {   
    abortOnError false   
} 

But IMHO it’s wrong. If lint is telling, you have a problem the best thing to do is fix it. Lint is a tools to make your app and the UX better.

Ignoring specific erros

Sometimes you really need to ignore some lint errors. For example, when you are using webView.getSettings().setJavaScriptEnabled(true); in your WebView

In this case, you should disable only the specific ids instead of disabling the whole lint.

lintOptions {
    disable 'SetJavaScriptEnabled'
}

You also can ignore it directly in your code:

@SuppressLint "SetJavaScriptEnabled")

Or in your XML

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:ignore="SomeLintIssueIdHere" >

If you prefer you can move all your issues rules from a lint.xml file in the root directory of your project.

<?xml version="1.0" encoding="UTF-8"?>
<lint>
    <issue id="SetJavaScriptEnabled" severity="ignore" />
</lint>
SkyWalker
  • 28,384
  • 14
  • 74
  • 132
  • Thanks for your replay, however neither of your answers solves my problem. In our custom linting project, I can no longer build the tests after changing 'com.android.tools.build:gradle:2.2.0' to 'com.android.tools.build:gradle:2.3.0'. Changing the linting options is not a viable solution. Your more than welcome to look into the code repository found [here](https://github.com/apertomove/linette) – hopeman Mar 13 '17 at 14:53
0

I had the same error when migrating to Android Gradle plugin 2.3.0 com.android.tools.build:gradle:2.3.0. The problem in my case was that the android-apt plugin that I used has become deprecated: Android Gradle plugin 2.3.0 has annotation processing out of the box and seems to block android-apt.

Read the migration guide and migrate the "apt" section of your gradle build script and "apt" dependencies, then remove the android-apt plugin: https://bitbucket.org/hvisser/android-apt/wiki/Migration

UPD: The problem was still there after the fix above. I looked into the error stacktrace in Event Log and found out that the exception happens in one of my custom lint checkers (io.vokal.lint:todo:1.0.3). Removing it from ~/.android/lint solved the problem.

  • Hey thanks for your reply, we don't have android-apt in our gradle script... I also removed the rules from `~/.android/lint` but still have the problem described above. – hopeman Apr 20 '17 at 07:26
0

I encountered the same issue. Looking into context.getContents():

return mDriver.getClient().readFile(file);

So i tried to do it manually like this: context.getDriver().getClient().readFile(context.file) which throws the same error message.

My workaround now is, instead of using context.getContents() i just use context.file and read it out without the driver. I am not sure if this is a good way but for me it works.

So here the working code:

static void someMethod(com.android.tools.lint.detector.api.Context context){
    readFile(context.file)
    ...
}

static String readFile(File file) {
    String path = file.getAbsolutePath();
    Charset encoding = Charset.defaultCharset();
    try {
        byte[] encoded = Files.readAllBytes(Paths.get(path));
        return new String(encoded, encoding);

    } catch (IOException e){
        return "";
    }
}
Leonard Arnold
  • 646
  • 3
  • 14