I routinely have problems during project builds where Resource.Designer gets generated but will no longer compile. My search engine shows that I'm not the only one that has this problem, but I've also not found any reliable "fix" for when it happens.
For example, right now I have a project that works just fine, but if I add a reference to a NuGet library (that I created) then the app will no longer compile because of loads of errors in Resource.Designer.cs.
On another project, I simply upgraded Xamarin Forms and now I can no longer compile, again due to a load of errors in Resource.Designer.cs.
Of course the immediate issue is "how do I fix the errors in these projects" but really I want to understand what is fundamentally going on here. What causes Resource.Designer to get generated and regenerated? What algorithm is used to decide what items get put into that file? Why do we so often end up with a file getting generated that then cannot actually compile? Why is it not getting the references it needs for those items?
I'd really like to understand this at a fundamental level so that once I get past the current thing causing me headaches, I can avoid it in the future when it comes up again (and I most certainly will come up again).
Resource.Designer.cs is synonymous with R.java in Android. Which of course is an application's resources that are referred to by a generated constant Resource ID.
These items are usually defined in your Xamarin.Android's .csproj via:
<AndroidResgenClass>Resource</AndroidResgenClass> (This might be outdated)
or
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile> (Current)
This is part of the Android Build process in which the aapt tooling will generate respective constant resource IDs per each resource defined in your project(res/ - Android, Resources/ - Xamarin.Android). These are then processed into binary form and embedded into the .apk. Thus the Resource.designer.cs is generated after a successful aapt.
It then goes a bit further to define a Resource in a specific Resource Type:
http://code.google.com/android/reference/android/R.html
anim
animator
array
attr
bool
color
dimen
drawable
fraction
id
integer
interpolator
layout
menu
mipmap
plurals
raw
string
style
styleable
transition
xml
Since aapt is called in the Android Build tooling, it is highly recommended to not manually invoke it unless you understand the complete Android build process.
https://developer.android.com/studio/command-line/index.html
As far as an "Algorithm", I don't think it's really that complex other than simply mapping a Resource ID to a resource as defined above. There are some complexities in the sense of Merging Resources in a project. For example a library project -> your application project:
The build tools merge resources from a library module with those of a dependent app module. If a given resource ID is defined in both modules, the resource from the app is used.|
If conflicts occur between multiple AAR libraries, then the resource from the library listed first in the dependencies list (toward the top of the dependencies block) is used.
To avoid resource conflicts for common resource IDs, consider using a prefix or other consistent naming scheme that is unique to the module (or is unique across all project modules).
https://developer.android.com/studio/projects/android-library.html#Considerations
Given the majority of people's issues with Resource.designer.cs, they typically come from a point of view of understanding where actual third-party Resources come from and how they are supported. Here are some tips that I personally use:
Ensure your Application project is compiled against the latest API version. Typically this will be the <TargetFrameworkVersion> MSBuild property. One of my colleagues has an amazing blog post that stands the test of time about this factor:
http://redth.codes/such-android-api-levels-much-confuse-wow/
Find where the Resource is coming from. Does it come from an official NuGet package? When was the Resource introduced into the Android framework? (Useful for mostly Material Design items).
For example, if I had an error message regarding colorPrimary, I might check what API it was introduced in:
Added in API level 21
https://developer.android.com/reference/android/R.attr.html#colorPrimary
Thus we now know we require API 21+ at minimum to use this item.
Take a deep dive into the dependencies you are loading into your project. You can use a decompiler like dotPeek to look through an assembly and see what Resources it's trying to give your project. Additionally you can look at the cache of respective .aar and view it's res/ folder. This is mostly useful for larger bindings like the Android Support / Google Play Services ones. For smaller projects, look for the /res string inside the decompiled .dll
For example let's take a look at com.android.support:appcompat-v7:24.2.1:
First we need to find the cache on our machine:
AppData\Local\Xamarin\Xamarin.Android.Support.v7.AppCompat\24.2.1\embedded\res (If you get stuck here on OSX, I wrote a guide awhile back about finding these paths here - https://developer.xamarin.com/guides/android/troubleshooting/resolving-library-installation-errors/)
So we can now look through all of the respective Resources this library is trying to give to us.
Finally the last item is that people tend to delete the Resource.designer.cs file from their project. After the aapt process is complete, it will generate a new one or it will fail on aapt. It is up to you to figure out whether that step passed or not (i.e. Check the main project Resources folder for the newly generated Resource.designer.cs file so you can re-include it into your project).
Related
I know there are two well-known folders where one can put resources.
The first is the /assets folder, the documentation says:
Contains file that should be compiled into an .apk file as-is. You can navigate this directory in the same way as a typical file system using URIs and read files as a stream of bytes using the AssetManager. For example, this is a good location for textures and game data.
The second is the /res folder, the documentation says:
Contains application resources, such as drawable files, layout files, and UI string. See Application Resources for more information.
Now i was wondering, there is a third option to create a resource folder "New > Folder > Java Resources Folder"
To me i looks like some part of the Android Plugin in IntelliJ because it has a little Android symbol in front of it .
Any ideas what the use of it could be? I couldn't find any documentation about it.
My first guess would be to use it in situations where you want to supply resources to a JVM Test.
In standard java world
Resources can be embedded directly in "your source tree" and used with Class's method getResource (see java documentation for a more precise description).
In android world
This practice is not recommanded (do not work at all, because such resources are removed from generated APK). You can still declare Java resources folders (see build.gradle :
sourceSets {
main {
resources.srcDirs = ['src/main/java/yourresourcesfolder']
}
}
And the result in the apk :
Conclusion
As resources's folder tree is removed,using java's resource folder become from my point of view, useless (in an android projet). Using android's asset folder is a better choice (also avoid resource's name conflict, but it's an another story :D )
This post is a bit old, but I want to bring an answer that explain one use case for the java resources directory on Android. If this folder exists in the options of a project it's because something can be done with it...
Enters the Service Loader, that helps to connect other services (aka libraries) into your main app, it can be used as a Gateway for your Android library to extend the functionality of a feature, exposing only the interfaces or abstract classes, with the Service Loader providing the implementation instead of your project having direct access to them.
Here is an example of how it's implemented. So, in summary the folder (META-INF/services) and files you have to create in order to use the Service Loader on an Android App, NEED to be inside this Java Resources Folder, otherwise your provider won't be able to see any implementation.
You can see it working in my sample here if you want to check it out: https://github.com/difereto-globant/test-library-feature/tree/1.0.9.
TL;DR
I'm an android developer and I have essentially several copies of the same app that feature slight differences. Despite my best efforts I'm having to resort to copy-and-paste style modification for each app-copy (hereafter "flavor") whenever I need to roll out a single change to all of the apps. This is particularly heinous in Android because of the number of languages/file-types involved in a given app - C for native code, Java for regular code, .xml files for data, layouts, and os permissions, etc. Tricks I know to avoid copy-and-paste coding that work in Java or C alone won't extend to both at once, or over to the .xml files. I've been using Apache ANT with some success to create a custom build/ folder on the fly and include relevant files there for different build-targets, but it's a little cludgy, and there are some cases it just can't handle.
I'm wondering if there is a build system that could handle all of this for me; I'm open to any advice, though the solution I have in mind is particular to a sort of language-independent/filesystem #include approach, which for a given flavor at build time injects either whole files into a src/ tree, or else injects code fragments into various .java, .c, and .xml template files in that src/ tree.
A Really Long Explanation with Concrete Examples:
Examples of the differences between flavors: in the Google Store I have to use the Google in-app purchasing sdk; but in the Amazon store I have to use the Amazon in-app purchasing sdk. Different flavors are paired with different advertising partners. Certain flavors require different i18n language files; or graphics and layout assets for different devices; etc. etc. Any given flavor is essentially the base code, plus any number of these "add ons", where each add on requires a little bit of custom code and file additions to the src/ tree for that app. Whenever I need to change an add-on, I end up having to copy-and-paste the change in each flavor of the app that uses it, which is a terrible pain.
As a concrete example, imagine I have an android game and I have implemented a custom Flurry Appcircle ad view. This would typically involve the following:
The addition of "<activity>", "<service>", and/or "<uses-permission>" tags to the game's AndroidManifest.xml
The addition of various "<string>" lines for the ad in the apk's res/values-xx/strings.xml folder system, where xx is a language code (ie Spanish translations would go in res/values-es/strings.xml)
One or more image or layout resources in res/layout, or assets/, for the ad.
The actual Flurry Inc sdk in the form of a Java .jar file in libs/ - possibly multiple jar files if different hardware architectures need to be handled differently.
Java Code in the game's Activity class, e.g. in onStart or onStop, to query for an Appcircle ad and show it. To avoid code duplication, I would normally write this in a base class that surrounds all code in a "if(appcircleAdsEnabled(){...}", create a default implementation of that method that returns false, and #Override and return true in various children Activity classes.
This causes a few problems:
The Flurry .jar is now a dependency for the base class to compile whether or not the ads are enabled or not in any given flavor. I can hope that the builder notices code or resources are unused at build time and removes it from the final apk; but there are no guarantees, and failure leads to (A) bloated final binary size and (B) potential P.R. issues or worse (especially from automated scanners searching for code inclusions - in a slightly different example, I'd have a hard time assuring the Amazon App Store that "yes Google Play Billing is there but it's not used.")
Because of the way Android turns resource files into java constants, and in the same way as (1), the res/* files may also become unnecessary dependencies of all games deriving from this Base Class.
Some libraries/methodologies I've found insist on their code being added in specific places or in specific ways which precludes the base class approach altogether.
For each individual game I still have to at least edit its AndroidManifest to "turn this on" and request relevant OS permissions necessary to show the ad.
It's tedious to remember which "add on" goes with which changes in which files. For instance, in any given flavor's AndroidManifest.xml, I can't keep track of which permissions are needed by which add ons. If I remove the Flurry add on, do I still need the INTERNET permission for something else?
What I'm hoping exists, and what I'm asking about, is if there's some way to inject files and code fragments into/on-top-of some skeleton file system, each add-on composed of a collection of such files and code fragments and injected dynamically at build time, with the build system merging lines across multiple add ons, and handling dependency inclusion on the fly. IE for my Flurry Ad add-on I would have:
Some collection of files 'FILES' that includes my xml additions to various .xml files (like AndroidManifest.xml), my code additions to various .java files (like the Activity subclass), and in some cases whole files themselves to be injected in various places (like the ad layout files)
In some skeleton template file tree, incomplete versions of e.g. AndroidManifest.xml, MyActivity.java, etc. with something like a language-independent #include syntax indicating that data from FILES will go there.
Also in that template file tree, directories in src/ with 'missing files' that will be copied in dynamically at build time from FILES
Some sort of build directive script for FILES indicating what goes where when this add-on is included, to take the skeleton template file tree and turn it into a fully fleshed out build/ tree.
And again, ideally it would be able to handle multiple "add ons" at the same time; ie I might have some FILES for this Advertiser, and some FILES for that billing provider, etc. etc., and a given product is just a list of which modules it includes, the build system magically knitting them together at build time.
This seems like exactly the problem the Gradle Build Variants system was designed to solve - it handles merging multiple versions of the AndroidManifest.xml, resources, and Java packages together into one or more separate apps. Specifically, the Multi-flavor variants seem to cover your requirements for combining multiple features together in various ways.
Gradle is offered as part of Android Studio, an IntelliJ based IDE specifically built for Android Gradle projects. You may consider reviewing one of the many Gradle Build guides if you are not familiar with Gradle.
The standard advice for sharing code & resources between Android projects is to use a library. Personally I find this works poorly if (a) the shared code changes a lot, or (b) your computer isn't fast enough.
I also don't want to get into deploying multiple APK's, which seems to be necessary when I use dependent projects (i.e. Java Build Path, Projects Tab).
On the other hand, sharing a folder of source code by using the Eclipse linked source feature works great (Java Build Path, Source tab, Link Source button), but for these two issues:
1) I can't use the same technique to share resources. I can create the link to the resources parent folder but then things get wonky and the shared resources don't get compiled (I'm using ADT 21).
2) So then I settle for copying the shared resources into each project, but this doesn't work because either. The shared code can't import the copy of its resources because it doesn't know the package name of the project that uses it. The solution I've been using is to access the resources dynamically, but that has become cumbersome as the number of resources grows.
So, I need a solution to either (1) or (2), or I'll have to go back to a library project. (Or maybe there is another option I haven't thought of?)
Your real problem is (2). Fixing (1) would eliminate some copying, but you would still run into problems with (2).
Unfortunately, that really isn't possible. There's a fair bit of fancy footwork that goes on to make multiple packages possible with library projects, and there's no good way to get that same result without library projects. Anything in res/ of a project is accessed via that project's R class, including your copied resources.
The solution I've been using is to access the resources dynamically
I translated that into you using getIdentifier(). That certainly works. Another approach is to having the hosting app supply resource IDs as parameters to the library code -- this is the pattern that the Android SDK itself uses. This is faster at runtime than the reflection-based getIdentifier(), and it gives the hosting app somewhat more flexibility, but you do wind up adding a bunch of parameters to your methods and constructors as needed to supply the various project-specific R values.
So I'm trying to use the built-in drawable timepicker_up_btn for api level 7. It is in the actual res folder in the sdk, and I can use other resources from that folder. But I get the error message "Resource is not public".
It seems like Google is trying to limit the use of this resource. I would think they don't care if I use it in an Android application and it makes the overall look of my application similar to stock Android.
Anyway, is this fixable? Can I somehow use a non-public resource without copying it to my project? And what is the deal with copying stock resources to own projects? Illegal? Frowned upon? Or go ahead we don't care?
The best thing to do is to copy the files to our application. I was told by some Google employees that you should not reference the resources, rather copy them to your application.
One of the reasons for this is that if you reference a whole bunch of icons for your application, you are not guaranteed that every one of these is updated at the same time when new versions of the SDK is released. You might end up with some up-to-date fancy icons and some old ones :)
Is there any way to use not public android resources in my application?
You can reference them like this
android:drawable="#*android:drawable/pressed_application_background_static"
but it is not recommended, because private resources are likely to be renamed or removed in the future.
Technically you can copy the resource from SDK folder to your own resource folder and then use it as your own. Though I am not sure whether it's a violation of the copyright.
When using Android libraries if more than one project (main or libraries) defines the same resource, the higher-priority project's copy gets used and replaces the previous one.
This is a problem when writing a reusable library because it forces you to prefix every resource name to avoid conflicts. See the Android Parcel Project for more information on the topic.
Now what I'd like to do is a script that would, prior to compilation, prefix the name of every resource from all libraries with their package name. For this I intend to use the generated ant build script and add a custom step to it.
Do you know if that would be possible? Do you see a better solution to fix this issue?
Do you know if that would be possible?
If you have source code to the library, I suppose you could do this. Any place you refer to resource IDs dynamically (reflection, getIdentifier(), etc.) would have to be adjusted manually, I suspect. And you may not be able to get assistance from the library author given that you modified their code.
I'd also work on trying to convince the library author to add resource prefixes in future editions of their library.