0

My company ships an Android app preloaded on an Android device to use with some industrial production equipment we make. We have both "phone" and "tablet" format devices, devices of different resolutions, locales, etc. So I'm familiar with having different xml folders for "layout" "layout-land", different image resources for "drawable-hdpi", "drawable-mdpi"; different language resources for "values-ru", values-ro", etc.

Now we have a customer that wants us to load our app on their own somewhat oddball aspect-ratio and resolution Android device, which they will supply us with, so I want to make a custom layout just for that device.

Assuming I make a layout folder called "layout-custom1", how do I tell my code to use that layout folder instead of defaulting to the regular layout or layout-land folders? I'd like to do it in just one place in my code because our app has a zillion screens/Activities and I'd prefer to not have to do it in before calling every setContentView().

And on that subject, what call can I make in my Java to ask what device I'm running on?

Edit: I'd prefer to avoid having different APKs because that will be a headache for our production staff.

user316117
  • 7,971
  • 20
  • 83
  • 158
  • 1
    You cannot target specific devices layouts like that, you will have to make a separate view if you need to make a device specific layout and do extra logic to show that view in setContentView – tyczj Sep 11 '17 at 19:41
  • @tyczj - the answer to [this StackOverflow question](https://stackoverflow.com/questions/12721483/how-to-create-device-specific-layouts) seems to imply that a separate view does not have to be defined, just a separate layout specified in the _setContentView()_ call - is the answer incorrect/incomplete? – user316117 Sep 11 '17 at 20:43
  • `R.layout.x` and `R.layout.y` are 2 different files, thats how you reference layouts from resources `.layout` is the type of file it is – tyczj Sep 12 '17 at 01:25

2 Answers2

2

Assuming I make a layout folder called "layout-custom1"

I think that will result in a build error. If not, it should, as you cannot invent new resource set qualifiers.

we have a customer that wants a version of our app for their own somewhat oddball aspect-ratio and resolution Android device so I want to make a custom layout just for that device

Ideally, find some existing resource set qualifiers that will cover that device, but no other devices that you support.

Or, use product flavors:

  • Create one for this customer and one (empty) one for everyone else

  • Override the resources as needed in the customer-specific flavor

  • Distribute the customer-specific flavor's APK to that customer and the other flavor to everyone else

Otherwise, you are pretty much stuck with modifying each setContentView() call, to use a customer-specific resource when running on this customer's device. You can simplify that somewhat via a common resource ID swizzling utility method, that takes R.layout.foo and returns R.layout.foo_funky for the customer's device and R.layout.foo for all other devices. Then, modify your setContentView(R.layout.foo) calls as setContentView(swizzler(R.layout.foo)).

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I'm unclear on your answer. Your last paragraph seems to imply that if I was willing to make a special-case call in _setContentView()_ I **could** have customer specific resource files. But your opening sentence seems to imply that creating such resources would result in a build error. I'd like to avoid separate APKs because that would become a production headache. – user316117 Sep 11 '17 at 20:32
  • @user316117: There is a difference between files and directories. My first sentence refers to directories. My last paragraph refers to files. `R.layout.foo` and `R.layout.foo_funky` would both be in `res/layout/` (and other resource sets as needed), with different filenames (`foo.xml` and `foo_funky.xml`, respectively). – CommonsWare Sep 11 '17 at 20:37
  • OK - that may be an acceptable compromise. I'd have to create the same number of new XML files whether I put them in a new folder or stuffed them into the existing one. Thanks! – user316117 Sep 11 '17 at 20:48
0

If you can deploy one more apk to this specific device, you can use the Runtime Resource Overlay (https://developer.sonymobile.com/2014/04/22/sony-contributes-runtime-resource-overlay-framework-to-android-code-example/) to create an apk containing only the necessary layouts (using the same ids), with no code.

Only overlays installed in /vendor/overlay, a directory writeable only by the device vendor (which is your case), are accepted, so you shouldn't have problem with this.

Also, remember to use the same signing certificate.

As explained on the link:

Runtime Resource Overlay hooks into the resource lookup framework, shadowing existing values or adding values for new configurations. The resource interface used by the application is unchanged, and the application is therefore not aware that RRO is currently applied, just as an application is currently not aware of its different resource configurations. Therefore, applications can take advantage of RRO without any source code modifications.

A key component of RRO is overlay packages. These are packages which contain alternate versions of one or more of an application’s resources. Any application may have its resources modified by one or more overlay packages. An overlay package only affects a single application, and in this context, the app is called the overlay’s target package.

Resource lookup, multiple overlays. The overlays are searched based on their priorities. The target package is always searched last.

  • So... you are going to force the customer to modify their firmware for their hardware? Why do you think the customer will be willing to do that, or is even in position to do that? – CommonsWare Sep 11 '17 at 19:59
  • Yes, the customer is a hardware vendor (with _their own somewhat oddball aspect-ratio and resolution Android device_). So it is really easy to them to embed both apks (original apk + overlay resources apk). – Henrique Cardone Sep 11 '17 at 23:30
  • No it isn't. The customer is using an off-the-shelf product. And, anyway, successful businesses are based on making life as easy as possible for the customer so even if he _could_ do some extra work why should we make him do so if it's not necessary? So CommonsWare is correct. – user316117 Sep 12 '17 at 21:27