Home | History | Annotate | Download | only in multiple-apks
      1 page.title=Creating Multiple APKs for Different GL Textures
      2 parent.title=Maintaining Multiple APKs
      3 parent.link=index.html
      4 
      5 trainingnavtop=true
      6 previous.title=Creating Multiple APKs for Different Screen Sizes
      7 previous.link=screensize.html
      8 next.title=Creating Multiple APKs with 2+ Dimensions
      9 next.link=multiple.html
     10 
     11 @jd:body
     12 
     13 <style type="text/css">
     14 .blueCell { background-color: #9fc5e8;}
     15 .greenCell { background-color: #b6d7a8;}
     16 .redCell { background-color: #ea9999;}
     17 </style>
     18 
     19 <div id="tb-wrapper">
     20 <div id="tb">
     21 
     22 <!-- table of contents -->
     23 <h2>This lesson teaches you to</h2>
     24 <ol>
     25   <li><a href="#Confirm">Confirm You Need Multiple APKs</a></li>
     26   <li><a href="#ChartReqs">Chart Your Requirements</a></li>
     27   <li><a href="#CreateLibrary">Put All Common Code and Resources in a Library Project</a></li>
     28   <li><a href="#CreateAPKs">Create New APK Projects</a></li>
     29   <li><a href="#AdjustManifests">Adjust the Manifests</a></li>
     30   <li><a href="#PreLaunch">Go Over Pre-launch Checklist</a></li>
     31 </ol>
     32 
     33 <!-- other docs (NOT javadocs) -->
     34 <h2>You should also read</h2>
     35 <ul>
     36   <li><a href="http://developer.android.com/google/play/publishing/multiple-apks.html">Multiple APK
     37 Support</a></li>
     38 </ul>
     39 
     40 </div>
     41 </div>
     42 
     43 <p>When developing your Android application to take advantage of multiple APKs on Google Play, its important to adopt some good practices from the get-go, and prevent unnecessary headaches further into the development process.  This lesson shows you how to create multiple APKs of your app, each supporting a different subset of OpenGL texture formats.  You will also gain some tools necessary to make maintaining a multiple APK codebase as painless as possible.</p>
     44 
     45 
     46 <h2 id="Confirm">Confirm You Need Multiple APKs</h2>
     47 
     48 <p>When trying to create an application that works across all available Android-powered
     49 devices, naturally you want your application look its best on each individual device, regardless of
     50 the fact they dont all support the same set of GL textures.  It may seem at the outset as though
     51 multiple APK support is the best solution, but this often isnt the case.  The <a
     52 href="{@docRoot}google/play/publishing/multiple-apks.html#ApiLevelOptions">Using Single APK
     53 Instead</a> section of the multiple APK developer guide includes some useful information on how to
     54 accomplish this with a single APK, including how to <a
     55 href="{@docRoot}google/play/publishing/multiple-apks.html#TextureOptions">detect supported texture
     56 formats at runtime</a>.  Depending on your situation, it might be easier to bundle all formats with
     57 your application, and simply pick which one to use at runtime.</p>
     58 
     59 <p>If you can manage it, confining your application to a single APK has several advantages,
     60 including:</p>
     61 <ul>
     62 <li>Publishing and Testing are easier</li>
     63 <li>Theres only one codebase to maintain</li>
     64 <li>Your application can adapt to device configuration changes</li>
     65 <li>App restore across devices just works</li>
     66 <li>You dont have to worry about market preference, behavior from "upgrades" from one APK to the
     67 next, or which APK goes with which class of devices</li>
     68 </ul>
     69 
     70 <p>The rest of this lesson assumes that youve researched the topic, studiously absorbed the
     71 material in the resources linked, and determined that multiple APKs are the right path for your
     72 application.</p>
     73 
     74 
     75 <h2 id="ChartReqs">Chart Your Requirements</h2>
     76  
     77 <p>The Android Developer Guide provides a handy reference of some of common supported textures on
     78 the <a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">supports-gl-texture
     79 page</a>.  This page also contains some hints as to which phones (or families of phones) support
     80 particular texture formats.  Note that its generally a good idea for one of your APKs to support
     81 ETC1, as that texture format is supported by all Android-powered devices that support the OpenGL ES
     82 2.0 spec.</p>
     83 
     84 <p>Since most Android-powered devices support more than one texture format, you need to establish an
     85 order of preference.  Create a chart including all the formats that your application is going to
     86 support.  The left-most cell is going to be the lowest priority (It will probably be ETC1, a really
     87 solid default in terms of performance and compatibility).  Then color in the chart such that each
     88 cell represents an APK.</p>
     89 <table cellpadding="10" cellspacing="0" border="1">
     90   <tbody>
     91     <tr>
     92       <td class="blueCell">ETC1</td>
     93       <td class="redCell">ATI</td>
     94       <td class="greenCell">PowerVR</td>
     95     </tr>
     96   </tbody>
     97 </table>
     98 
     99 <p>
    100 Coloring in the chart does more than just make this guide less monochromatic - It also has a way of
    101 making intra-team communication easier-  You can now simply refer to each APK as "blue", "green", or
    102 "red", instead of "The one that supports ETC1 texture formats", etc.</p>
    103 
    104 <h2 id="CreateLibrary">Put All Common Code and Resources in a Library Project</h2>
    105 <p>Whether youre modifying an existing Android application or starting one from scratch, this is
    106 the first thing that you should do to the codebase, and by the far the most important.  Everything
    107 that goes into the library project only needs to be updated once (think language-localized strings,
    108 color themes, bugs fixed in shared code), which improves your development time and reduces the
    109 likelihood of mistakes that could have been easily avoided.</p>
    110 
    111 <p class="note"><strong>Note:</strong>  While the implementation details of how to create and
    112 include library projects are beyond the scope of this lesson, you can get up to speed quickly on
    113 their creation at the following links:</p>
    114 <ul>
    115 <li><a
    116 href="{@docRoot}tools/projects/projects-eclipse.html#SettingUpLibraryProject">Setting up
    117 a library project (Eclipse)</a></li>
    118 <li><a
    119 href="{@docRoot}tools/projects/projects-cmdline.html#SettingUpLibraryProject">Setting up
    120 a library project (Command line)</a></li>
    121 </ul>
    122 
    123 <p>If youre converting an existing application to use multiple APK support,
    124 scour your codebase for every localized string file, list of values, theme
    125 colors, menu icons and layout that isnt going to change across APKs, and put
    126 it all in the library project.  Code that isnt going to change much should
    127 also go in the library project.  Youll likely find yourself extending these
    128 classes to add a method or two from APK to APK.</p>
    129 
    130 <p>If, on the other hand, youre creating the application from scratch, try as
    131 much as possible to write code in the library project <em>first</em>, then only move it down to an
    132 individual APK if necessary.  This is much easier to manage in the long run than adding it to one,
    133 then another, then another, then months later trying to figure out whether this blob can be moved up
    134 to the library section without screwing anything up.</p>
    135 
    136 <h2 id="CreateAPKs">Create New APK Projects</h2>
    137 <p>There should be a separate Android project for each APK youre going to release.  For easy
    138 organization, place the library project and all related APK projects under the same parent folder. 
    139 Also remember that each APK needs to have the same package name, although they dont necessarily
    140 need to share the package name with the library.  If you were to have 3 APKs following the scheme
    141 described earlier, your root directory might look like this:</p>
    142 
    143 <pre class="no-pretty-print classic">
    144 alexlucas:~/code/multi-apks-root$ ls
    145 foo-blue
    146 foo-green
    147 foo-lib
    148 foo-red
    149 </pre>
    150 
    151 
    152 <p>Once the projects are created, add the library project as a reference to each APK project.  If
    153 possible, define your starting Activity in the library project, and extend that Activity in your APK
    154 project.  Having a starting activity defined in the library project gives you a chance to put all
    155 your application initialization in one place, so that each individual APK doesnt have to
    156 re-implement "universal" tasks like initializing Analytics, running licensing checks, and any other
    157 initialization procedures that dont change much from APK to APK.</p>
    158 
    159 
    160 <h2 id="AdjustManifests">Adjust the Manifests</h2>
    161 <p>When a user downloads an application which uses multiple APKs through Google Play, the correct
    162 APK to use is chosen using some simple rules:</p>
    163 
    164 <ul>
    165 <li>The manifest has to show that particular APK is eligible</li>
    166 <li>Of the eligible APKs, highest version number wins</li>
    167 <li>If <em>any</em> of the texture formats listed in your APK are supported by the device on market,
    168 that device is considered eligible</li>
    169 </ul>
    170 
    171 <p>With regards to GL Textures, that last rule is important.  It means that you should, for
    172 instance, be <em>very</em> careful about using different GL formats in the same application.  If you
    173 were to use PowerVR 99% of the time, but use ETC1 for, say, your splash screen... Then your manifest
    174 would necessarily indicate support for both formats.  A device that <em>only</em> supported ETC1
    175 would be deemed compatible, your app would download, and the user would see some thrilling crash
    176 messages.  The common case is going to be that if youre using multiple APKs specifically to target
    177 different devices based on GL texture support, its going to be one texture format per APK.</p>
    178 
    179 <p>This actually makes texture support a little bit different than the other two multiple APK
    180 dimensions, API level and screen size.  Any given device only has one API level, and one screen
    181 size, and its up to the APK to support a range of them.  With textures, the APK will generally
    182 support one texture, and the device will support many.  There will often be overlap in terms of one
    183 device supporting many APKs, but the solution is the same:  Version codes.</p>
    184 
    185 <p>By way of example, take a few devices, and see how many of the APKs defined earlier fit each
    186 device.</p>
    187 <table cellpadding="10" cellspacing="0" border="1">
    188   <tbody>
    189     <tr>
    190       <td>FooPhone</td>
    191       <td>Nexus S</td>
    192       <td>Evo</td>
    193     </tr>
    194     <tr>
    195       <td class="blueCell">ETC1</td>
    196       <td class="blueCell">ETC1</td>
    197       <td class="blueCell">ETC1</td>      
    198     </tr>
    199     <tr>
    200       <td></td>
    201       <td class="greenCell">PowerVR</td>
    202       <td class="redCell">ATI TC</td>
    203     </tr>
    204   </tbody>
    205 </table>
    206 <p> Assuming that PowerVR and ATI formats are both preferred over ETC1 when available, than
    207 according to the "highest version number wins" rule, if we set the versionCode attribute in each APK
    208 such that red &#8805; green &#8805; blue, then both Red and Green will always be chosen over Blue on
    209 devices which support them, and should a device ever come along which supports both Red and Green,
    210 red will be chosen.
    211 </p>
    212 
    213 <p>  In order to keep all your APKs on separate "tracks," its important to have a good version code
    214 scheme.  The recommended one can be found on the Version Codes area of our developer guide.  Since
    215 the example set of APKs is only dealing with one of 3 possible dimensions, it would be sufficient to
    216 separate each APK by 1000 and increment from there.  This might look like:</p>
    217 
    218 <p>Blue: 1001, 1002, 1003, 1004...<br />
    219 Green: 2001, 2002, 2003, 2004...<br />
    220 Red:3001, 3002, 3003, 3004...</p>
    221 
    222 <p>  Putting this all together, your Android Manifests would likely look something like the
    223 following:</p>
    224 <p>Blue:</p>
    225 <pre>
    226 &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    227     android:versionCode="1001" android:versionName="1.0" package="com.example.foo"&gt;
    228     &lt;supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" /&gt;
    229     ...
    230 </pre>
    231 
    232 <p>Green:</p>
    233 <pre>
    234 &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    235     android:versionCode="2001" android:versionName="1.0" package="com.example.foo"&gt;
    236     &lt;supports-gl-texture android:name="GL_AMD_compressed_ATC_texture" /&gt;
    237     ...
    238 </pre>
    239 
    240 <p>Red:</p>
    241 <pre>
    242 &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    243     android:versionCode="3001" android:versionName="1.0" package="com.example.foo"&gt;
    244     &lt;supports-gl-texture android:name="GL_IMG_texture_compression_pvrtc" /&gt;
    245     ...
    246 </pre>
    247 
    248 <h2 id="PreLaunch">Go Over Pre-launch Checklist</h2>
    249 <p>Before uploading to Google Play, double-check the following items.  Remember that these are
    250 specifically relevant to multiple APKs, and in no way represent a complete checklist for all
    251 applications being uploaded to Google Play.</p>
    252 
    253 <ul>
    254 <li>All APKs must have the same package name</li>
    255 <li>All APKs must be signed with the same certificate</li>
    256 <li>Double check your manifest filters for conflicting information (an APK that only supports
    257 cupcake on XLARGE screens isnt going to be seen by anybody)</li>
    258 <li>Each APK's manifest must be unique across at least one of supported screen, OpenGL texture, or
    259 platform version</li>
    260 <li>Try to test each APK on at least one device.  Barring that, you have one of the most
    261 customizable device emulators in the business sitting on your development machine.  Go nuts!</li>
    262 </ul>
    263 
    264 <p>Its also worth inspecting the compiled APK before pushing to market, to make sure there arent
    265 any surprises that could hide your application on Google Play.  This is actually quite simple using the
    266 "aapt" tool.  Aapt (the Android Asset Packaging Tool) is part of the build process for creating and
    267 packaging your Android applications, and is also a very handy tool for inspecting them. </p>
    268 
    269 <pre class="no-pretty-print classic">
    270 &gt;aapt dump badging
    271 package: name='com.example.hello' versionCode='1' versionName='1.0'
    272 sdkVersion:'11'
    273 uses-permission:'android.permission.SEND_SMS'
    274 application-label:'Hello'
    275 application-icon-120:'res/drawable-ldpi/icon.png'
    276 application-icon-160:'res/drawable-mdpi/icon.png'
    277 application-icon-240:'res/drawable-hdpi/icon.png'
    278 application: label='Hello' icon='res/drawable-mdpi/icon.png'
    279 launchable-activity: name='com.example.hello.HelloActivity'  label='Hello' icon=''
    280 uses-feature:'android.hardware.telephony'
    281 uses-feature:'android.hardware.touchscreen'
    282 main
    283 supports-screens: 'xlarge'
    284 supports-any-density: 'true'
    285 locales: '--_--'
    286 densities: '120' '160' '240'
    287 </pre>
    288 
    289 <p>When you examine aapt output, be sure to check that you dont have conflicting values for
    290 supports-screens and compatible-screens, and that you dont have unintended "uses-feature" values
    291 that were added as a result of permissions you set in the manifest. In the example above, the APK
    292 will be invisible to most, if not all devices.</p>
    293 <p>Why?  By adding the required permission SEND_SMS, the feature requirement of android.hardware.telephony was implicitly added.  Since most (if not all) xlarge devices are tablets without telephony hardware in them, Google Play will filter out this APK in these cases, until future devices come along which are both large enough to report as xlarge screen size, and possess telephony hardware.  
    294 </p>
    295 <p>Fortunately this is easily fixed by adding the following to your manifest:</p>
    296 <pre>
    297 &lt;uses-feature android:name="android.hardware.telephony" android:required="false" /&gt;
    298 </pre>
    299 <p>The <code>android.hardware.touchscreen</code> requirement is also implicitly added. If you want your APK to be visible on TVs which are non-touchscreen devices you should add the following to your manifest:</p>
    300 <pre>
    301 &lt;uses-feature android:name="android.hardware.touchscreen" android:required="false" /&gt;
    302 </pre>
    303 
    304 <p>Once youve completed the pre-launch checklist, upload your APKs to Google Play.  It may take a bit for the application to show up when browsing Google Play, but when it does, perform one last check.  Download the application onto any test devices you may have to make sure that the APKs are targeting the intended devices. Congratulations, youre done!</p>
    305