Friday, August 14, 2015

Supporting Multiple Screen Sizes

It is generally good practice to create a single APK that supports multiple screen sizes using alternative layouts: http://developer.android.com/guide/practices/screens_support.html.  At the same time, one can also target different flavors to different screen sizes and accomplish the same thing.

In this example, I am looking to lock the screen in landscape orientation for all activities on xlarge screens and in portrait orientation for all activities on small, normal, and large screens.  As it requires changes to the AndroidManifest.xml document for these changes; this forces us to use the multiple flavors approach.

In my evolving example, I go ahead and create additional flavors:
  • notelephony
  • notelephonytablet (new)
  • telephony
  • telephonytablet (new)
Then update the AndroidManifest.xml files for each with the supports-screens element, e.g.,:

AndroidManifest.xml (notelphony)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.larkintuckerllc.helloandroid" >
    <supports-screens
        android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="false"
    />
</manifest>

Using the aapt tool we see that it now reports:
supports-screens: 'small' 'normal' 'large'
This only targets the APK to the proper devices, now to actually force an orientation for the activities:

Now that we getting deeper into merging manifests we need to read up on them more: https://developer.android.com/tools/building/manifest-merge.html.

While the document does refer to a document that can be used to troubleshoot the merge: manifest-merger-<productFlavor>-report.txt, it did not seem to contain the details that I was expecting.  Rather I dug around and found what appears to the the final composite AndroidManifest.xml file under ./app/build/intermediates.

note: While I never found documentation that explains exactly how the merging works (just lots of examples), it is clear that andoid:name has special meaning and the merge process will match blocks up based on it.

So, we add to the notelephony flavor AndroidManifest.xml file the uses-feature for portrait and screenOrientation to each of the activities.

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.larkintuckerllc.helloandroid" >
    <uses-feature android:name="android.hardware.screen.portrait" />
    <supports-screens
        android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="false"
    />
    <application>
        <activity
            android:name=".MainActivity"
            android:screenOrientation="portrait">
        </activity>
        <activity
            android:name=".ThingActivity"
            android:screenOrientation="portrait">
        </activity>
    </application>
</manifest

Now this flavor always shows two activites vertically and the aapt tool reports:
uses-feature: name='android.hardware.screen.portrait'
With all this in place, here are the changes to the code to support this configuration: https://github.com/larkintuckerllc/HelloAndroid/commit/09e643979d3e15980382fa31b22dbfdc3cb67cfc




No comments:

Post a Comment