If the flavor used specifies the applicationId as being com.example.boo and the manifest packageName is com.example.foo.
If i attempt to debug an activity and do an evaluate expression with findViewById(R.id.sampleView) it will return that resource was not found, because the R class belongs to com.example.foo, if i do it like it.resources.getResourceName((it.contentView as ViewGroup).getChildAt(3).id) it shows that the name is com.example.boo:id/sampleView
I found in the official documentation a subnote mentioning this behaviour.
But nothing telling me how to actually debug, because all expressions using resources will return false negatives/positives, since it cannot find the resources in question.
How do i solve this issue?
In your app's build.gradle file in section defaultConfig make your applicationId not include parts which you are using as flavors. For Example: you appId 'com.example.foo' and then name your flavors 'flav1' and 'flav2'. In that case you will have appId the same as your packageName and there should not be such problems with R file.
Your application will consists of applicationId(com.example.foo)+flavorName(flav1) = com.example.foo.flav1
Related
My project has different build types i.e. debug, beta and production and also have different product flavors i.e. QA and Integration. I have defined
a
buildConfigField 'int', 'APP_THEME', 'R.style.AKTheme'
in the productFlavors to have a separate theme for each flavor. The generated BuildConfig.java for app source set have the APP_THEME field and it is working as expected.
Recently I have started writing instrumentation tests for my app. When I try to run these tests Android studio gives me the error that can not resolve AKTheme i.e.
final int APP_THEME = R.style.AKTheme in the generated BuildConfig.java for the test source set.
It seems that R.style.AKTheme is not accessible to the generated BuildConfig.java file (test source set). I searched over internet but didn't find any help.
R.style.AKTheme is a reference, not a value, while in BuildConfig you can only use values.
There are couple of ways to achieve what you want:
Use the String name of the style in BuildConfig:
buildConfigField 'String', 'APP_THEME', '"AKTheme"'
and then in code to get the style res id:
int style = context.getResources().getIdentifier(BuildConfig.APP_THEME, "style", context.getPackageName());
Now you can use style.
You can use different source-sets.
If you are using different buildtypes, you can create a directory for that build type, and put any different resources specially for that build type in that directory. The directory should be created in the same directory as main sources directory, and named exactly the same as the buildType. Details: https://developer.android.com/studio/build/build-variants
I had quite the same issue. I had this in my build.gradle to get the right ssl certificate depending on the env. :
buildConfigField 'int', 'SSL_CERTIFICAT_RAWRES_', 'R.raw.devcert'
This was working to build and run the project, but I faced an issue when I wanted to run the task : "compileDebugAndroidTestJavaWithJavac" (used for sonarqube in my case). The compiler didn't found the resource file R when he automatically generates the buildConfig file.
The solution was to put a String to identify my certificate file "devcert" in the build.gradle instead of using directly the resInt "R.raw" :
buildConfigField 'String', 'SSL_CERTIFICAT_RAWRES_STRING', '"devcert"'
and then in my code, I get the raw file certificate like this :
final int raw = context.getResources().getIdentifier(BuildConfig.SSL_CERTIFICAT_RAWRES_STRING, "raw", context.getPackageName());
That way, the generated buildConfig found correctly the String identifier to retrieve the wanted raw file using the code above.
I found my answer here: https://developer.android.com/studio/test#create_instrumented_test_for_a_build_variant
For my case my test project and my main project is referencing a different package name, e.g. at the top of BuildConfig.java one referencing to package 'com.xxx.xxx' while one is referencing to 'com.xxx.xxx.test'
adding the line
testApplicationId = "com.xxx.xxx"
in defaultConfig in app level build.gradle file solves the issue for me
In an Android project, the resource ids are fully identified by the application id. For example, if my appid is com.mycompany.myapp, the resource id would be com.mycompany.myapp.R.blah.
In my case, I need to create two versions of the app - beta version and release version. Both the versions may be installed on the same device. This can happen only if the appids are not the same. My strategy is, during the nightly build, I will programmatically modify the manifest file and change the appid to com.mycompany.myappbeta. However, if I do this, I would need to touch a number of source files that are using the resource ids.
I am wondering if there is some token in the manifest file where I can explicitly say how the resource ids be qualified? Regards.
Edit
It turns out app id and package id are indeed two different concepts. I wanted to change the app-id but not the package-id. However, it seems this is not possible under Eclipse. As other posts have pointed out, Gradle build can handle changing the app-id but retaining the package id. I am moving over to Android Studio now.
the resource ids are fully identified by the application id
Technically, they are identified by the package name, from the package attribute in the root manifest.
My strategy is, during the nightly build, I will programmatically modify the manifest file and change the appid to com.mycompany.myappbeta. However, if I do this, I would need to touch a number of source files that are using the resource ids.
Which is why your nightly build should be using Gradle and the Gradle for Android plugin. Then, you skip all of what you described, and instead use build types. Two build types (debug and release) are pre-defined, and if you want to invent another one (e.g., beta), you can. Then, in the build type configuration in your build.gradle file, you use applicationIdSuffix to give non-release builds a distinct suffix. That will be added to the application ID for the purposes of unique installations, but your package name is unaffected, so your resources are unaffected.
For example:
android {
compileSdkVersion 19
buildToolsVersion "21.1.2"
defaultConfig {
versionCode 2
versionName "1.1"
minSdkVersion 14
targetSdkVersion 18
}
signingConfigs {
release {
storeFile file('HelloConfig.keystore')
keyAlias 'HelloConfig'
storePassword 'laser.yams.heady.testy'
keyPassword 'fw.stabs.steady.wool'
}
}
buildTypes {
debug {
applicationIdSuffix ".d"
}
release {
signingConfig signingConfigs.release
}
beta.initWith(buildTypes.release)
beta {
applicationIdSuffix ".beta"
debuggable true
}
}
}
Here I:
Give the debug build type an application ID suffix of .d
Leave the release build type along from the standpoint of an application ID suffix
Create a new beta build type, cloned from the release build type, where I give it a .beta application ID suffix and mark it as debuggable
However, if I do this, I would need to touch a number of source files that are using the resource ids.
No, you will not. You just need to change package id in your Manifest file only, ensuring however all services and activities listed in manifest file are using full class path, i.e.:
android:name="com.mycompany.myapp.MainActivity"
not just shortened notation:
android:name=".MainActivity"
as this make your app not working when package Id will not match with your code packages.
I have the following product flavors in module's build.gradle
productFlavors {
pro {
applicationId "com.icounttimer.android"
}
free {
applicationId "com.icounttimer.android.free"
}
}
The package structure of my app module is:
src/main/java/com/icounttimer/android/MainActivity.java
Building pro-debug.apk shows the splashscreen correctly. However, free-debug.apk does not show the splashscreen.
Changing the applicationId of 'free' flavor to 'com.icounttimer.android' resolves the issue. But when using a different applicationId, the splash screen won't be shown.
Environment:
CordovaLib: v3.6.3
Android Studio 1.0 RC4
What is the reason for this behaviour and how to resolve this issue?
The reason which I found is as follows:
Changing applicationId via build.gradle, changes the app's package name.
Note that it is different from the package structure of the app which remains unaltered during different build variants.
The app package structure, in this case, is unaltered: src/main/java/com/icounttimer/android/MainActivity.java
Diving through the code, I found out that the showSplashScreen() methods in CordovaActivity.java (part of CordovaLib) get the resources as follows:
this.splashscreen = getResources().getIdentifier(splash, "drawable", getClass().getPackage().getName());
The third arguments for getIdentifier(...) method is the package name of app.
getClass().getPackage().getName()
gets the pkgName based on package structure which always returns 'com.icounttimer.android' no matter which build variant it is.
To fix this, replace both of its occurences in CordovaActivity.java with:
this.getPackageName() //returns the name of the application pkg which is the applicationId
So I have base Application class, DApp.
My flavor application classes just extend the DApp.
for example
package com.d.android;
public class App extends DApp {}
In my gradle script the following is setup for the flavor:
productFlavors {
d {
applicationId = "com.d.android"
}
}
In my manifest I've declared my app like that:
name = ".App"
For some reason gradle does not honor the different package name given by applicationId.
For now I just resolved it by defining AndroidManifest files for each flavor and declaring the full class name for the app file, but that seems wrong. That means that my package name is wrong.
Any ideas?
I think the problem is that you are not specifying a package name. You should always specify the package name in the root of your default android manifest file like this:
package="com.exmaple.app"
Please take a look at this explanation by the Google guys, hope it helps.
http://tools.android.com/tech-docs/new-build-system/applicationid-vs-packagename
Good luck
My problem is that after I added flavors to my project the flavor with a package name different from the actual source seems to have problems with accessing the files in android_res/drawable.
More specifically I have a html-view that calls the following image.
<img src="file:///android_res/drawable/image.png">
The image shows up in the production flavor that has the package name which is the same as the directory of the java-files but it doesn't work for the beta flavor:
productFlavors {
production {
packageName "com.company.myapp"
}
beta {
packageName "com.company.beta"
}
}
where the actual directory with the java files is
java/com/company/myapp
It is rather strange that this happens since the resources are not even in that folder.
packageName is not supported in gradle. Gradle has a distinction between applicationId and packageName (see http://tools.android.com/tech-docs/new-build-system/applicationid-vs-packagename) which means that should be able to have the resources package name differ from the package identifier for your application.
Unfortunately that does not seem to be supported by the file:///android_res URL scheme in a webview.
I was able to workaround it in my case by creating an R class in the other package with the correct inner class and with a public static final int field that was initialized with the value from the real R file. This is a hack and doesn't survive renaming the resource and is not convenient if you have lots of resources you need to access.
So in your case that would look like adding this to your beta flavor source files directory:
package com.company.beta;
class R
{
class drawable
{
public static final int image = com.company.myapp.R.drawable.image;
}
}
UPDATED ANSWER
Have you set up your flavor folders properly?
If you have two flavors (flavorOne, flavorTwo) you need to set up the source folders accordingly.
Your build.gradle file should look something like this:
productFlavors {
flavorOne {
applicationId "com.package.name"
versionCode 1
versionName "1.0"
}
flavorTwo {
applicationId "com.package.name.two"
versionCode 1
versionName "1.0"
}
}
So, here is what the folder structure would look like for those two flavors:
src
---|main
--------|java
-------------|com.package.name
--------|res
-------------|drawable
---|flavorOne
--------|java
-------------|com.package.name
--------|res
-------------|drawable
---|flavorTwo
--------|java
-------------|com.package.name
--------|res
-------------|drawable
Put the drawables for each flavor in it's associated folder.
So you would have the image.png file for flavorOne in that drawable folder and the image.png for flavorTwo in the flavorTwo drawable folder.
This way localization will work for each flavor.
You should NOT be creating 'R' classes. These are autogenerated.
OLD ANSWER
Not really a solution to your exact problem but another approach.
You could move your image files to the assets folder instead and use this
<img src="file:///android_asset/image.png">