19

How do I make the resources (string, dimen, color, etc.) in my Android library module private?

I've tried both documented ways of doing this and neither work...

  1. Following the official Android doc of creating a res/values/public.xml does not work; all of the resources remain public in the app that uses this library.
  2. Following Chris Banes's instruction (and reiterated in this StackOverflow answer) of creating a res-public/values/public.xml folder does not work either; all of the resources are made private, but those listed in the public.xml file are not made public as they should be.

Does anyone have the definitive instructions for making library resources private? Are there any open-source libraries out there that have properly made their resources private?

I'm using...

  • Android Studio v2.2.3
  • buildToolsVersion "24.0.2"
  • com.android.tools.build:gradle:2.2.3
Community
  • 1
  • 1
Gus
  • 2,531
  • 4
  • 22
  • 28
  • 3
    `appcompat-v7` uses this. If you look in the AAR, you will see `public.txt`, which is generated based on this information, and [it uses `res-public`](https://github.com/android/platform_frameworks_support/tree/master/v7/appcompat/res-public/values). Ditto [the design support library](https://android.googlesource.com/platform/frameworks/support/+/master/design/res-public/values) and [its `material-android` successor](https://github.com/material-components/material-components-android/tree/master/lib/res-public/values). – CommonsWare Jan 25 '17 at 23:40
  • Thanks, @CommonsWare. Those links helped me get to the root of my problem... I had the incorrect path when referencing my `res` and `res-public` folders in my build.gradle `sourceSets`. – Gus Jan 26 '17 at 02:15

2 Answers2

9

Your resources are assumed to be public in any module (library, etc) unless you start, explicitly, declaring any resource in the module to be public. At that point you basically opt-in to every resource (within the module) being private except what you mark as public. This preserves backward compatibility and let's you incrementally tighten down access in large projects with many modules.

To make all resources private simply add <public /> to any of your existing resource files.

The above answer talks about adding a specific resource directory just to manage the public/private modifiers. While that works, I might suggest you manage the visibility and declaration in the main resource files next to where they are declared. Here's a sample strings.xml resource file I used with a brand new library module. The public/private prefix in the string names is for illustrative purposes only.

res/values/strings.xml

<resources>
  <string name="app_name">My Library2</string>

  <public type="string" name="public_string_in_lib2" />
  <string name="public_string_in_lib2">public string in lib2</string>

  <string name="private_string_in_lib2">private string in lib2</string>
</resources>

Fundamentally, these qualifications are being used to create a public.txt file that is embedded in the AAR that will be depended upon by another module. Various pieces of tooling like Android Studio will use this information to flag/warn, but technically, a consumer of the library isn't prevented from using the resource unless their tooling is being really strict.

PaulR
  • 3,223
  • 1
  • 21
  • 32
4

Option #2 actually works. I had not properly defined my sourceSets in my build.gradle...

sourceSets {
    main.res.srcDirs = [
        'src/main/res',
        'src/main/res-public'
    ]
}
Gus
  • 2,531
  • 4
  • 22
  • 28
  • 1
    Could you, please, share the solution? It doesn't work for me :( – Slava Aug 01 '17 at 12:10
  • @Gus The above solution didn't work for me. Still, I am able to access the private resources in the Main app module – AKASH WANGALWAR Nov 26 '18 at 09:00
  • @AKASHWANGALWAR check out this android doc, https://developer.android.com/studio/projects/android-library#PrivateResources – Ebi Igweze Jan 18 '19 at 12:17
  • How you manage to get it worked? Its not working for me (Gradle plugin: 3.3.1) – Alphonsa Augustine Feb 12 '19 at 12:29
  • Resource privatisation means, you won't see them in lint or suggestions. But if you know you can access them. My question is how to have 2 sets of folder for resources in two different place? I am getting error `res/values already exist, please try different qualifier` – Jimit Patel Apr 21 '20 at 11:12