Files
react-native/docs/signed-apk-android.html
T
Website Deployment Script eff2e81bcd Deploy website
Deploy website version based on 758f18eacb099c9c124773a904992acf6da82a22
2020-05-30 10:22:48 +00:00

186 lines
36 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><title>Publishing to Google Play Store · React Native</title><meta name="viewport" content="width=device-width"/><meta name="generator" content="Docusaurus"/><meta name="description" content="Android requires that all apps be digitally signed with a certificate before they can be installed. In order to distribute your Android application via [Google Play store](https://play.google.com/store) it needs to be signed with a release key that then needs to be used for all future updates. Since 2017 it is possible for Google Play to manage signing releases automatically thanks to [App Signing by Google Play](https://developer.android.com/studio/publish/app-signing#app-signing-google-play) functionality. However, before your application binary is uploaded to Google Play it needs to be signed with an upload key. The [Signing Your Applications](https://developer.android.com/tools/publishing/app-signing.html) page on Android Developers documentation describes the topic in detail. This guide covers the process in brief, as well as lists the steps required to package the JavaScript bundle."/><meta name="docsearch:version" content="0.62"/><meta name="docsearch:language" content="en"/><meta property="og:title" content="Publishing to Google Play Store · React Native"/><meta property="og:type" content="website"/><meta property="og:url" content="https://reactnative.dev/"/><meta property="og:description" content="Android requires that all apps be digitally signed with a certificate before they can be installed. In order to distribute your Android application via [Google Play store](https://play.google.com/store) it needs to be signed with a release key that then needs to be used for all future updates. Since 2017 it is possible for Google Play to manage signing releases automatically thanks to [App Signing by Google Play](https://developer.android.com/studio/publish/app-signing#app-signing-google-play) functionality. However, before your application binary is uploaded to Google Play it needs to be signed with an upload key. The [Signing Your Applications](https://developer.android.com/tools/publishing/app-signing.html) page on Android Developers documentation describes the topic in detail. This guide covers the process in brief, as well as lists the steps required to package the JavaScript bundle."/><meta property="og:image" content="https://reactnative.dev/img/logo-og.png"/><meta name="twitter:card" content="summary"/><meta name="twitter:image" content="https://reactnative.dev/img/logo-og.png"/><link rel="shortcut icon" href="/img/favicon.ico"/><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css"/><link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/solarized-dark.min.css"/><link rel="alternate" type="application/atom+xml" href="https://reactnative.dev/blog/atom.xml" title="React Native Blog ATOM Feed"/><link rel="alternate" type="application/rss+xml" href="https://reactnative.dev/blog/feed.xml" title="React Native Blog RSS Feed"/><script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-41298772-2', 'auto');
ga('send', 'pageview');
</script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/focus-visible@5.0.2/dist/focus-visible.min.js"></script><script type="text/javascript" src="https://snack.expo.io/embed.js"></script><script type="text/javascript" src="https://platform.twitter.com/widgets.js"></script><script type="text/javascript" src="https://buttons.github.io/buttons.js"></script><script type="text/javascript" src="/js/codeblocks.js"></script><script type="text/javascript" src="/js/tabs.js"></script><script type="text/javascript" src="/js/docs-rating.js"></script><script src="https://unpkg.com/vanilla-back-to-top@7.1.14/dist/vanilla-back-to-top.min.js"></script><script>
document.addEventListener('DOMContentLoaded', function() {
addBackToTop(
{"zIndex":100}
)
});
</script><script src="/js/scrollSpy.js"></script><link rel="stylesheet" href="/css/prism.css"/><link rel="stylesheet" href="/css/main.css"/><script src="/js/codetabs.js"></script></head><body class="sideNavVisible separateOnPageNav"><div class="fixedHeaderContainer"><div class="headerWrapper wrapper"><header><a href="/"><img class="logo" src="/img/header_logo.svg" alt="React Native"/><h2 class="headerTitleWithLogo">React Native</h2></a><a href="/versions"><h3>0.62</h3></a><div class="navigationWrapper navigationSlider"><nav class="slidingNav"><ul class="nav-site nav-site-internal"><li class="siteNavGroupActive"><a href="/docs/getting-started" target="_self">Docs</a></li><li class=""><a href="/docs/components-and-apis" target="_self">Components</a></li><li class=""><a href="/docs/accessibilityinfo" target="_self">API</a></li><li class=""><a href="/help" target="_self">Community</a></li><li class=""><a href="/blog/" target="_self">Blog</a></li><li class="navSearchWrapper reactNavSearchWrapper"><input type="text" id="search_input_react" placeholder="Search" title="Search"/></li><li class=""><a href="https://github.com/facebook/react-native" target="_self">GitHub</a></li></ul></nav></div></header></div></div><div class="navPusher"><div class="docMainWrapper wrapper"><div class="docsNavContainer" id="docsNav"><nav class="toc"><div class="toggleNav"><section class="navWrapper wrapper"><div class="navBreadcrumb wrapper"><div class="navToggle" id="navToggler"><div class="hamburger-menu"><div class="line1"></div><div class="line2"></div><div class="line3"></div></div></div><h2><i></i><span>Guides (Android)</span></h2><div class="tocToggler" id="tocToggler"><i class="icon-toc"></i></div></div><div class="navGroups"><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">The Basics<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/getting-started">Introduction</a></li><li class="navListItem"><a class="navItem" href="/docs/intro-react-native-components">Core Components and Native Components</a></li><li class="navListItem"><a class="navItem" href="/docs/intro-react">React Fundamentals</a></li><li class="navListItem"><a class="navItem" href="/docs/handling-text-input">Handling Text Input</a></li><li class="navListItem"><a class="navItem" href="/docs/using-a-scrollview">Using a ScrollView</a></li><li class="navListItem"><a class="navItem" href="/docs/using-a-listview">Using List Views</a></li><li class="navListItem"><a class="navItem" href="/docs/troubleshooting">Troubleshooting</a></li><li class="navListItem"><a class="navItem" href="/docs/platform-specific-code">Platform Specific Code</a></li><li class="navListItem"><a class="navItem" href="/docs/more-resources">More Resources</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Environment setup<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/environment-setup">Setting up the development environment</a></li><li class="navListItem"><a class="navItem" href="/docs/integration-with-existing-apps">Integration with Existing Apps</a></li><li class="navListItem"><a class="navItem" href="/docs/building-for-tv">Building For TV Devices</a></li><li class="navListItem"><a class="navItem" href="/docs/out-of-tree-platforms">Out-of-Tree Platforms</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Workflow<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/running-on-device">Running On Device</a></li><li class="navListItem"><a class="navItem" href="/docs/fast-refresh">Fast Refresh</a></li><li class="navListItem"><a class="navItem" href="/docs/debugging">Debugging</a></li><li class="navListItem"><a class="navItem" href="/docs/testing-overview">Testing</a></li><li class="navListItem"><a class="navItem" href="/docs/libraries">Using Libraries</a></li><li class="navListItem"><a class="navItem" href="/docs/typescript">Using TypeScript with React Native</a></li><li class="navListItem"><a class="navItem" href="/docs/upgrading">Upgrading to new React Native versions</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Design<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/style">Style</a></li><li class="navListItem"><a class="navItem" href="/docs/height-and-width">Height and Width</a></li><li class="navListItem"><a class="navItem" href="/docs/flexbox">Layout with Flexbox</a></li><li class="navListItem"><a class="navItem" href="/docs/images">Images</a></li><li class="navListItem"><a class="navItem" href="/docs/colors">Color Reference</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Interaction<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/handling-touches">Handling Touches</a></li><li class="navListItem"><a class="navItem" href="/docs/navigation">Navigating Between Screens</a></li><li class="navListItem"><a class="navItem" href="/docs/animations">Animations</a></li><li class="navListItem"><a class="navItem" href="/docs/gesture-responder-system">Gesture Responder System</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Inclusion<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/accessibility">Accessibility</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Performance<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/performance">Performance Overview</a></li><li class="navListItem"><a class="navItem" href="/docs/optimizing-flatlist-configuration">Optimizing Flatlist Configuration</a></li><li class="navListItem"><a class="navItem" href="/docs/ram-bundles-inline-requires">RAM Bundles and Inline Requires</a></li><li class="navListItem"><a class="navItem" href="/docs/profiling">Profiling</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">JavaScript Runtime<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/javascript-environment">JavaScript Environment</a></li><li class="navListItem"><a class="navItem" href="/docs/timers">Timers</a></li><li class="navListItem"><a class="navItem" href="/docs/hermes">Using Hermes</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Connectivity<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/network">Networking</a></li><li class="navListItem"><a class="navItem" href="/docs/security">Security</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Native Components and Modules<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/native-modules-setup">Native Modules Setup</a></li><li class="navListItem"><a class="navItem" href="/docs/direct-manipulation">Direct Manipulation</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Guides (Android)<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/native-modules-android">Native Modules</a></li><li class="navListItem"><a class="navItem" href="/docs/native-components-android">Native UI Components</a></li><li class="navListItem"><a class="navItem" href="/docs/headless-js-android">Headless JS</a></li><li class="navListItem navListItemActive"><a class="navItem" href="/docs/signed-apk-android">Publishing to Google Play Store</a></li><li class="navListItem"><a class="navItem" href="/docs/removing-default-permissions">Removing Default Permissions</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Guides (iOS)<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/native-modules-ios">Native Modules</a></li><li class="navListItem"><a class="navItem" href="/docs/native-components-ios">Native UI Components</a></li><li class="navListItem"><a class="navItem" href="/docs/linking-libraries-ios">Linking Libraries</a></li><li class="navListItem"><a class="navItem" href="/docs/running-on-simulator-ios">Running On Simulator</a></li><li class="navListItem"><a class="navItem" href="/docs/communication-ios">Communication between native and React Native</a></li><li class="navListItem"><a class="navItem" href="/docs/app-extensions">App Extensions</a></li></ul></div></div></section></div><script>
var coll = document.getElementsByClassName('collapsible');
var checkActiveCategory = true;
for (var i = 0; i < coll.length; i++) {
var links = coll[i].nextElementSibling.getElementsByTagName('*');
if (checkActiveCategory){
for (var j = 0; j < links.length; j++) {
if (links[j].classList.contains('navListItemActive')){
coll[i].nextElementSibling.classList.toggle('hide');
coll[i].childNodes[1].classList.toggle('rotate');
checkActiveCategory = false;
break;
}
}
}
coll[i].addEventListener('click', function() {
var arrow = this.childNodes[1];
arrow.classList.toggle('rotate');
var content = this.nextElementSibling;
content.classList.toggle('hide');
});
}
document.addEventListener('DOMContentLoaded', function() {
createToggler('#navToggler', '#docsNav', 'docsSliderActive');
createToggler('#tocToggler', 'body', 'tocActive');
var headings = document.querySelector('.toc-headings');
headings && headings.addEventListener('click', function(event) {
var el = event.target;
while(el !== headings){
if (el.tagName === 'A') {
document.body.classList.remove('tocActive');
break;
} else{
el = el.parentNode;
}
}
}, false);
function createToggler(togglerSelector, targetSelector, className) {
var toggler = document.querySelector(togglerSelector);
var target = document.querySelector(targetSelector);
if (!toggler) {
return;
}
toggler.onclick = function(event) {
event.preventDefault();
target.classList.toggle(className);
};
}
});
</script></nav></div><div class="container mainContainer docsContainer"><div class="wrapper"><div class="post"><header class="postHeader"><a class="edit-page-link button" href="https://github.com/facebook/react-native-website/blob/master/docs/signed-apk-android.md" target="_blank" rel="noreferrer noopener">Edit</a><h1 id="__docusaurus" class="postHeaderTitle">Publishing to Google Play Store</h1></header><article><div><span><p>Android requires that all apps be digitally signed with a certificate before they can be installed. In order to distribute your Android application via <a href="https://play.google.com/store">Google Play store</a> it needs to be signed with a release key that then needs to be used for all future updates. Since 2017 it is possible for Google Play to manage signing releases automatically thanks to <a href="https://developer.android.com/studio/publish/app-signing#app-signing-google-play">App Signing by Google Play</a> functionality. However, before your application binary is uploaded to Google Play it needs to be signed with an upload key. The <a href="https://developer.android.com/tools/publishing/app-signing.html">Signing Your Applications</a> page on Android Developers documentation describes the topic in detail. This guide covers the process in brief, as well as lists the steps required to package the JavaScript bundle.</p>
<h3><a class="anchor" aria-hidden="true" id="generating-an-upload-key"></a><a href="#generating-an-upload-key" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Generating an upload key</h3>
<p>You can generate a private signing key using <code>keytool</code>. On Windows <code>keytool</code> must be run from <code>C:\Program Files\Java\jdkx.x.x_x\bin</code>.</p>
<pre><code class="hljs">$ keytool -genkeypair -v -keystore my-upload-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
</code></pre>
<p>This command prompts you for passwords for the keystore and key and for the Distinguished Name fields for your key. It then generates the keystore as a file called <code>my-upload-key.keystore</code>.</p>
<p>The keystore contains a single key, valid for 10000 days. The alias is a name that you will use later when signing your app, so remember to take note of the alias.</p>
<p>On Mac, if you're not sure where your JDK bin folder is, then perform the following command to find it:</p>
<pre><code class="hljs">$ /usr/libexec/java_home
</code></pre>
<p>It will output the directory of the JDK, which will look something like this:</p>
<pre><code class="hljs">/Library/Java/JavaVirtualMachines/jdkX.X.X_XXX.jdk/Contents/Home
</code></pre>
<p>Navigate to that directory by using the command <code>$ cd /your/jdk/path</code> and use the keytool command with sudo permission as shown below.</p>
<pre><code class="hljs">$ sudo keytool -genkey -v -keystore my-upload-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
</code></pre>
<p><em>Note: Remember to keep the keystore file private. In case you've lost upload key or it's been compromised you should <a href="https://support.google.com/googleplay/android-developer/answer/7384423#reset">follow these instructions</a>.</em></p>
<h3><a class="anchor" aria-hidden="true" id="setting-up-gradle-variables"></a><a href="#setting-up-gradle-variables" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Setting up Gradle variables</h3>
<ol>
<li>Place the <code>my-upload-key.keystore</code> file under the <code>android/app</code> directory in your project folder.</li>
<li>Edit the file <code>~/.gradle/gradle.properties</code> or <code>android/gradle.properties</code>, and add the following (replace <code>*****</code> with the correct keystore password, alias and key password),</li>
</ol>
<pre><code class="hljs"><span class="hljs-attr">MYAPP_UPLOAD_STORE_FILE</span>=my-upload-key.keystore
<span class="hljs-attr">MYAPP_UPLOAD_KEY_ALIAS</span>=my-key-alias
<span class="hljs-attr">MYAPP_UPLOAD_STORE_PASSWORD</span>=*****
<span class="hljs-attr">MYAPP_UPLOAD_KEY_PASSWORD</span>=*****
</code></pre>
<p>These are going to be global Gradle variables, which we can later use in our Gradle config to sign our app.</p>
<p><em>Note about security: If you are not keen on storing your passwords in plaintext, and you are running OSX, you can also <a href="https://pilloxa.gitlab.io/posts/safer-passwords-in-gradle/">store your credentials in the Keychain Access app</a>. Then you can skip the two last rows in <code>~/.gradle/gradle.properties</code>.</em></p>
<h3><a class="anchor" aria-hidden="true" id="adding-signing-config-to-your-apps-gradle-config"></a><a href="#adding-signing-config-to-your-apps-gradle-config" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Adding signing config to your app's Gradle config</h3>
<p>The last configuration step that needs to be done is to setup release builds to be signed using upload key. Edit the file <code>android/app/build.gradle</code> in your project folder, and add the signing config,</p>
<pre><code class="hljs css language-gradle">...
android {
...
defaultConfig { ... }
signingConfigs {
release {
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">project</span>.hasProperty(<span class="hljs-string">'MYAPP_UPLOAD_STORE_FILE'</span>)) {
storeFile <span class="hljs-keyword">file</span>(MYAPP_UPLOAD_STORE_FILE)
storePassword MYAPP_UPLOAD_STORE_PASSWORD
keyAlias MYAPP_UPLOAD_KEY_ALIAS
keyPassword MYAPP_UPLOAD_KEY_PASSWORD
}
}
}
buildTypes {
release {
...
signingConfig signingConfigs.release
}
}
}
...
</code></pre>
<h3><a class="anchor" aria-hidden="true" id="generating-the-release-apk"></a><a href="#generating-the-release-apk" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Generating the release APK</h3>
<p>Run the following in a terminal:</p>
<pre><code class="hljs css language-sh">$ <span class="token builtin class-name">cd</span> android
$ ./gradlew bundleRelease
</code></pre>
<p>Gradle's <code>bundleRelease</code> will bundle all the JavaScript needed to run your app into the AAB (<a href="https://developer.android.com/guide/app-bundle">Android App Bundle</a>). If you need to change the way the JavaScript bundle and/or drawable resources are bundled (e.g. if you changed the default file/folder names or the general structure of the project), have a look at <code>android/app/build.gradle</code> to see how you can update it to reflect these changes.</p>
<blockquote>
<p>Note: Make sure gradle.properties does not include <em>org.gradle.configureondemand=true</em> as that will make the release build skip bundling JS and assets into the app binary.</p>
</blockquote>
<p>The generated AAB can be found under <code>android/app/build/outputs/bundle/release/app.aab</code>, and is ready to be uploaded to Google Play.</p>
<p><em>Note: In order for Google Play to accept AAB format the App Signing by Google Play needs to be configured for your application on the Google Play Console. If you are updating an existing app that doesn't use App Signing by Google Play, please check our <a href="#migrating-old-android-react-native-apps-to-use-app-signing-by-google-play">migration section</a> to learn how to perform that configuration change.</em></p>
<h3><a class="anchor" aria-hidden="true" id="testing-the-release-build-of-your-app"></a><a href="#testing-the-release-build-of-your-app" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Testing the release build of your app</h3>
<p>Before uploading the release build to the Play Store, make sure you test it thoroughly. First uninstall any previous version of the app you already have installed. Install it on the device using:</p>
<pre><code class="hljs css language-sh">$ npx react-native run-android --variant<span class="token operator">=</span>release
</code></pre>
<p>Note that <code>--variant=release</code> is only available if you've set up signing as described above.</p>
<p>You can terminate any running bundler instances, since all your framework and JavaScript code is bundled in the APK's assets.</p>
<h3><a class="anchor" aria-hidden="true" id="publishing-to-other-stores"></a><a href="#publishing-to-other-stores" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Publishing to other stores</h3>
<p>By default, the generated APK has the native code for both x86 and ARMv7a CPU architectures. This makes it easier to share APKs that run on almost all Android devices. However, this has the downside that there will be some unused native code on any device, leading to unnecessarily bigger APKs.</p>
<p>You can create an APK for each CPU by changing the following line in android/app/build.gradle:</p>
<pre><code class="hljs css language-diff"><span class="hljs-deletion">- ndk {</span>
<span class="hljs-deletion">- abiFilters "armeabi-v7a", "x86"</span>
<span class="hljs-deletion">- }</span>
<span class="hljs-deletion">- def enableSeparateBuildPerCPUArchitecture = false</span>
<span class="hljs-addition">+ def enableSeparateBuildPerCPUArchitecture = true</span>
</code></pre>
<p>Upload both these files to markets which support device targeting, such as <a href="https://developer.android.com/google/play/publishing/multiple-apks.html">Google Play</a> and <a href="https://developer.amazon.com/docs/app-submission/device-filtering-and-compatibility.html">Amazon AppStore</a>, and the users will automatically get the appropriate APK. If you want to upload to other markets, such as <a href="https://www.apkfiles.com/">APKFiles</a>, which do not support multiple APKs for a single app, change the following line as well to create the default universal APK with binaries for both CPUs.</p>
<pre><code class="hljs css language-diff"><span class="hljs-deletion">- universalApk false // If true, also generate a universal APK</span>
<span class="hljs-addition">+ universalApk true // If true, also generate a universal APK</span>
</code></pre>
<h3><a class="anchor" aria-hidden="true" id="enabling-proguard-to-reduce-the-size-of-the-apk-optional"></a><a href="#enabling-proguard-to-reduce-the-size-of-the-apk-optional" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Enabling Proguard to reduce the size of the APK (optional)</h3>
<p>Proguard is a tool that can slightly reduce the size of the APK. It does this by stripping parts of the React Native Java bytecode (and its dependencies) that your app is not using.</p>
<p><em><strong>IMPORTANT</strong>: Make sure to thoroughly test your app if you've enabled Proguard. Proguard often requires configuration specific to each native library you're using. See <code>app/proguard-rules.pro</code>.</em></p>
<p>To enable Proguard, edit <code>android/app/build.gradle</code>:</p>
<pre><code class="hljs css language-gradle"><span class="hljs-comment">/**
* Run Proguard to shrink the Java bytecode in release builds.
*/</span>
<span class="hljs-keyword">def</span> enableProguardInReleaseBuilds = <span class="hljs-keyword">true</span>
</code></pre>
<h3><a class="anchor" aria-hidden="true" id="migrating-old-android-react-native-apps-to-use-app-signing-by-google-play"></a><a href="#migrating-old-android-react-native-apps-to-use-app-signing-by-google-play" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Migrating old Android React Native apps to use App Signing by Google Play</h3>
<p>If you are migrating from previous version of React Native chances are your app does not use App Signing by Google Play feature. We recommend you enable that in order to take advantage from things like automatic app splitting. In order to migrate from the old way of signing you need to start by <a href="#generating-an-upload-key">generating new upload key</a> and then replacing release signing config in <code>android/app/build.gradle</code> to use the upload key instead of the release one (see section about <a href="#adding-signing-config-to-your-app-s-gradle-config">adding signing config to gradle</a>). Once that's done you should follow the <a href="https://support.google.com/googleplay/android-developer/answer/7384423">instructions from Google Play Help website</a> in order to send your original release key to Google Play.</p>
</span></div></article></div><div class="docs-prevnext"><a class="docs-prev button" href="/docs/headless-js-android"><span class="arrow-prev"></span><span>Headless JS</span></a><a class="docs-next button" href="/docs/removing-default-permissions"><span>Removing Default Permissions</span><span class="arrow-next"></span></a></div></div></div><nav class="onPageNav"></nav></div><footer class="nav-footer" id="footer"><section class="sitemap"><div><h5>Docs</h5><a href="/docs/getting-started">Getting Started</a><a href="/docs/tutorial">Tutorial</a><a href="/docs/components-and-apis">Components and APIs</a><a href="/docs/more-resources">More Resources</a></div><div><h5>Community</h5><a href="/help">The React Native Community</a><a href="/showcase">Who&#x27;s using React Native?</a><a href="https://stackoverflow.com/questions/tagged/react-native" target="_blank">Ask Questions on Stack Overflow</a><a href="https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md">Contributor Guide</a><a href="https://dev.to/t/reactnative" target="_blank">DEV Community</a></div><div><h5>More Resources</h5><a href="/blog">Blog</a><a href="https://twitter.com/reactnative" target="_blank">Twitter</a><a href="https://github.com/facebook/react-native" target="_blank">GitHub</a><a href="https://reactjs.org" target="_blank">React</a></div></section><a href="https://code.facebook.com/projects/" target="_blank" class="fbOpenSource"><img src="/img/oss_logo.png" alt="Facebook Open Source" width="170" height="45"/></a><section class="copyright">Copyright © 2020 Facebook Inc.</section></footer></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script><script>window.fbAsyncInit = function() {FB.init({appId:'1677033832619985',xfbml:true,version:'v2.7'});};(function(d, s, id){var js, fjs = d.getElementsByTagName(s)[0];if (d.getElementById(id)) {return;}js = d.createElement(s); js.id = id;js.src = '//connect.facebook.net/en_US/sdk.js';fjs.parentNode.insertBefore(js, fjs);}(document, 'script','facebook-jssdk'));
</script><script>window.twttr=(function(d,s, id){var js,fjs=d.getElementsByTagName(s)[0],t=window.twttr||{};if(d.getElementById(id))return t;js=d.createElement(s);js.id=id;js.src='https://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js, fjs);t._e = [];t.ready = function(f) {t._e.push(f);};return t;}(document, 'script', 'twitter-wjs'));</script><script>
document.addEventListener('keyup', function(e) {
if (e.target !== document.body) {
return;
}
// keyCode for '/' (slash)
if (e.keyCode === 191) {
const search = document.getElementById('search_input_react');
search && search.focus();
}
});
</script><script>
var search = docsearch({
apiKey: '2c98749b4a1e588efec53b2acec13025',
indexName: 'react-native-versions',
inputSelector: '#search_input_react',
algoliaOptions: {"facetFilters":["tags:0.62"],"hitsPerPage":5}
});
</script></body></html>