Home | History | Annotate | Download | only in multiple-apks
      1 page.title=Creating Multiple APKs for Different API Levels
      2 parent.title=Maintaining Multiple APKs
      3 parent.link=index.html
      4 
      5 trainingnavtop=true
      6 next.title=Creating Multiple APKs for Different Screen Sizes
      7 next.link=screensize.html
      8 
      9 @jd:body
     10 
     11 <style type="text/css">
     12 .blueCell { background-color: #9fc5e8;}
     13 .greenCell { background-color: #b6d7a8;}
     14 .redCell { background-color: #ea9999;}
     15 .blackCell { background-color: #000000;}
     16 </style>
     17 
     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   <li><a
     39 href="http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html">
     40 How to have your (Cup)cake and eat it too</a></li>
     41 </ul>
     42 
     43 </div>
     44 </div>
     45 
     46 
     47 <p>When developing your Android application to take advantage of multiple APKs on Google Play,
     48 its important to adopt some good practices from the get-go, and prevent unnecessary headaches
     49 further into the development process.  This lesson shows you how to create multiple APKs of your
     50 app, each covering a slightly different range of API levels.  You will also gain some tools
     51 necessary to make maintaining a multiple APK codebase as painless as possible.</p>
     52 
     53 
     54 <h2 id="Confirm">Confirm You Need Multiple APKs</h2>
     55 
     56 <p>When trying to create an application that works across multiple generations of the Android
     57 platform, naturally you want your application to take advantage of new features on new devices,
     58 without sacrificing backwards compatibility.  It may seem at the outset as though multiple APK
     59 support is the best solution, but this often isnt the case.  The <a
     60 href="{@docRoot}google/play/publishing/multiple-apks.html#ApiLevelOptions">Using Single APK
     61 Instead</a> section of the multiple APK developer guide includes some useful information on how to
     62 accomplish this with a single APK, including use of our support library. You can also learn how to
     63 write code that runs only at certain API levels in a single APK, without resorting to
     64 computationally expensive techniques like reflection from  <a
     65 href="http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html">
     66 this article</a>.</p>
     67 
     68 <p>If you can manage it, confining your application to a single APK has several
     69 advantages, including:</p>
     70 
     71 <ul>
     72 <li>Publishing and testing are easier</li>
     73 <li>Theres only one codebase to maintain</li>
     74 <li>Your application can adapt to device configuration changes</li>
     75 <li>App restore across devices just works</li>
     76 <li>You dont have to worry about market preference, behavior from "upgrades" from one APK to the
     77 next, or which APK goes with which class of devices
     78 </ul>
     79 
     80 <p>The rest of this lesson assumes that youve researched the topic, studiously absorbed the
     81 material in the resources linked, and determined that multiple APKs are the right path for your
     82 application.</p>
     83 
     84 <h2 id="ChartReqs">Chart Your Requirements</h2>
     85 
     86 <p>Start off by creating a simple chart to quickly determine how many APKs you need, and what API
     87 range each APK covers.  For handy reference, the <a
     88 href="{@docRoot}about/dashboards/index.html">Platform Versions</a> page of the
     89 Android Developer website provides data about the relative number of active devices running a given
     90 version of the Android platform.  Also, although it sounds easy at first, keeping track of which set
     91 of API levels each APK is going to target gets difficult rather quickly, especially if theres going
     92 to be some overlap (there often is).  Fortunately, its easy to chart out your requirements quickly,
     93 easily, and have an easy reference for later.</p>
     94 
     95 <p>In order to create your multiple APK chart, start out with a row of cells representing the
     96 various API levels of the Android platform.  Throw an extra cell at the end to represent future
     97 versions of Android.</p>
     98 <table cellpadding="10" cellspacing="0" border="1">
     99   <tbody>
    100     <tr>
    101       <td>3</td>
    102       <td>4</td>
    103       <td>5</td>
    104       <td>6</td>
    105       <td>7</td>
    106       <td>8</td>
    107       <td>9</td>
    108       <td>10</td>
    109       <td>11</td>
    110       <td>12</td>
    111       <td>13</td>
    112       <td>+</td>
    113     </tr>
    114   </tbody>
    115 </table>
    116 
    117 <p>Now just color in the chart such that each color represents an APK.  Heres one example of how
    118 you might apply each APK to a certain range of API levels.</p>
    119 
    120 <table cellpadding="10" cellspacing="0" border="1">
    121   <tbody>
    122     <tr>
    123       <td class="blueCell">3</td>
    124       <td class="blueCell">4</td>
    125       <td class="blueCell">5</td>
    126       <td class="blueCell">6</td>
    127       <td class="greenCell">7</td>
    128       <td class="greenCell">8</td>
    129       <td class="greenCell">9</td>
    130       <td class="greenCell">10</td>
    131       <td class="redCell">11</td>
    132       <td class="redCell">12</td>
    133       <td class="redCell">13</td>
    134       <td class="redCell">+</td>
    135     </tr>
    136   </tbody>
    137 </table>
    138 
    139 <p>Once youve created this chart, distribute it to your team.  Team communication on your project
    140 just got immediately simpler, since instead of asking "Hows the APK for API levels 3 to 6, er, you
    141 know, the Android 1.x one.  Hows that coming along?"  You can simply say "Hows the Blue APK coming
    142 along?"</p>
    143 
    144 <h2 id="CreateLibrary">Put All Common Code and Resources in a Library Project</h2>
    145 <p>Whether youre modifying an existing Android application or starting one from scratch, this is
    146 the first thing that you should do to the codebase, and by the far the most important.  Everything
    147 that goes into the library project only needs to be updated once (think language-localized strings,
    148 color themes, bugs fixed in shared code), which improves your development time and reduces the
    149 likelihood of mistakes that could have been easily avoided.</p>
    150 
    151 <p class="note"><strong>Note:</strong>  While the implementation details of how to create and
    152 include library projects are beyond the scope of this lesson, you can get up to speed quickly on
    153 their creation at the following links:</p>
    154 <ul>
    155 <li><a
    156 href="{@docRoot}tools/projects/projects-eclipse.html#SettingUpLibraryProject">Setting up
    157 a library project (Eclipse)</a></li>
    158 <li><a
    159 href="{@docRoot}tools/projects/projects-cmdline.html#SettingUpLibraryProject">Setting up
    160 a library project (Command line)</a></li>
    161 </ul>
    162 
    163 
    164 <p>If youre converting an existing application to use multiple APK support,
    165 scour your codebase for every localized string file, list of values, theme
    166 colors, menu icons and layout that isnt going to change across APKs, and put
    167 it all in the library project.  Code that isnt going to change much should
    168 also go in the library project.  Youll likely find yourself extending these
    169 classes to add a method or two from APK to APK.</p>
    170 
    171 <p>If, on the other hand, youre creating the application from scratch, try as
    172 much as possible to write code in the library project <em>first</em>, then only move it down to an
    173 individual APK if necessary.  This is much easier to manage in the long run than adding it to one,
    174 then another, then another, then months later trying to figure out whether this blob can be moved up
    175 to the library section without screwing anything up.</p>
    176 
    177 <h2 id="CreateAPKs">Create New APK Projects</h2>
    178 <p>There should be a separate Android project for each APK youre going to release.  For easy
    179 organization, place the library project and all related APK projects under the same parent folder. 
    180 Also remember that each APK needs to have the same package name, although they dont necessarily
    181 need to share the package name with the library.  If you were to have 3 APKs following the scheme
    182 described earlier, your root directory might look like this:</p>
    183 
    184 <pre class="no-pretty-print classic">
    185 alexlucas:~/code/multi-apks-root$ ls
    186 foo-blue
    187 foo-green
    188 foo-lib
    189 foo-red
    190 </pre>
    191 
    192 <p>Once the projects are created, add the library project as a reference to each APK project.  If
    193 possible, define your starting Activity in the library project, and extend that Activity in your APK
    194 project.  Having a starting activity defined in the library project gives you a chance to put all
    195 your application initialization in one place, so that each individual APK doesnt have to
    196 re-implement "universal" tasks like initializing Analytics, running licensing checks, and any other
    197 initialization procedures that dont change much from APK to APK.</p>
    198 
    199 
    200 <h2 id="AdjustManifests">Adjust the Manifests</h2>
    201 <p>When a user downloads an application which uses multiple APKs through Google Play, the correct
    202 APK to use is chosen using two simple rules:</p>
    203 <ul>
    204 <li>The manifest has to show that particular APK is eligible</li>
    205 <li>Of the eligible APKs, highest version number wins</li>
    206 </ul>
    207 <p>
    208 By way of example, lets take the set of multiple APKs described earlier, and assume that we havent
    209 set a max API level for any of the APKs.  Taken individually, the possible range of each APK would
    210 look like this:</p>
    211 <table cellpadding="10" cellspacing="0" border="1">
    212   <tbody>
    213     <tr>
    214       <td class="blueCell">3</td>
    215       <td class="blueCell">4</td>
    216       <td class="blueCell">5</td>
    217       <td class="blueCell">6</td>
    218       <td class="blueCell">7</td>
    219       <td class="blueCell">8</td>
    220       <td class="blueCell">9</td>
    221       <td class="blueCell">10</td>
    222       <td class="blueCell">11</td>
    223       <td class="blueCell">12</td>
    224       <td class="blueCell">13</td>
    225       <td class="blueCell">+</td>
    226     </tr>
    227     <tr>
    228       <td class="blackCell">3</td>
    229       <td class="blackCell">4</td>
    230       <td class="blackCell">5</td>
    231       <td class="blackCell">6</td>
    232       <td class="greenCell">7</td>
    233       <td class="greenCell">8</td>
    234       <td class="greenCell">9</td>
    235       <td class="greenCell">10</td>
    236       <td class="greenCell">11</td>
    237       <td class="greenCell">12</td>
    238       <td class="greenCell">13</td>
    239       <td class="greenCell">+</td>
    240     </tr>
    241     <tr>
    242       <td class="blackCell">3</td>
    243       <td class="blackCell">4</td>
    244       <td class="blackCell">5</td>
    245       <td class="blackCell">6</td>
    246       <td class="blackCell">7</td>
    247       <td class="blackCell">8</td>
    248       <td class="blackCell">9</td>
    249       <td class="blackCell">10</td>
    250       <td class="redCell">11</td>
    251       <td class="redCell">12</td>
    252       <td class="redCell">13</td>
    253       <td class="redCell">+</td>
    254     </tr>
    255   </tbody>
    256 </table>
    257 <p>
    258 Because it is required that an APK with a higher minSdkVersion also have a
    259 higher version code, we know that in terms of versionCode values, red &#8805;
    260 green &#8805; blue.  Therefore we can effectively collapse the chart to look like this:</p>
    261 <table cellpadding="10" cellspacing="0" border="1">
    262   <tbody>
    263     <tr>
    264       <td class="blueCell">3</td>
    265       <td class="blueCell">4</td>
    266       <td class="blueCell">5</td>
    267       <td class="blueCell">6</td>
    268       <td class="greenCell">7</td>
    269       <td class="greenCell">8</td>
    270       <td class="greenCell">9</td>
    271       <td class="greenCell">10</td>
    272       <td class="redCell">11</td>
    273       <td class="redCell">12</td>
    274       <td class="redCell">13</td>
    275       <td class="redCell">+</td>
    276     </tr>
    277   </tbody>
    278 </table>
    279 
    280 <p>
    281 Now, lets further assume that the Red APK has some requirement on it that the other two dont.  
    282 <a href="{@docRoot}google/play/filters.html">Filters on Google Play</a> page of
    283 the Android Developer guide has a whole list of possible culprits.  For the
    284 sake of example, lets assume that red requires a front-facing camera.  In fact, the entire point of
    285 the red APK is to combine the front-facing camera with sweet new functionality that was added in API
    286 11.  But, it turns out, not all devices that support API 11 even HAVE front-facing cameras!  The
    287 horror!</p>
    288 
    289 <p>Fortunately, if a user is browsing Google Play from one such device, Google Play will look at the
    290 manifest, see that Red lists the front-facing camera as a requirement, and quietly ignore it, having
    291 determined that Red and that device are not a match made in digital heaven.  It will then see that
    292 Green is not only forward-compatible with devices with API 11 (since no maxSdkVersion was defined),
    293 but also doesnt care whether or not theres a front-facing camera!  The app can still be downloaded
    294 from Google Play by the user, because despite the whole front-camera mishap, there was still an
    295 APK that supported that particular API level.</p>
    296 
    297 <p>  In order to keep all your APKs on separate "tracks", its important to have a good version code
    298 scheme.  The recommended one can be found on the <a
    299 href="{@docRoot}google/play/publishing/multiple-apks.html#VersionCodes">Version Codes</a> area of
    300 our developer guide.  Since the example set of APKs is only dealing with one of 3 possible
    301 dimensions, it would be sufficient to separate each APK by 1000, set the first couple digits to the
    302 minSdkVersion for that particular APK, and increment from there.  This might look like:</p>
    303 
    304 <p>Blue: 03001, 03002, 03003, 03004...<br />
    305 Green: 07001, 07002, 07003, 07004...<br />
    306 Red:11001, 11002, 11003, 11004...</p>
    307 
    308 <p>  Putting this all together, your Android Manifests would likely look something like the following:</p>
    309 <p>Blue:</p>
    310 <pre>
    311 &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    312     android:versionCode="03001" android:versionName="1.0" package="com.example.foo"&gt;
    313     &lt;uses-sdk android:minSdkVersion="3" /&gt;
    314     ...
    315 </pre>
    316 
    317 <p>Green:</p>
    318 <pre>
    319 &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    320     android:versionCode="07001" android:versionName="1.0" package="com.example.foo"&gt;
    321     &lt;uses-sdk android:minSdkVersion="7" /&gt;
    322     ...
    323 </pre>
    324 
    325 <p>Red:</p>
    326 <pre>
    327 &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    328     android:versionCode="11001" android:versionName="1.0" package="com.example.foo"&gt;
    329     &lt;uses-sdk android:minSdkVersion="11" /&gt;
    330     ...
    331 </pre>
    332 
    333 <h2 id="PreLaunch">Go Over Pre-launch Checklist</h2>
    334 <p>  Before uploading to Google Play, double-check the following items.  Remember that these are specifically relevant to multiple APKs, and in no way represent a complete checklist for all applications being uploaded to Google Play.</p>
    335 
    336 <ul>
    337 <li>All APKs must have the same package name</li>
    338 <li>All APKs must be signed with the same certificate</li>
    339 <li>If the APKs overlap in platform version, the one with the higher minSdkVersion must have a higher version code</li>
    340 <li>Double check your manifest filters for conflicting information (an APK that only supports cupcake on XLARGE screens isnt going to be seen by anybody)</li>
    341 <li>Each APK's manifest must be unique across at least one of supported screen, openGL texture, or platform version</li>
    342 <li>Try to test each APK on at least one device.  Barring that, you have one of the most customizable device emulators in the business sitting on your development machine.  Go nuts!</li>
    343 </ul>
    344 
    345 <p>Its also worth inspecting the compiled APK before pushing to market, to make sure there arent
    346 any surprises that could hide your application on Google Play.  This is actually quite simple using the
    347 "aapt" tool.  Aapt (the Android Asset Packaging Tool) is part of the build process for creating and
    348 packaging your Android applications, and is also a very handy tool for inspecting them. </p>
    349 
    350 <pre class="no-pretty-print classic">
    351 &gt;aapt dump badging
    352 package: name='com.example.hello' versionCode='1' versionName='1.0'
    353 sdkVersion:'11'
    354 uses-permission:'android.permission.SEND_SMS'
    355 application-label:'Hello'
    356 application-icon-120:'res/drawable-ldpi/icon.png'
    357 application-icon-160:'res/drawable-mdpi/icon.png'
    358 application-icon-240:'res/drawable-hdpi/icon.png'
    359 application: label='Hello' icon='res/drawable-mdpi/icon.png'
    360 launchable-activity: name='com.example.hello.HelloActivity'  label='Hello' icon=''
    361 uses-feature:'android.hardware.telephony'
    362 uses-feature:'android.hardware.touchscreen'
    363 main
    364 supports-screens: 'small' 'normal' 'large' 'xlarge'
    365 supports-any-density: 'true'
    366 locales: '--_--'
    367 densities: '120' '160' '240'
    368 </pre>
    369 
    370 <p>When you examine aapt output, be sure to check that you dont have conflicting values for
    371 supports-screens and compatible-screens, and that you dont have unintended "uses-feature" values
    372 that were added as a result of permissions you set in the manifest. In the example above, the APK
    373 wont be visible to very many devices.</p>
    374 <p>Why?  By adding the required permission SEND_SMS, the feature requirement of android.hardware.telephony was implicitly added.  Since API 11 is Honeycomb (the version of Android optimized specifically for tablets), and no Honeycomb devices have telephony hardware in them, Google Play will filter out this APK in all cases, until future devices come along which are higher in API level AND possess telephony hardware.
    375 </p>
    376 <p>Fortunately this is easily fixed by adding the following to your manifest:</p>
    377 <pre>
    378 &lt;uses-feature android:name="android.hardware.telephony" android:required="false" /&gt;
    379 </pre>
    380 <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>
    381 <pre>
    382 &lt;uses-feature android:name="android.hardware.touchscreen" android:required="false" /&gt;
    383 </pre>
    384 <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>
    385