I have a multi module android app which has lint configured to run prior to pushing to github, as a pre-push hook. I have 2 different machines (both Mac) which I use to write code for this app.
On one machine lint flags an error due to Missing Permissions. The permission that lint is looking for is declared in a different module and the app compiles, builds and runs as expected, so this being done correctly is not in question. I'm also part of a team of 5 and no one else sees this.
<?xml version="1.0" encoding="UTF-8"?>
<issues format="5" by="lint 3.6.2">
<issue
id="MissingPermission"
severity="Error"
message="Missing permissions required by TelephonyManager.getNetworkType: android.permission.READ_PHONE_STATE"
category="Correctness"
priority="9"
summary="Missing Permissions"
explanation="This check scans through your code and libraries and looks at the APIs being used, and checks this against the set of permissions required to access those APIs. If the code using those APIs is called at runtime, then the program will crash.
Furthermore, for permissions that are revocable (with targetSdkVersion 23), client code must also be prepared to handle the calls throwing an exception if the user rejects the request for permission at runtime."
errorLine1=" return when (telephonyManager.networkType) {"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="/Users/chris/myproject/dependencies/network/CellularInfoImpl.kt"
line="47"
column="18"/>
</issue>
I've checked the following list to ensure that both machines are running the same configuration.
Android Studio version.
It's the same code base on the same branch.
Gradle plugin version
gradle.properties
gradle-wrapper.properties
Android Studios preferences for Correctness Inspections. (Missing permissions is ticked on both)
lint config.xml
lint version, taken from the lint report after completing the gradle task.
My question is, what else could be causing the discrepancy? Where else should I be looking to attempt to resolve this?
Thanks.
The simple solution is to add a SuppressWarning annotation for Missing Permissions. This overcomes the problem by stopping the lint warnings, but doesn't actually solve it.
Related
My Android project has about ~70 Robolectric tests and they were all passing for 2 months. Somehow, starting today, the tests are failing with weird error messages:
java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
java.lang.NoClassDefFoundError: org/apache/http/client/HttpClient
Also can't load resource files
I didn't change my code, so it can't be code related issue. I cleaned project and gradle but it didn't help. I did do a update promoted by Android Studio a few days ago, not sure if related.
Is anyone else is experiencing the issue? How do I get out of this bad state?
-- edit --
Robolectric version matters! Interesting observation based on suggestions in comments, robolectric version v.s. failure rate:
3.3.1, ~40% of the tests fail.
3.2.2, ~40% failure (same as 3.3.1)
3.1.4, ~15% failure
3.1.2, ~0% failure (with caveats, see below)
3.1, 100% failure (!)
Another observation is that it's inconsistent. If I run the whole set, all pass! But If I only run one test file, all fail with this message:
No such manifest file:
build/intermediates/bundles/debug/AndroidManifest.xml
AS is quite sensitive about dependencies change, as well AS doesn't set the working directory for tests by default.
No such manifest ... error directly saying that Robolectric can not find your manifest.
Whenever you have test failing in AS check first the command line run if it is reproducible.
Check first working directory for test:
I would also recommend to setup module directory as working directory by default:
I'm trying to test using the following directory structure (which was setup by Android Studio):
I can run some tests just fine, and even the AllTests.java runs fine without the AndroidManifest.xml file even being there. The thing is, for one of my new tests, I need the android.permission.INTERNET permission. So, I added the following to the AndroidManifest.xml file located within the androidTest directory:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.core"
android:versionCode="2"
android:versionName="2.0" >
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
Unfortunately, this doesn't work. I'm still getting the following error when I run one of my tests:
E/RestAPIRequestTest﹕ Permission denied (missing INTERNET permission?)
I've tried setting the package to be com.example.core.test in my AndroidManifest.xml file (since that is what it shows up as in my Settings->Apps list), but with no joy.
I'm thinking it's not even recognizing the AndroidManifest.xml file, since the version number doesn't show in the Settings for the test app, either.
How can I inject the correct permissions for my test project?
I needed to do something similar. I created a folder named "debug" next to androidTest, which corresponds to the debug variant of the app, and put an AndroidManifest.xml with the permission in that folder. Then the permission works under test since the test app uses the debug variant. It's not ideal because it blurs the line between test and debug, which aren't quite the same thing.
I think what's happening is that the permissions in androidTest/AndroidManifest.xml are going to the test app, not the target app, although it's not 100% clear to me if there are actually two different APKs or what.
In older versions of Android Studio and the Android Gradle plugin the androidTest/AndroidManifest.xml file was ignored. This was documented at the tools.android.com site at the time.
With the Android Studio 1.0+ and Android Gradle 1.0+ plugin launch in December 2014 the AndroidManifest.xml file should now be merged with the normal main/AndroidManifest.xml files (in addition to the debug and release manifest files if they exist). More details regarding the manifest merging rules are here.
If you still run into issues or are just debugging manifest related testing issues try this
(Adapt this slightly for Windows):
Drop to a terminal
change to to your project directory
cd MyApplication
Build your project, assuming 'debug' is the build type you want to test with, but you could also be testing with 'release' or a build script defined one.
./gradlew assembleDebugTest
Then inspect your test APK manifest:
ls app/build/intermediates/manifests/test/debug/AndroidManifest.xml
View your application APK manifest:
ls app/build/intermediates/manifests/full/debug/AndroidManifest.xml
A merge output log can be found detailing the manifest merging process:
ls app/build/outputs/apk/manifest-merger-debug-report.txt
A couple of extra notes:
An instrumentation element is automatically added to your test APK's AndroidManifest.xml so you should only be adding extra activities, permissions, etc that your test APK needs.
If testing with mock locations your application APK will need the ACCESS_MOCK_LOCATION permission. You can add the permission to your debug/AndroidManifest.xml file or you can define that the test APK and the application APK should use the same userId when deployed (sharedUserId attribute in your AndroidManifest.xml).
This is a known problem.
Currently (AGP <= 3.4.X) is not supporting AndroidManifest test merging.
This is reported here: https://issuetracker.google.com/issues/127986458
and here there is the issue created by one of the Roboelectric maintainers.
The workaround as described here its near the same proposed by user3286293 and currently is the only way to have the manifest merged for testing purposes.
Hope to see a fix for AGP 3.5 or 3.6
As specified here, during instrumented tests, there are generated two .apk files. If you take a look, the smaller one it's most probably the one named app-debug-androidTest-unaligned.apk and it actually does include the provided permissions.
Inspecting the file with aapt d permissions <apk_file_path>.apk can be useful to see a list of all of them.
Now, there might be an issue with the context itself where the permission is requested. I had a similar problem, trying to write some screenshots on SD card (thus needing the WRITE_EXTERNAL_STORAGE permission).
This answer helped me to fix the problem, although I cannot fully understand why it's necessary.
In few words, you'll need to declare the same android:sharedUserId in both manifests, in order to merge the permissions when both apks are installed on the same device - that happens when tests are running.
This helped me to separate permissions needed just for testing from the one in production.
You need to define that in build.gradle file:
android {
sourceSets {
androidTest.manifest.srcFile "src/androidTest/AndroidManifest.xml"
}
}
One solution would be like build main apk and test apk in single run.
Example: ./gradlew clean :main:assembleDebug :main:assembleDebugAndroidTest.
This will create a new instrumented main application which has all extra permissions required for test application.
I'd like to know if there is a way to add certain permissions (or anything) to an android manifest file, but so that its only used during test runs - not production. I'm looking for something programmatic, not cutting and pasting when I'm testing.
Here's the context:
I'm reading this article: http://developer.android.com/training/location/location-testing.html, the best practice for test running an app used to be creating a 'test-app' however with android studio we now are not meant to create a new app - all testing should be done through the app. (Thank you gradle)
The issue is that this article is written with a testing permission (ACCESS_MOCK_LOCATION) in it, and I don't want that sitting in my app - and if there's a good way of doing it, I'd like to do that.
UPDATE: The reason I had this problem was because of a misunderstanding of the set up of android studio architecture since the migration to Gradle.
I didn't realize that the build types shared the 'androidTest' and 'main' source folders. And so when testing or running the unfinished app, it takes the debug files (if any) and adds all the production stuff to it. So in my case, I added a empty manifest file in debug and simply added the two permissions to it. When I run or test, gradle adds all of my apps things from its other manifest to it this skeletal file (or vice versa, I'm uncertain).
So in the end we don't need to modify the androidTest folder (in fact I don't think we are allowed to add a manifest here) as its completely generated based off of whether a user is running on debug or deployment. Cheers! :-)
Let's say you use the default debug and release build types and you run your tests against the debug build type.
In this case you can create a src/debug/AndroidManifest.xml and add the additional permissions you need in your debug builds:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your.package">
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
</manifest>
If your project does not follow the default folder hierarchy and you want to add permissions to the debug build add the following block.
sourceSets {
debug {
manifest.srcFile '<your folder>/AndroidManifest.xml'
}
}
I can create an app with Delphi XE5 (update 2, hotfix 1 -- but same was true in Update 1) that runs when it is created as a DEBUG version. But when I create it as a RELEASE-APPLICATION STORE version Internet stops working.
It seems to overwrite the android.manifest.xml file and take the INTERNET setting out of it. I have tried various ways of manually updating the file and deploying. But you have to run BUILD again to get the change to get incorporated -- and that overwrites the file again.
The app is simple app using REST. Also has a browser, with URL set in another part. Works fine in DEBUG version. In RELEASE-APPLICATION STORE version on REST call it says SOCKET #13 error, also web page does not work. So definitely no INTERNET.
Any thoughts, order for doing the manual change, or ideas would be greatly appreciated.
FOLLOW-UP --- FOUND THE SOLUTION
Unfortunately user permission settings are not not working completely in my environment. I change the INTERNET setting to TRUE in PROJECT | OPTIONS | USER PERMISSIONS and compile/build and the INTERNET setting gets eliminated (overwritten) from the AndroidManifest.xml file created in the project \release folder. In \debug version it is there (INTERNET setting) and is fine.
Solution for me, at least, is to update the AndroidManifest.template.xml file and add the INTERNET setting there -- so it is copied to both \release and \debug versions of the AndroidManifest.xml files.
So my AndroidManifest.Template.xml file .. in the project root looks like this:
... header and other info
<uses-permission android:name="android.permission.INTERNET" />
... other stuff and footer for file
The template files is used to create the \release and \debug versions of the AndroidManifest.xml files so it forces that setting to be put in that file.
This worked and cleared up the socket 13 error I was getting, and no INTERNET access on the release Android versions. YAY!!!
You have to go into the Project Options and enable the INTERNET permission. It is enabled by default for Debug builds, and disabled by default for Release builds.
I had the same problem. And setting project settings have no effect on release version. I think it is some kind of bug, because that effect appears only with INTERNET option. My solution is to set this option manually in androidManifest.template. In that case, it is working fine.
I put mine in after ..uses-permission... and it worked fine.
If I run "lint ." inside project directory I get the expected warnings, but if I run it from inside eclipse I get nonsense errors and warnings, for example:
The resource R.array.settings_derivatives appears to be unused [in fact, it is used]
The x.y.z is not registered in the manifest [in fact, it is registered]
Call requires API level 3 (current min is 1): android.view.SurfaceView#isInEditMode [in fact minSdkVersion is set to 7]
edit: If I create a new workspace and import the existing projects I get the right errors
There seems to be an issue, when the project directory is not directly under the workspace directory.
As of today the bug should be fixed in release 20:
http://code.google.com/p/android/issues/detail?id=27527
Edit:
If necessary you can make a softlink into the workspace.
The problem was solved by switching workspace to a fresh one. It probably was a problem with settings left over from previous lint versions
I solved the same problem using this:-
Right click on the project folder > Android tools > Clear Link Markers
"Run Android Lint" makes some markers and the markers cause this error.
"Preference --> Android --> Lint Error Checking", search issues "NewApi", and you can see the settings.
This check scans through all the Android API calls in the application and warns about any calls that are not available on all versions targeted by this application (according to its minimum SDK attribute in the manifest).
If your code is deliberately accessing newer APIs, and you have ensured (e.g. with conditional execution) that this code will only ever be called on a supported platform, then you can annotate your class or method with the #TargetApi