mozilla

Revision 545883 of Open Web Apps for Android: Synthetic APKs

  • Revision slug: Mozilla/Marketplace/Publishing/Open_web_apps_for_android
  • Revision title: Open Web Apps for Android: Synthetic APKs
  • Revision id: 545883
  • Created:
  • Creator: maedca
  • Is current revision? No
  • Comment

Revision Content

Los usuarios can install your apps from Marketplace into the Firefox browser or Firefox OS, gaining the benefit of powerful open web features. However, Android users may be more comfortable installing your apps as 'normal' Android apps. You're now able to offer users this feature using Synthetic APKs (also known as Web runtime for Android), a solution available on the Firefox Marketplace that creates native APKs for installation on Android devices.

What is a Synthetic APK?

A synthetic APK is an Open Web App packaged into an Android installation package, which can then be installed and run the same as any other Android app. The APK package consists of web content (in the case of packaged apps) or a pointer to web content (in the case of hosted apps). This content is then enclosed in a thin Java/Android wrapper which provides for the integration with the native OS.

These packages are created by the APK Factory Service which is run as a web service by Marketplace. The APK Factory Service makes use of the APK Factory Library to create the actual package and APK Signer to digitally sign the APK. This service is available to your own Marketplace, should you choose to create one.

You don't need any knowledge of Android development, or to take any extra development steps, to use a synthetic APK: you simply select the APK option when submitting your apps to Marketplace.

Note: Synthetic APKs are supported by Android devices with Firefox 29 or later installed.

The Open Web App runtime on Android supports 12 APIs to access device capabilities such as vibration, geolocation, battery status, and more. You can see a complete list of supported APIs here: APIs showing "A" under "Availability" are those APIs available on Android, with green cells indicating that the API is available in full. You can also mouseover individual cells to get tooltips containing more information.

The runtime on Android will continue to add support for other APIs in future releases. Some of the APIs planned are:

  • Alarm API
  • SimplePush API
  • Web Activities

Note: Android users may be using devices with a higher resolutions (DPI) and larger screen sizes than those found on Firefox OS devices. Apps that haven't used responsive design may therefore provide a poor experience, and you may want to design your apps with this in mind.

Using synthetic APKs

This section provides details on how you choose to make use of synthetic APKs, how they affect the Marketplace experience, and information on app updates.

Activating the synthetic APK option

When you submit an app to the Firefox Marketplace, you get the option of making your app available as a ‘native’ app for Android devices using a synthetic APK.

Submitting an app

When you submit an app to Marketplace the APK Factory Service is invoked to create a synthetic APK signed in Android debug mode. This version of the APK is then made available to the app reviewers to complete the normal review process. Once the app has been reviewed and approved the APK Factory service is invoked again, this time to sign the synthetic APK with a unique APK Signing Key. The resulting signed Synthetic APK is then cached for delivery when a user chooses to install the app.

Installing a synthetic APK

Once your app has been approved, when a user selects your app in the Marketplace on their Android device installation differs slightly from the normal process, as follows:

  1. Firefox Marketplace displays the app's information and install button as normal.
  2. When the user selects install they're shown the standard Marketplace install confirmation dialog. The dialog lists the permissions requested by privileged apps and information about the need to enable the option to install apps from “unknown sources”; the Marketplace will include wording to explain any concerns users may have.
  3. When the user confirms that they want to continue with the installation, {{ domxref("Apps.install") }} / {{ domxref("Apps.installPackage") }} are invoked as you'd expect (depending on whether it's a hosted or packaged app), however instead of the normal process by which the Open Web App version is installed, a call is made to the APK Factory Service to request the cached APK. The synthetic APK is then downloaded to the Android device and the standard Android app installation process invoked.

Once the synthetic APK has been installed, the user will find the application in their Apps menu and the process to use and remove the apps will be the same as they'd expect from other Android apps.

Keeping apps up-to-date

The Marketplace and the APK Factory also provides a mechanism for updating your app and letting users know the update is available.

If your app is hosted, whenever you make a change on its server users will pick up those changes the next time they run your app. If you make a change to your app manifest, such as making a change to the app's icon, after detecting the updated version number in the app’s manifest file APK factory will create an updated APK and notify users that an update is available.

For packaged apps you update the app’s content and submit an new package zip file and updated manifest. The APK Factory will pick up those changes and notify your users that an updated app is available.

How the APK Factory works

This section describes how the APK Factory creates synthetic APKs.

  1. When the APK factory is invoked, as described above, it detects whether the app is hosted or packaged, then requests the app's manifest file from the hosting server (the Firefox Marketplace, or wherever else the app is hosted):
    • The main manifest in the case of hosted apps.
    • The mini manifest in the case of packaged apps.
  2. The APK factory now has the information it needs about the app, and requests the:
    • Apps hosting URL in the case of hosted apps.
    • The app's zip archive from the marketplace in the case of packaged apps.
  3. Now the APK Factory service creates the synthetic APK by performing some metadata transcoding for elements such as icons and security requirements, then:
    • wrapping the hosting URL in a Android Java container for hosted apps
    • wrapping the app's content in a Android Java container for packaged apps.
  4. Once created, the synthetic APK is signed by a secure APK Signer service:
    • For "review" APKs are signed in Android debug mode.
    • For "release" APKs are signed with an APK signing key.
  5. Finally, the signed APK is cached for delivery to:
    • the app review process.
    • an Android device when the user requests installation from Marketplace.

The following diagrams offer an alternative representation of the workflow of the APK Factory. First, a packaged app:

Now, for a hosted app:

Package naming and APK signing keys

On installation of a synthetic APK the Android device checks the Java package name and signature. It verifies the signature the first time an app is installed (there is no central authority it checks with) and future updates must then have the same package name and signature. If the package name and signature aren't the same the Android device won't update the installation.

Package naming

The package name for a synthetic APK consist of the hosting site and a unique serial number, for example:

  • for a hosted app: org.mykzilla.p362b12c70d0556c124908a3c125d3d02:
  • for a package app: com.firefox.marketplace.p0604c71abc0d4091829d19be9a50453c

APK signing keys

Each APK needs to be identified by an APK signing key before it can be installed on an Android device. APK signing keys are created and owned by the APK Signer service. These signing keys are sensitive, and stored securely in the APK Signer, which is why it is considered "secure".

This service creates a unique key for each app, applying it to the original release and subsequent updates. The reuse of the key on updated app APKs is important as without a match in the package name and key Android won't install an update over an earlier version of the app. If you create your own version of Marketplace the APK will retain the same name and keys, so that either version will be able to update the other.

Note: Mozilla assumes no responsibility for the credibility of the APK signing keys, meaning that the keys provide no information about the authenticity of the app or developer beyond the fact that they have been approved for release in Marketplace. The service is not tied to Google or any other central authority.

FAQ

Here are answers to some frequently asked questions about Synthetic APKs.

What about re-installation of apps installed as bookmarks?

This hasn't been fully realized yet, but the expected behavior is that bookmark-style apps will stop working when the user updates to a version of Firefox for Android with the Synthetic APK implementation (version 29 or later). The user will then have to reinstall their apps to use them again.

How will in-app purchases work?

The APK is given access to the trusted UI, mozPay, and all payment processes for in-app purchases, so in-app payments will function as normal.

How do I download a copy of my app's APK?

You can download a copy of your app using wget and the following command:

https://controller.apk.firefox.com/application.apk?manifestUrl=ESCAPED_URL_TO_MANIFEST

where ESCAPED_URL_TO_MANIFEST is an escaped URL to the app's manifest or mini-manifest. That URL causes the APK Factory to return the cached copy of the APK, or create a new one if the app hasn't been submitted to Marketplace. If the app hasn't been submitted to Marketplace the APK is signed in debug mode.

Examples

For a hosted app:

> wget https://controller.apk.firefox.com/application.apk?manifestUrl=http%3A%2F%2Fmykzilla.org%2Fapp%2Fmanifest.webapp -O mykzilla.apk
> aapt dump --values badging mykzilla.apk
package: name='org.mykzilla.p362b12c70d0556c124908a3c125d3d02' versionCode='1395692586' versionName=''

For a packaged app:

> wget https://controller.apk.firefox.com/application.apk?manifestUrl=https%3A%2F%2Fmarketplace.firefox.com%2Fapp%2Fa22e0277-35bc-434d-9371-1568c75fc726%2Fmanifest.webapp -O cuttherope.apk
> aapt dump --values badging cuttherope.apk
package: name='com.firefox.marketplace.p0604c71abc0d4091829d19be9a50453c' versionCode='1394154656' versionName='1.3'

Can I generate a synthetic APK manually from a different URL?

Yes you can, by providing the URL to any location for your manifest or mini-manifest files. However, be aware that because the synthetic APK is generated from different URL the package name will differ from that created when you submit the app to Marketplace, so the Marketplace version will be installed as a separate app.

If I setup my own copy of APK Factory can I use the synthetic APK it generates?

You can, but be aware that the signing keys will differ from those assigned to a version of the synthetic APK generated by Marketplace. As a result Android will refuse to install whichever version the user tries to install second. (See If I also have an Android native version of my app, can both be installed on an Android device? for more information.)

Can I submit a synthetic APK to Google Play or other Android store?

You can submit a synthetic APK to Google Play or an alternative Android store. However, it's your responsibility to:

  • Confirm that your app complies with the policies of the store you're submitting it to. Approval for distribution in Marketplace doesn't imply any approval for Google Play or another Android Marketplace.
  • When you update your Open Web App you'll have to update the synthetic APK on any stores you have submitted the APK to, there is no automatic process to deliver updated APKs to Android stores.

Can I use my Android signing keys to sign the synthetic APK and choose the package name?

At present you cannot use your own signing keys to sign a synthetic APK or choose the package name. This is an option being considered. If this is of interest to you, join the discussion on the dev-marketplace mailing list, or the Marketplace IRC channel.

If I also have an Android native version of my app, can both be installed on an Android device?

Unless you choose to use the synthetic APK package name for your native Android app, both can be installed on an Android device. If you choose to use the same package name for your native Android app (which you'll sign with your own key) Android will refuse to install whichever version the user tries to install second. This is because the package names are the same but the signing keys are different, so Android considers the apps to be the same, but from different sources. Therefore Android will refuse to update one app with the other, since that would allow one developer to override another's app. The user will end up with the first version installed on their device.

Because of the issues it may cause for users, it's highly recommedned that you don't reuse the package name the APK Factory assigns to your app for a native Android version of your app.

How can I test/debug APKs?

We're working on a toolchain for testing and debugging an app on an Android device. The initial version will include a Node-based command-line tool for generating an APK you can install on the device and debug using Firefox's Remote Developer Tools.

Revision Source

<div class="summary">
 <p>Los usuarios can install your apps from Marketplace into the Firefox browser or Firefox OS, gaining the benefit of powerful open web features. However, Android users may be more comfortable installing your apps as 'normal' Android apps. You're now able to offer users this feature using Synthetic APKs (also known as <strong>Web runtime for Android</strong>), a solution available on the <a href="https://marketplace.firefox.com/">Firefox Marketplace</a> that creates native APKs for installation on Android devices.</p>
</div>
<h2 id="What_is_a_Synthetic_APK.3F">What is a Synthetic APK?</h2>
<p>A synthetic APK is an Open Web App packaged into an Android installation package, which can then be installed and run the same as any other Android app. The APK package consists of web content (in the case of packaged apps) or a pointer to web content (in the case of hosted apps). This content is then enclosed in a thin Java/Android wrapper which provides for the integration with the native OS.</p>
<p>These packages are created by the <a href="https://github.com/mozilla/apk-factory-service">APK Factory Service</a> which is run as a web service by Marketplace. The APK Factory Service makes use of the <a href="https://github.com/mozilla/apk-factory-library">APK Factory Library</a> to create the actual package and <a href="https://github.com/mozilla/apk-signer">APK Signer</a> to digitally sign the APK. This service is available to <a href="/en-US/Marketplace/Publishing/Creating_a_store">your own Marketplace</a>, should you choose to create one.</p>
<p>You don't need any knowledge of Android development, or to take any extra development steps, to use a synthetic APK: you simply select the APK option when submitting your apps to Marketplace.</p>
<div class="note">
 <p><strong>Note</strong>: Synthetic APKs are supported by Android devices with Firefox 29 or later installed.</p>
</div>
<p>The Open Web App runtime on Android supports 12 APIs to access device capabilities such as vibration, geolocation, battery status, and more. You can see a <a href="https://wiki.mozilla.org/WebAPI#APIs">complete list of supported APIs here</a>: APIs showing "A" under "Availability" are those APIs available on Android, with green cells indicating that the API is available in full. You can also mouseover individual cells to get tooltips containing more information.</p>
<p>The runtime on Android will continue to add support for other APIs in future releases. Some of the APIs planned are:</p>
<ul>
 <li>Alarm API</li>
 <li>SimplePush API</li>
 <li>Web Activities</li>
</ul>
<div class="note">
 <p><strong>Note</strong>: Android users may be using devices with a higher resolutions (DPI) and larger screen sizes than those found on Firefox OS devices. Apps that haven't used responsive design may therefore provide a poor experience, and you may want to design your apps with this in mind.</p>
</div>
<h2 id="Using_synthetic_APKs">Using synthetic APKs</h2>
<p>This section provides details on how you choose to make use of synthetic APKs, how they affect the Marketplace experience, and information on app updates.</p>
<h3 id="Activating_the_synthetic_APK_option">Activating the synthetic APK option</h3>
<p>When you <a href="/en-US/Marketplace/Submission/Submitting_an_app">submit an app to the Firefox Marketplace</a>, you get the option of making your app available as a ‘native’ app for Android devices using a synthetic APK.</p>
<h3 id="Submitting_an_app">Submitting an app</h3>
<p>When you submit an app to Marketplace the APK Factory Service is invoked to create a synthetic APK signed in Android debug mode. This version of the APK is then made available to the app reviewers to complete the normal review process. Once the app has been reviewed and approved the APK Factory service is invoked again, this time to sign the synthetic APK with a unique APK Signing Key. The resulting signed Synthetic APK is then cached for delivery when a user chooses to install the app.</p>
<h3 id="Installing_a_synthetic_APK">Installing a synthetic APK</h3>
<p>Once your app has been approved, when a user selects your app in the Marketplace on their Android device installation differs slightly from the normal process, as follows:</p>
<ol>
 <li><a href="https://marketplace.firefox.com/">Firefox Marketplace</a> displays the app's information and install button as normal.</li>
 <li>When the user selects install they're shown the standard Marketplace install confirmation dialog. The dialog lists the permissions requested by privileged apps and information about the need to enable the option to install apps from “unknown sources”; the Marketplace will include wording to explain any concerns users may have.</li>
 <li>When the user confirms that they want to continue with the installation, {{ domxref("Apps.install") }} / {{ domxref("Apps.installPackage") }} are invoked as you'd expect (depending on whether it's a hosted or packaged app), however instead of the normal process by which the Open Web App version is installed, a call is made to the APK Factory Service to request the cached APK. The synthetic APK is then downloaded to the Android device and the standard Android app installation process invoked.</li>
</ol>
<p>Once the synthetic APK has been installed, the user will find the application in their Apps menu and the process to use and remove the apps will be the same as they'd expect from other Android apps.</p>
<h3 id="Keeping_apps_up-to-date">Keeping apps up-to-date</h3>
<p>The Marketplace and the APK Factory also provides a mechanism for updating your app and letting users know the update is available.</p>
<p>If your app is hosted, whenever you make a change on its server users will pick up those changes the next time they run your app. If you make a change to your app manifest, such as making a change to the app's icon, after detecting the updated version number in the app’s manifest file APK factory will create an updated APK and notify users that an update is available.</p>
<p>For packaged apps you update the app’s content and submit an new package zip file and updated manifest. The APK Factory will pick up those changes and notify your users that an updated app is available.</p>
<h2 id="How_the_APK_Factory_works">How the APK Factory works</h2>
<p>This section describes how the APK Factory creates synthetic APKs.</p>
<ol>
 <li>When the APK factory is invoked, as described above, it detects whether the app is hosted or packaged, then requests the app's manifest file from the hosting server (the Firefox Marketplace, or wherever else the app is hosted):
  <ul>
   <li>The main manifest in the case of hosted apps.</li>
   <li>The mini manifest in the case of packaged apps.<span id="cke_bm_343E" style="display: none;">&nbsp;</span></li>
  </ul>
 </li>
 <li>The APK factory now has the information it needs about the app, and requests the:
  <ul>
   <li>Apps hosting URL in the case of hosted apps.</li>
   <li>The app's zip archive from the marketplace in the case of packaged apps.</li>
  </ul>
 </li>
 <li>Now the APK Factory service creates the synthetic APK by performing some metadata transcoding for elements such as icons and security requirements, then:
  <ul>
   <li>wrapping the hosting URL in a Android Java container for hosted apps</li>
   <li>wrapping the app's content in a Android Java container for packaged apps.</li>
  </ul>
 </li>
 <li>Once created, the synthetic APK is signed by a secure <strong><a href="https://github.com/mozilla/apk-signer">APK Signer</a></strong> service:
  <ul>
   <li>For "review" APKs are signed in Android debug mode.</li>
   <li>For "release" APKs are signed with an <strong>APK signing key</strong>.</li>
  </ul>
 </li>
 <li>Finally, the signed APK is cached for delivery to:
  <ul>
   <li>the app review process.</li>
   <li>an Android device when the user requests installation from Marketplace.</li>
  </ul>
 </li>
</ol>
<p>The following diagrams offer an alternative representation of the workflow of the APK Factory. First, a packaged app:</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/7315/synthapkflow-packaged.png" style="width: 540px; height: 522px; display: block; margin: 0px auto;" /></p>
<p>Now, for a hosted app:</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/7313/synthapkflow-hosted.png" style="width: 678px; height: 525px; margin: 0px auto; display: block;" /></p>
<h2 id="Package_naming_and_APK_signing_keys">Package naming and APK signing keys</h2>
<p>On installation of a synthetic APK the Android device checks the Java package name and signature. It verifies the signature the first time an app is installed (there is no central authority it checks with) and future updates must then have the same package name and signature. If the package name and signature aren't the same the Android device won't update the installation.</p>
<h3 id="Package_naming">Package naming</h3>
<p>The package name for a synthetic APK consist of the hosting site and a unique serial number, for example:</p>
<ul>
 <li>for a hosted app: org.mykzilla.p362b12c70d0556c124908a3c125d3d02:</li>
 <li>for a package app: com.firefox.marketplace.p0604c71abc0d4091829d19be9a50453c</li>
</ul>
<h3 id="APK_signing_keys">APK signing keys</h3>
<p>Each APK needs to be identified by an APK signing key before it can be installed on an Android device. APK signing keys are created and owned by the <strong><a href="https://github.com/mozilla/apk-signer">APK Signer</a> service</strong>. These signing keys are sensitive, and stored securely in the APK Signer, which is why it is considered "secure".</p>
<p>This service creates a unique key for each app, applying it to the original release and subsequent updates. The reuse of the key on updated app APKs is important as without a match in the package name and key Android won't install an update over an earlier version of the app. If you create your own version of Marketplace the APK will retain the same name and keys, so that either version will be able to update the other.</p>
<div class="note">
 <p><strong>Note</strong>: Mozilla assumes no responsibility for the credibility of the APK signing keys, meaning that the keys provide no information about the authenticity of the app or developer beyond the fact that they have been approved for release in Marketplace. The service is not tied to Google or any other central authority.</p>
</div>
<h2 id="FAQ">FAQ</h2>
<p>Here are answers to some frequently asked questions about Synthetic APKs.</p>
<h3 id="What_about_re-installation_of_apps_installed_as_bookmarks.3F">What about re-installation of apps installed as bookmarks?</h3>
<p>This hasn't been fully realized yet, but the expected behavior is that bookmark-style apps will stop working when the user updates to a version of Firefox for Android with the Synthetic APK implementation (version 29 or later). The user will then have to reinstall their apps to use them again.</p>
<h3 id="How_will_in-app_purchases_work.3F">How will in-app purchases work?</h3>
<p>The APK is given access to the trusted UI, <a href="/en-US/docs/Web/API/Navigator.mozPay">mozPay</a>, and all payment processes for in-app purchases, so in-app payments will function as normal.</p>
<h3 id="How_do_I_download_a_copy_of_my_app's_APK.3F">How do I download a copy of my app's APK?</h3>
<p>You can download a copy of your app using wget and the following command:</p>
<p><code>https://controller.apk.firefox.com/application.apk?manifestUrl=ESCAPED_URL_TO_MANIFEST</code></p>
<p>where ESCAPED_URL_TO_MANIFEST is an escaped URL to the app's manifest or mini-manifest. That URL causes the APK Factory to return the cached copy of the APK, or create a new one if the app hasn't been submitted to Marketplace. If the app hasn't been submitted to Marketplace the APK is signed in debug mode.</p>
<h4 id="Examples">Examples</h4>
<p>For a hosted app:</p>
<p><code>&gt; wget https://controller.apk.firefox.com/application.apk?manifestUrl=http%3A%2F%2Fmykzilla.org%2Fapp%2Fmanifest.webapp -O mykzilla.apk<br />
 &gt; aapt dump --values badging mykzilla.apk<br />
 package: name='org.mykzilla.p362b12c70d0556c124908a3c125d3d02' versionCode='1395692586' versionName=''</code></p>
<p>For a packaged app:</p>
<p><code>&gt; wget https://controller.apk.firefox.com/application.apk?manifestUrl=https%3A%2F%2Fmarketplace.firefox.com%2Fapp%2Fa22e0277-35bc-434d-9371-1568c75fc726%2Fmanifest.webapp -O cuttherope.apk<br />
 &gt; aapt dump --values badging cuttherope.apk<br />
 package: name='com.firefox.marketplace.p0604c71abc0d4091829d19be9a50453c' versionCode='1394154656' versionName='1.3'</code></p>
<h3 id="Can_I_generate_a_synthetic_APK_manually_from_a_different_URL.3F">Can I generate a synthetic APK manually from a different URL?</h3>
<p>Yes you can, by providing the URL to any location for your manifest or mini-manifest files. However, be aware that because the synthetic APK is generated from different URL the package name will differ from that created when you submit the app to Marketplace, so the Marketplace version will be installed as a separate app.</p>
<h3 id="If_I_setup_my_own_copy_of_APK_Factory_can_I_use_the_synthetic_APK_it_generates.3F">If I setup my own copy of APK Factory can I use the synthetic APK it generates?</h3>
<p>You can, but be aware that the signing keys will differ from those assigned to a version of the synthetic APK generated by Marketplace. As a result Android will refuse to install whichever version the user tries to install second. (See <a href="https://developer.mozilla.org/en-US/Marketplace/Publishing/Open_web_apps_for_android#If_I_also_have_an_Android_native_version_of_my_app.2C_can_both_be_installed_on_an_Android_device.3F">If I also have an Android native version of my app, can both be installed on an Android device?</a> for more information.)</p>
<h3 id="Can_I_submit_a_synthetic_APK_to_Google_Play_or_other_Android_store.3F">Can I submit a synthetic APK to Google Play or other Android store?</h3>
<p>You can submit a synthetic APK to Google Play or an alternative Android store. However, it's your responsibility to:</p>
<ul>
 <li>Confirm that your app complies with the policies of the store you're submitting it to. Approval for distribution in Marketplace doesn't imply any approval for Google Play or another Android Marketplace.</li>
 <li>When you update your Open Web App you'll have to update the synthetic APK on any stores you have submitted the APK to, there is no automatic process to deliver updated APKs to Android stores.</li>
</ul>
<h3 id="Can_I_use_my_Android_signing_keys_to_sign_the_synthetic_APK_and_choose_the_package_name.3F">Can I use my Android signing keys to sign the synthetic APK and choose the package name?</h3>
<p>At present you cannot use your own signing keys to sign a synthetic APK or choose the package name. This is an option being considered. If this is of interest to you, join the discussion on the <a href="https://lists.mozilla.org/listinfo/dev-marketplace">dev-marketplace mailing list</a>, or the <a href="irc://irc.mozilla.org/marketplace">Marketplace IRC channel</a>.</p>
<h3 id="If_I_also_have_an_Android_native_version_of_my_app.2C_can_both_be_installed_on_an_Android_device.3F">If I also have an Android native version of my app, can both be installed on an Android device?</h3>
<p>Unless you choose to use the synthetic APK package name for your native Android app, both can be installed on an Android device. If you choose to use the same package name for your native Android app (which you'll sign with your own key) Android will refuse to install whichever version the user tries to install second. This is because the package names are the same but the signing keys are different, so Android considers the apps to be the same, but from different sources. Therefore Android will refuse to update one app with the other, since that would allow one developer to override another's app. The user will end up with the first version installed on their device.</p>
<div class="warning">
 <p>Because of the issues it may cause for users, it's highly recommedned that you don't reuse the package name the APK Factory assigns to your app for a native Android version of your app.</p>
</div>
<h3 id="How_can_I_test.2Fdebug_APKs.3F">How can I test/debug APKs?</h3>
<p>We're working on a toolchain for testing and debugging an app on an Android device. The initial version will include a Node-based command-line tool for generating an APK you can install on the device and debug using Firefox's Remote Developer Tools.</p>
Revert to this revision