MockContentResolver is not found in an Android Test project with separate module - android

I'm trying to setup a test project like is described in the Android Testing Blueprint but I receive the following NoClassDefFoundError:
java.lang.NoClassDefFoundError: android.test.mock.MockContentResolver
Android Studio resolves this correctly but when running I receive this error.
It's worth to note that I do not have an androidTest configuration on the app project, instead I only have a separate tests module with:
apply plugin: 'com.android.test'
I'm running tests like this:
./gradlew :tests:connectedAndroidTest
Test project to reproduce this issue can be found here:
https://github.com/vexdev/android-testing-templates/tree/master/AndroidTestingBlueprint
EDIT: Also asked on Android Development community
EDIT: Also created following android issue:
https://code.google.com/p/android/issues/detail?id=200182&thanks=200182&ts=1454489567

As #rds said, test package is not part of the framework on the device, therefore you need to include the package.
Seems like com.android.test plugin is not adding those classes, so you can fix it by adding
compile 'com.google.android:android-test:4.1.1.4'
in your dependencies for the module where you are applying the plugin.

Some android packages are not automatically linked, but you have to explicitly specify them using the <uses-library> tag. That is the case with the android.test package (see uses-library docs), like #rds mentioned.
Adding a compile dependency will work if you have minSdkVersion > =15, but will add a legacy Maven artifact that has been updated on the Aug 24, 2012 for the last time.
IMHO, it might be a better solution to add the following snippet to the manifest of the test module:
<application>
<uses-library android:name="android.test.runner" />
</application>
This will tell the system to include the android.test package as well, so the MockContentResolver will be found by the class loader.
Hope it helps.

The MockContentProvider is not part of the framework, it's only shipped in the SDK for test apks.
In your Android Studio project, you must store the source files for local unit tests under a specific source directory (src/test/java)

Related

How to access LibraryExtension in custom gradle plugin

I would like to write a custom gradle plugin that manipulates either com.android.build.gradle.AppExtension or com.android.build.gradle.LibraryExtension. The basic form of the plugin is:
class AndroidLibrary : Plugin<Project> {
override fun apply(project: Project) {
var lib: LibraryExtension = project.extensions.getByName("android") as LibraryExtension
lib.minSdkVersion = "26"
}
}
The problem is that the class LibraryExtension cannot be resolved. That class is contained in "com.android.tools.build:gradle:7.1.2". Note, there is no problem accessing either of these classes in a gradle.build.kts script file. I just can't access either of those classes from within a custom plugin like seen above. I've tried adding a dependency to com.android.tools.build.gradle 7.1.2 in the build script, but that doesn't work. I also tried adding it as a buildscript dependency, and that didn't help either. I also got the
com.android.tools.build:gradle jar file and added it as a dependency, but that too didn't work.
It seems to me to be reasonable to expect a custom plugin of being able to manipulate the android build settings but I just can't find a way to resolve either LibraryExtension or AppExtension from within the custom plugin project.
If someone knows what I need to do to resolve those two classes, that would be greatly appreciated. I'm currently under the impression, that this is an architectural limitation of with android's gradle plugin and that I really can't access the "android" build section using LibraryExtension or AppExtension from a custom plugin and dsl. If that is the case, that too would be useful to know.
check this answer for your question, it is gonna solve your problem.
Initially I was building the plugin using IDEA. I could build the project by using a "gradlew build" command. I noticed that I would get the following message whenever I tried to sync the project:
This version of the Android Support plugin for IntelliJ IDEA (or Android Studio) cannot open this project, please retry with version 2020.1.1 or newer
I had been ignoring that issue since I could successfully build the project using gradle commands. Here's a link the explains what the message means: https://intellij-support.jetbrains.com/hc/en-us/community/posts/4405168877202-This-version-of-the-Android-Support-plugin-for-IntelliJ-IDEA-or-Android-Studio-cannot-open-this-project-please-retry-with-version-2020-3-1-or-newer-
One of the suggestions to this problem was to build the project in Android Studio instead of waiting for IDEA to incorporate later android build. I did that and that indeed fixed that issue. The additional side effect was that I could now build the plugin. I was able to add dependencies for both gradleApi and to com.android.build.gradle and was able to resolve AppExtension of LibraryExtension. I had added the same dependencies I when I was using IDEA IDE. I had been customarily building my custom gradle plugin using IDEA. This was my first custom gradle plugin that I was going to manipulate an "android" build configuration.

Issue with DJI SDK gradle 4.4.0, provided keyword in gradle not working

Previously my gradle used to look like this and worked fine (apart from few registered bugs)
implementation 'com.dji:dji-sdk:4.3.2'
Now, after changing to
implementation 'com.dji:dji-sdk:4.4.0'
the Camera and other files cannot be recognized anymore. I am attaching a screenshot of the unrecognized imports.
However when I am trying to add
//dji-drones-sdk
implementation 'com.dji:dji-sdk:4.4.0'
provided 'com.dji:dji-sdk-provided:4.4.0'
I am getting "could not download dji-sdk-provided.jar"
Screenshot attached
All the examples and github codes are in version 4.3.2. Can anyone help me out?
Here is the link to the dji sdk
I have found the issue. After Gradle 3.4, the "provided" is replaced by "compileOnly"
I quote,
Gradle adds the dependency to the compilation classpath only (it is not added to the build output). This is useful when you're creating an Android library module and you need the dependency during compilation, but it's optional to have present at runtime. That is, if you use this configuration, then your library module must include a runtime condition to check whether the dependency is available, and then gracefully change its behavior so it can still function if it's not provided. This helps reduce the size of the final APK by not adding transient dependencies that aren't critical. This configuration behaves just like provided (which is now deprecated).
Hence using compileOnly in place of provided will do the trick.
Here is a link to the gradle changes documentation

Build error with Android Studio 3.0 Canary 4

I am currently in the process of developing an Instant app, for which I have restructured my monolithic app into feature modules.
Everything was up and running till Android Studio canary 3, but after an update to Android Studio Canary 4 my project fails to build with the following error:
A problem was found with the configuration of task ':minimoBase:dataBindingExportBuildInfoDebugAndroidTest'.
> Directory '/Users/nayak.vishal/projectData/minimo_instant_app_project/putica-client-android-
native/minimoBase/build/intermediates/data-binding-info/androidTest/debug'
specified for property 'xmlOutFolder' does not exist.
The following procedure worked as a workaround for this issue:
Execute the following build commands on the gradle command line
1) gradlew clean
2) gradlew :appModule:assembleDebug
here appModule is the name of the app module for building the installable apk
the build is successful and the debug apk generated in the output folder can be installed successfully
3) gradlew :instantAppModule:assembleDebug
here instantAppModule is the name of the instant app module
the build is successful and the instant app apks can be installed and launched via deep link
Once the above command line builds are successful, building via Android Studio Canary 4 also stops throwing the build error.
I got similar error when I turn on data-binding for library module. When I turn it off and move all classes that require data-binding to app module, it works. So I guess there is a problem that DataBinding doesn't work on Library module any more ( Gradle 2.x fine with this).
dataBinding {
enabled = false
}
I am using com.android.tools.build:gradle:3.0.0-alpha5 and Android Studio 3.0 Preview Canary5
UPDATE
Although the original answer worked, I really want to turn on data-binding on my library module, where I implement some base classes using binding technique. I move them back to library module and upgrade kotlin version to the latest one 1.1.3-2. Suddenly it works also. I am not sure which one is the better but both ways work for me.
UPDATE 2
I am using com.android.tools.build:gradle:3.0.0-alpha9 and kotlin 1.1.3-2 at this time and suddenly the problem re-appear.
Now I think the problem doesn't come from Kotlin. My library module turned dataBiding { enabled=true}, but it doesn't have any layout file. I tried to create a fake layout file wrapped by <layout> tag and it works
<?xml version="1.0" encoding="utf-8"?>
<layout>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</layout>
In your gradle.properties file , add the following line
android.enableAapt2=false
Recent versions of AS3.0 switched to using AAPT2 by default.
You can disable AAPT2 in your gradle.propertіes fіle with above mentioned line of code, and continue developing on AS3 canary 4.
This was an issue for me when I had a "base" feature module without any layouts (all my actual layouts are in separate features)
Adding a dummy layout XML file in the base feature (e.g. as base/src/res/layout/dummy.xml) meant the missing directory was created and the app compiled.
(this is using com.android.tools.build:gradle:3.0.0-alpha6)
I've had the same problem, seems like a bug in Canary 4.
For now, as a workaround, I downgraded to Android Studio 3.0.0 Canary 3 (This is an archive of all Android Studio releases) and also downgraded the Android Gradle plugin to 3.0.0-alpha3:
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alpha3'
...
}
Updated:
Just check the Canary version after update. For that see Android Studio version just above the toolbar (File..Edit..View..line) where name at end like "Canary X".-> X is number like 3,4,5,etc.
For example suppose updated version(X) is 5.
Try to change that classpath in build.gradle(applicationName) to 3.0.0-alpha5 and sync(/Try) again:
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alpha5'
}
Means that updated version(X):-
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alphaX'
}

Android gradle JAR dependency ends up declared as native

In my Android projects build.gradle file I have:
dependencies {
compile 'org.apache.directory.studio:org.apache.commons.io:2.4'
compile 'org.apache.commons:commons-collections4:4.0'
}
When I run aapt dump badging I see:
native-code: 'commons-io-2.4.jar'
Clearly commons-io is not native code but the Android Gradle plugin thinks it is. How can I tell the Android Gradle plugin this library does not contain native code? Also curious how did it decide what architecture this library is? It seems to have picked some variety of arm since the APK won't install on a intel-based Android emulator, it gives the error: INSTALL_FAILED_CPU_ABI_INCOMPATIBLE.
You may be using the incorrect Commons IO library. Try:
http://mvnrepository.com/artifact/commons-io/commons-io/2.4
The version you're using seems to be specific to Apache Directory Studio 2.4 which seems to be a desktop app.
I once had troubles introducing a dependency on commons-io:2.4 into my build code. The problem is that Gradle itself comes with a version of commons-io. In my case it could be fixed with this:
sourceSets {
main {
compileClasspath = configurations.compile.minus files("$gradle.gradleHomeDir/lib/commons-io-1.4.jar")
}
}
I took this snippet from My Gradle project depends on commons-io 2.4, but Gradle puts $GRADLE_HOME/commons-io-1.4.jar into the classpath, causing failures
But be aware that it is not recommended to use different versions of libraries to come with Gradle.
You can find more information about this here: https://discuss.gradle.org/t/unable-to-use-commons-io-2-4-because-gradle-forces-the-loading-of-commons-io-1-4/8021
This might aswell be completely unrelated :)

Mockito + Dexmaker on Android

I am trying to use Mockito in my Android project.
I have found very nice tutorial that deals with it: http://www.paulbutcher.com/2012/05/mockito-on-android-step-by-step/
Basically it uses new version of Mockito + Dexmaker and everything works as expected.
However, when I try to mock some Android specific object i.e:
Context context = mock(Context.class);
I receive this exception:
java.lang.IllegalArgumentException:
dexcache == null (and no default could be found;
consider setting the 'dexmaker.dexcache' system property)
at com.google.dexmaker.DexMaker.generateAndLoad(DexMaker.java:359)
at com.google.dexmaker.stock.ProxyBuilder.buildProxyClass(ProxyBuilder.java:252)
at com.google.dexmaker.mockito.DexmakerMockMaker.createMock(DexmakerMockMaker.java:54)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26)
Any idea how to fix it?
From #rjath's comment of #MrChaz's answer, this works better for me:
System.setProperty(
"dexmaker.dexcache",
getInstrumentation().getTargetContext().getCacheDir().getPath());
I put it in my setUp() method.
I've managed to piece together a fix that seems to be working for me.
To the manifest I added read and write external storage.
To the test I added System.setProperty("dexmaker.dexcache", "/sdcard"); to the test.
To the emulator image I added an SD card.
I believe this works because by default mockito tries to use the apps cache directory but I never run an activity so I suspect the directory is never created by the OS
So the problem is with Dexmaker not being able to find the cache path on Android >= 4.3 as other people mentioned and as described in this dexmaker issue.
I went with implementing the workaround in a custom instrumented test runner instead of in every test (or their superclass) setUp(), because it feels a bit less hacky (it really is in only one place - and not inherited in every subclass) and more flexible.
For the sake of documentation these are the necessary changes to do this:
public class CustomInstrumentationTestRunner extends InstrumentationTestRunner {
#Override public void onCreate (final Bundle arguments) {
super.onCreate(arguments);
// temporary workaround for an incompatibility in current dexmaker (1.1) implementation and Android >= 4.3
// cf. https://code.google.com/p/dexmaker/issues/detail?id=2 for details
System.setProperty("dexmaker.dexcache", getTargetContext().getCacheDir().toString());
}
}
And set up your project (or test project) to use this class as the instrumented test runner in its AndroidManifest.xml when building with ant:
<instrumentation
android:name="my.package.CustomInstrumentationTestRunner"
android:targetPackage="my.target.package" />
or its build.gradle when building with gradle:
android {
defaultConfig {
// ...
testInstrumentationRunner 'my.package.CustomInstrumentationTestRunner'
}
// ...
}
If you have other instrumentation entries, you can switch between them either on the command line or select one in your IDE running configuration.
I had this issue for an Android Library project but NOT for the application project! Setting the System property "dexmaker.dexcache" as mentioned above worked around the issue.
I'm running Android 4.3 Nexus 4 device, building with 19.0.3 tools, target api 19,
my dependencies:
androidTestCompile "org.mockito:mockito-core:1.9.5"
androidTestCompile "com.google.dexmaker:dexmaker:1.0"
androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.0"
It looks like the dexmaker project has moved from Google Code to GitHub.
In the maven central repository there are versions 1.1 and 1.2 published in March 2014 and December 2014.
I've verified this "dexcache == null" issue still exists through version 1.2 - but only on certain devices. For example, a Galaxy S5 with Android 5.0 has the problem, and a Galaxy S4 with Android 4.4.2 does not.
I cloned the GitHub repository (last commit March 12th 2015 - ca74669), and ran locally, and the problem has been fixed (there are also commits in the history that back this up). So once there is a 1.3 release, hopefully this problem is gone for good!
Anyone else wanting to run a local copy of 1.3-SNAPSHOT, here's how I did that (on a Mac, but other platforms should work too, you'll need mvn, adb, and dx on PATH):
git clonehttps://github.com/crittercism/dexmaker.git
cd dexmaker
mvn install -Dmaven.test.skip=true
cp -R ~/.m2/repository/com/google/dexmaker $ANDROID_HOME/extras/android/m2repository/com/google
Then change version in app/build.gradle: androidTestCompile 'com.google.dexmaker:dexmaker:1.3-SNAPSHOT'
Or pom.xml if using maven to build, or overwrite your libs/dexmaker.jar with ~/.m2/repository/com/google/dexmaker/dexmaker/1.3-SNAPSHOT/dexmaker-1.3-SNAPSHOT.jar if you are using eclipse/ant
Also, FYI, the original issue report for the same issue on Google Code as well.
You can add the mockito core as a dependency instead. Then, that error will not happen and you won't need a workaround.
dependencies {
...
testCompile 'org.mockito:mockito-core:1.10.19'
}
I observed this issue when did manipulations with resources and folders inside test folder. Actually just restarting Android Studio helped. Simple, but worked.

Categories

Resources