Every app needs its own signing key. For a full understanding of how Android app signing works, see the official Android documentation.Generate a keystore for your app:
Replace my-app-name with your app’s name.Store the keystore file and passwords securely — losing them means you cannot update your app. All future updates must be signed with the same key.
If your app is also published on Google Play, you must use a separate
signing key for the dApp Store. You cannot reuse the same key for both stores.
Publishing multiple apps?
Each app should have its own signing key. You can keep things organized by storing multiple key aliases in a single keystore file:
Then reference the appropriate -alias when signing each app.
Expo
Native Android
Web App
By default, EAS builds an Android App Bundle (.aab). The dApp Store requires an APK instead.For signing, EAS can automatically generate and manage a keystore for you on your first build. Alternatively, you can provide your own keystore created with the instructions above.
eas build --platform android --profile dapp-store --local
The build runs on your machine and needs macOS or Linux. It requires the Android SDK and NDK installed locally. The APK is output to the project directory. On Windows, use EAS Cloud instead.
eas build --platform android --profile dapp-store
The build runs on EAS servers. Once finished, download the APK from the link provided.
On your first build, EAS will prompt you to either generate a new keystore automatically or provide an existing one.
Any web app or website can be published on the dApp Store by wrapping it in an Android WebView shell. The solana-mobile webshell command generates that Android project for you and builds a signed release APK from it.
The generated app is a WebView shell, not a Trusted Web Activity
(TWA), so it
needs no Digital Asset Links setup. Browsers are rolling out Local Network
Access restrictions
that break Mobile Wallet Adapter connections for web apps, including TWA-based
wrappers such as Bubblewrap APKs. The shell handles wallet intents natively,
so those flows keep working.
A JDK 17 or newer and the Android SDK are installed. Run solana-mobile doctor to check.
If your web app uses Mobile Wallet Adapter, it is on @solana-mobile/wallet-standard-mobilev0.5.1 or later, which detects the shell and skips the browser permission flow. See Local Network Access.
Template: Web Manifest
A web manifest is optional, but when one is available the CLI seeds the app name, icons, and start URL from it. At minimum, a manifest file includes the app’s name, icons, and start URL:
Either form prompts for whatever is still missing: application id, app name, version code and name, and the signing keystore. See webshell init for the full list of flags.
Already using Bubblewrap? Pass its twa-manifest.json to --manifest and the
CLI carries over the application id, versions, and signing key, so your
existing app updates keep working.
Pass --keystore-path to sign with the key you created above. When that path
does not exist yet, init creates a keystore there instead. Keep the keystore
file and its passwords secure — losing them means you cannot update your app.
The build prompts for the keystore password. Set SOLANA_MOBILE_KEYSTORE_PASSWORD (and SOLANA_MOBILE_KEY_PASSWORD, if the key uses a different password) to skip the prompts in CI:
Every dApp Store update needs a higher versionCode. Bump SOLANA_MOBILE_VERSION_CODE and SOLANA_MOBILE_VERSION_NAME in the generated project’s gradle.properties, then build again:
npx solana-mobile@latest webshell build my-app
Because the shell loads your live site, changes you ship to the web app itself reach users without a new APK.
{"docsConfig":{"theme":"aspen","$schema":"https://mintlify.com/docs.json","name":"Solana Mobile Docs","colors":{"primary":"#000000","light":"#EF5C6F","dark":"#EF5C6F"},"logo":{"light":"https://mintcdn.com/solanalabs/TqbmPoBvHph_ccql/logo/light.png?fit=max\u0026auto=format\u0026n=TqbmPoBvHph_ccql\u0026q=85\u0026s=1521aea54cb9a58ad8a4dc762f7e09fb","dark":"https://mintcdn.com/solanalabs/kMNOLb20KE24UVGL/logo/dark.svg?fit=max\u0026auto=format\u0026n=kMNOLb20KE24UVGL\u0026q=85\u0026s=099c9770f78a15840ff19eb457b57feb","href":"/"},"favicon":"https://mintcdn.com/solanalabs/JcpEBaAjfQ94V5J-/favicon.ico?fit=max\u0026auto=format\u0026n=JcpEBaAjfQ94V5J-\u0026q=85\u0026s=2a17f5cfd557f7f5ce8bb00d8b26210c","appearance":{"default":"dark"},"background":{"decoration":"gradient"},"navbar":{"links":[{"href":"https://discord.gg/solanamobile","label":"Discord"}],"primary":{"type":"button","label":"Publish","href":"https://publish.solanamobile.com/"}},"footer":{"socials":{"x":"https://twitter.com/solanamobile","github":"https://github.com/solana-mobile","discord":"https://discord.gg/solanamobile","youtube":"https://www.youtube.com/@solanamobile"},"links":[{"header":"Community","items":[{"label":"Stack Exchange","href":"https://solana.stackexchange.com/"},{"label":"Discord","href":"https://discord.gg/solanamobile"},{"label":"Twitter","href":"https://twitter.com/solanamobile"}]},{"header":"More","items":[{"label":"GitHub","href":"https://github.com/solana-mobile"},{"label":"Seeker Release Notes","href":"/seeker/release-notes"}]},{"header":"Legal","items":[{"label":"Terms of Service","href":"https://solanamobile.com/tos-homepage-web"},{"label":"Privacy Policy","href":"https://solanamobile.com/privacy-policy-homepage-web"},{"label":"Developer Agreement","href":"https://solanamobile.com/developer-agreement-web"},{"label":"dApp Store Terms of Use","href":"https://solanamobile.com/dapp-store-tos"},{"label":"Cookie Policy","href":"https://solanamobile.com/cookie-policy-web"},{"label":"Your Privacy Choices","href":"https://solanamobile.com/cookie-policy-web"}]}]},"fonts":{"heading":{"family":"__ppMori_c9a5a4","source":"https://mintlify-assets.b-cdn.net/EHeAzD6gM8HDt9NQftiBgWSV3A.woff2","format":"woff2"},"body":{"family":"__ppMori_c9a5a4","source":"https://mintlify-assets.b-cdn.net/EHeAzD6gM8HDt9NQftiBgWSV3A.woff2","format":"woff2"}},"integrations":{"gtm":{"tagId":"GTM-KT4PN29R"}},"contextual":{"options":["copy","view","chatgpt","claude"],"display":"header"},"metadata":{"timestamp":true},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"solanalabs","hasAudioNarration":false,"actualSubdomain":"solanalabs","customDomains":["docs.solanamobile.com"],"gitSource":{"type":"github","owner":"solana-mobile","repo":"solana-mobile-docs","deployBranch":"main","contentDirectory":"","isPrivate":false,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6adef66ead3ed130d8d6b47c","collectionId":"a8a9cd6a-3b49-4d29-812d-d732cfaeda2c","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6adef66ead3ed130d8d6b47c"},"feedback":{"issues":false},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"REMOVE_BRANDING":{"status":"ENABLED"},"CONTEXTUAL_FEEDBACK":{"status":"ENABLED"},"CODE_SNIPPET_FEEDBACK":{"status":"ENABLED","enabled":"DISABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6ae411f7f91d54971319c61e","clientVersion":"0.0.4076","searchFilterCounts":[{"language":"default","tag":"Get Started","count":22},{"language":"default","tag":"Mobile Wallet Adapter SDK","count":15},{"language":"default","tag":"dApp Store","count":14},{"language":"default","tag":"Recipes","count":12},{"language":"default","tag":"Solana Mobile Stack","count":11},{"language":"default","tag":"CLI","count":10},{"language":"default","tag":"Commands","count":8},{"language":"default","tag":"Seeker","count":8},{"language":"default","tag":"Release Notes","count":8},{"language":"default","tag":"Publishing","count":7}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":"img[src*=\"sample_app_imgs\"]{min-height:200px;object-fit:cover}li[id=\"topbar-cta-button\"]>a>div>span{color:#000000!important}img.no-zoom{cursor:default!important;touch-action:manipulation;pointer-events:auto}li[id=\"topbar-cta-button\"]>a>div>span{color:#000000!important}li[id=\"topbar-cta-button\"]>a>div>svg>path{stroke:#000000!important}.dark li[id=\"topbar-cta-button\"]>a>div>span{color:#000000!important}.ot-sdk-show-settings{align-items:center;display:inline-flex;gap:0.5rem;max-width:none!important;overflow:visible!important;white-space:nowrap}.ot-sdk-show-settings .ccpa-opt-out-icon{flex:none;height:14px;margin:0;width:30px}"}],"page":{"pagePath":"dapp-store/build-and-sign-an-apk","slug":"/dapp-store/build-and-sign-an-apk","pageMetadata":{"title":"Build and Sign an APK","description":"The Solana dApp Store requires a signed APK file for submission. This guide covers how to build one for Expo, native Android, and web app projects.","href":"/dapp-store/build-and-sign-an-apk"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"The Solana dApp Store requires a signed APK file for submission. This guide covers how to build one for Expo, native Android, and web app projects.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];const FooterDisclaimer=()=>{return _jsxs(`p`,{className:`not-prose mint-mt-16 mint-text-center mint-text-xs mint-text-gray-500 dark:mint-text-gray-400`,children:[`Code samples on this page are subject to the`,` `,_jsx(`a`,{className:`mint-underline mint-underline-offset-2`,href:`https://www.apache.org/licenses/LICENSE-2.0`,children:`Apache 2.0 license`}),`.`]})};function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{Accordion,Card,CodeBlock,Heading,Note,Tab,Tabs,Tip,Warning,_MdxComponentBoundary}=_components;if(!Accordion)_missingMdxReference(`Accordion`,true);if(!Card)_missingMdxReference(`Card`,true);if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Note)_missingMdxReference(`Note`,true);if(!Tab)_missingMdxReference(`Tab`,true);if(!Tabs)_missingMdxReference(`Tabs`,true);if(!Tip)_missingMdxReference(`Tip`,true);if(!Warning)_missingMdxReference(`Warning`,true);if(!_MdxComponentBoundary)_missingMdxReference(`_MdxComponentBoundary`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`The Solana dApp Store accepts `,_jsx(_components.strong,{children:`signed APK`}),` files. This guide covers how to build and sign an APK for your project, regardless of framework.`]}),`\n`,_jsx(Heading,{level:`2`,id:`create-a-signing-key`,children:`Create a signing key`}),`\n`,_jsxs(_components.p,{children:[`Every app needs its own signing key. For a full understanding of how Android app signing works, see the `,_jsx(_components.a,{href:`https://developer.android.com/studio/publish/app-signing#certificates-keystores`,children:`official Android documentation`}),`.`]}),`\n`,_jsx(_components.p,{children:`Generate a keystore for your app:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`5`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`keytool`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -genkey`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -v`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -keystore`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` my-app-name.keystore`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -alias`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` my-app-name`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -keyalg`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` RSA`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -keysize`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 2048`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D7BA7D`},children:` \\\\`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -validity`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 10000`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Replace `,_jsx(_components.code,{children:`my-app-name`}),` with your app’s name.`]}),`\n`,_jsx(_components.p,{children:`Store the keystore file and passwords securely — losing them means you cannot update your app. All future updates must be signed with the same key.`}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`If your app is also published on Google Play, you `,_jsx(_components.strong,{children:`must`}),` use a separate\nsigning key for the dApp Store. You cannot reuse the same key for both stores.`]})}),`\n`,_jsxs(Accordion,{title:`Publishing multiple apps?`,id:`publishing-multiple-apps`,children:[_jsx(_components.p,{children:`Each app should have its own signing key. You can keep things organized by storing multiple key aliases in a single keystore file:`}),_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`5`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# First app`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`keytool`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -genkey`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -v`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -keystore`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` publisher.keystore`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -alias`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` my-first-app`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -keyalg`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` RSA`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -keysize`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 2048`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -validity`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 10000`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Second app`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`keytool`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -genkey`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -v`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -keystore`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` publisher.keystore`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -alias`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` my-second-app`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -keyalg`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` RSA`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -keysize`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 2048`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -validity`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 10000`})]}),`\n`]})})}),_jsxs(_components.p,{children:[`Then reference the appropriate `,_jsx(_components.code,{children:`-alias`}),` when signing each app.`]})]}),`\n`,_jsxs(Tabs,{children:[_jsxs(Tab,{title:`Expo`,icon:`react`,id:`expo`,\"data-child-tab-ids\":`[\"local-build\",\"eas-cloud\"]`,\"data-child-heading-ids\":`[\"1-configure-eas-for-apk-builds\",\"2-build-the-apk\",\"verify-the-apk\"]`,children:[_jsx(_components.p,{children:`By default, EAS builds an Android App Bundle (.aab). The dApp Store requires an APK instead.`}),_jsxs(_components.p,{children:[`For signing, EAS can automatically generate and manage a keystore for you on your first build. Alternatively, you can provide your own keystore created with the `,_jsx(_components.a,{href:`#create-a-signing-key`,children:`instructions above`}),`.`]}),_jsx(Heading,{level:`2`,id:`1-configure-eas-for-apk-builds`,children:`1. Configure EAS for APK builds`}),_jsxs(_components.p,{children:[`Add a `,_jsx(_components.code,{children:`dapp-store`}),` build profile to your `,_jsx(_components.code,{children:`eas.json`}),`:`]}),_jsx(CodeBlock,{filename:`eas.json`,numberOfLines:`9`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`9`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"build\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"dapp-store\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"android\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"buildType\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"apk\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),_jsx(Heading,{level:`2`,id:`2-build-the-apk`,children:`2. Build the APK`}),_jsxs(Tabs,{children:[_jsxs(Tab,{title:`Local Build`,id:`local-build`,children:[_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`eas`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` build`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --platform`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` android`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --profile`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` dapp-store`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --local`})]}),`\n`]})})}),_jsxs(_components.p,{children:[`The build runs on your machine and needs macOS or Linux. It requires the `,_jsx(_components.a,{href:`https://docs.expo.dev/get-started/set-up-your-environment/?mode=development-build\u0026buildEnv=local`,children:`Android SDK and NDK`}),` installed locally. The APK is output to the project directory. On Windows, use EAS Cloud instead.`]})]}),_jsxs(Tab,{title:`EAS Cloud`,id:`eas-cloud`,children:[_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`eas`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` build`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --platform`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` android`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --profile`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` dapp-store`})]}),`\n`]})})}),_jsx(_components.p,{children:`The build runs on EAS servers. Once finished, download the APK from the link provided.`})]})]}),_jsx(_components.p,{children:`On your first build, EAS will prompt you to either generate a new keystore automatically or provide an existing one.`}),_jsx(Heading,{level:`2`,id:`verify-the-apk`,children:`Verify the APK`}),_jsx(_components.p,{children:`Confirm your APK is properly signed:`}),_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`apksigner`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` verify`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --print-certs`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` app-release.apk`})]}),`\n`]})})})]}),_jsxs(Tab,{title:`Native Android`,icon:`android`,id:`native-android`,\"data-child-heading-ids\":`[\"1-configure-signing-in-build-gradle\",\"2-build-the-apk-2\",\"3-verify-the-apk\"]`,children:[_jsx(Heading,{level:`2`,id:`1-configure-signing-in-build-gradle`,children:`1. Configure signing in build.gradle`}),_jsxs(_components.p,{children:[`Add a signing config in your `,_jsx(_components.code,{children:`app/build.gradle`}),`:`]}),_jsx(CodeBlock,{filename:`app/build.gradle`,numberOfLines:`16`,language:`groovy`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`groovy`,children:_jsxs(_components.code,{language:`groovy`,numberOfLines:`16`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`android {`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` signingConfigs {`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` dappStore {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` storeFile file(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"keystores/my-app-name.keystore\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` storePassword `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"your_keystore_password\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` keyAlias `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"my-app-name\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` keyPassword `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"your_key_password\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` buildTypes {`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` release {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` signingConfig signingConfigs`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`dappStore`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),_jsx(Heading,{level:`2`,id:`2-build-the-apk-2`,children:`2. Build the APK`}),_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`./gradlew`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` assembleRelease`})]}),`\n`]})})}),_jsxs(_components.p,{children:[`Or in Android Studio: `,_jsx(_components.strong,{children:`Build`}),` > `,_jsx(_components.strong,{children:`Build APK(s)`}),`.`]}),_jsxs(_components.p,{children:[`Your signed APK will be at `,_jsx(_components.code,{children:`app/build/outputs/apk/release/app-release.apk`}),`.`]}),_jsx(Heading,{level:`2`,id:`3-verify-the-apk`,children:`3. Verify the APK`}),_jsx(_components.p,{children:`Confirm your APK is properly signed:`}),_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`apksigner`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` verify`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --print-certs`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` app-release.apk`})]}),`\n`]})})})]}),_jsxs(Tab,{title:`Web App`,icon:`globe`,id:`web-app`,\"data-child-heading-ids\":`[\"prerequisites\",\"1-generate-the-android-project\",\"2-build-the-apk-3\",\"3-verify-the-apk-2\",\"4-test-the-apk\",\"updating-your-app\"]`,children:[_jsxs(_components.p,{children:[`Any web app or website can be published on the dApp Store by wrapping it in an Android WebView shell. The `,_jsx(_components.a,{href:`/cli/webshell`,children:_jsx(_components.code,{children:`solana-mobile webshell`})}),` command generates that Android project for you and builds a signed release APK from it.`]}),_jsx(Note,{children:_jsxs(_components.p,{children:[`The generated app is a WebView shell, not a `,_jsx(_components.a,{href:`https://developer.chrome.com/docs/android/trusted-web-activity`,children:`Trusted Web Activity\n(TWA)`}),`, so it\nneeds no Digital Asset Links setup. Browsers are rolling out `,_jsx(_components.a,{href:`https://developer.chrome.com/blog/local-network-access`,children:`Local Network\nAccess`}),` restrictions\nthat break Mobile Wallet Adapter connections for web apps, including TWA-based\nwrappers such as Bubblewrap APKs. The shell handles wallet intents natively,\nso those flows keep working.`]})}),_jsx(Heading,{level:`3`,id:`prerequisites`,children:`Prerequisites`}),_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Your web app is reachable at a public URL.`}),`\n`,_jsxs(_components.li,{children:[`A JDK 17 or newer and the Android SDK are installed. Run `,_jsx(_components.a,{href:`/cli/doctor`,children:_jsx(_components.code,{children:`solana-mobile doctor`})}),` to check.`]}),`\n`,_jsxs(_components.li,{children:[`If your web app uses Mobile Wallet Adapter, it is on `,_jsx(_components.code,{children:`@solana-mobile/wallet-standard-mobile`}),` `,_jsx(_components.strong,{children:`v0.5.1 or later`}),`, which detects the shell and skips the browser permission flow. See `,_jsx(_components.a,{href:`/recipes/mobile-wallet-adapter/local-network-access`,children:`Local Network Access`}),`.`]}),`\n`]}),_jsxs(Accordion,{title:`Template: Web Manifest`,id:`template-web-manifest`,children:[_jsxs(_components.p,{children:[`A `,_jsx(_components.a,{href:`https://developer.mozilla.org/en-US/docs/Web/Manifest`,children:`web manifest`}),` is optional, but when one is available the CLI seeds the app name, icons, and start URL from it. At minimum, a manifest file includes the app’s name, icons, and start URL:`]}),_jsx(CodeBlock,{filename:`manifest.json`,numberOfLines:`21`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`21`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"name\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"APP_NAME\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"short_name\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"APP_NAME\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"scope\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"/\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"start_url\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"/\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"icons\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"src\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"/android-chrome-192x192.png\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"sizes\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"192x192\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"type\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"image/png\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"src\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"/android-chrome-512x512.png\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"sizes\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"512x512\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"type\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"image/png\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ],`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"theme_color\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"#ffffff\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"background_color\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"#ffffff\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"display\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"standalone\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),_jsxs(_components.p,{children:[`For more information, view the `,_jsx(_components.a,{href:`https://web.dev/articles/add-manifest`,children:`web manifest documentation`}),`.`]})]}),_jsx(Heading,{level:`2`,id:`1-generate-the-android-project`,children:`1. Generate the Android project`}),_jsxs(_components.p,{children:[`Point `,_jsx(_components.code,{children:`init`}),` at your site URL:`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npx`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` solana-mobile@latest`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` webshell`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` init`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` my-app`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --url`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` https://your-app.com`})]}),`\n`]})})}),_jsx(_components.p,{children:`If your site has a web manifest, point at that instead and the CLI fills in the app name, icons, and start URL for you:`}),_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npx`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` solana-mobile@latest`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` webshell`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` init`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` my-app`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --manifest`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` https://your-app.com/manifest.json`})]}),`\n`]})})}),_jsxs(_components.p,{children:[`Either form prompts for whatever is still missing: application id, app name, version code and name, and the signing keystore. See `,_jsx(_components.a,{href:`/cli/webshell#webshell-init`,children:_jsx(_components.code,{children:`webshell init`})}),` for the full list of flags.`]}),_jsx(Tip,{children:_jsxs(_components.p,{children:[`Already using Bubblewrap? Pass its `,_jsx(_components.code,{children:`twa-manifest.json`}),` to `,_jsx(_components.code,{children:`--manifest`}),` and the\nCLI carries over the application id, versions, and signing key, so your\nexisting app updates keep working.`]})}),_jsx(Warning,{children:_jsxs(_components.p,{children:[`Pass `,_jsx(_components.code,{children:`--keystore-path`}),` to sign with the key you created above. When that path\ndoes not exist yet, `,_jsx(_components.code,{children:`init`}),` creates a keystore there instead. Keep the keystore\nfile and its passwords secure — losing them means you cannot update your app.`]})}),_jsx(Heading,{level:`2`,id:`2-build-the-apk-3`,children:`2. Build the APK`}),_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npx`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` solana-mobile@latest`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` webshell`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` build`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` my-app`})]}),`\n`]})})}),_jsxs(_components.p,{children:[`The build prompts for the keystore password. Set `,_jsx(_components.code,{children:`SOLANA_MOBILE_KEYSTORE_PASSWORD`}),` (and `,_jsx(_components.code,{children:`SOLANA_MOBILE_KEY_PASSWORD`}),`, if the key uses a different password) to skip the prompts in CI:`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`3`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`3`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`export`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` SOLANA_MOBILE_KEYSTORE_PASSWORD`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'\u003ckeystore-password>'`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`export`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` SOLANA_MOBILE_KEY_PASSWORD`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'\u003ckey-password>'`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npx`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` solana-mobile@latest`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` webshell`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` build`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` my-app`})]}),`\n`]})})}),_jsxs(_components.p,{children:[`The signed APK lands at `,_jsx(_components.code,{children:`my-app/app/build/outputs/apk/release/app-release.apk`}),`.`]}),_jsx(Heading,{level:`2`,id:`3-verify-the-apk-2`,children:`3. Verify the APK`}),_jsx(_components.p,{children:`Confirm your APK is properly signed:`}),_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`apksigner`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` verify`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --print-certs`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` my-app/app/build/outputs/apk/release/app-release.apk`})]}),`\n`]})})}),_jsx(Heading,{level:`2`,id:`4-test-the-apk`,children:`4. Test the APK`}),_jsx(_components.p,{children:`Install it on a connected device or emulator and check that your wallet flows work inside the shell:`}),_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npx`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` solana-mobile@latest`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` device`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` install`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` my-app/app/build/outputs/apk/release/app-release.apk`})]}),`\n`]})})}),_jsx(Heading,{level:`3`,id:`updating-your-app`,children:`Updating your app`}),_jsxs(_components.p,{children:[`Every dApp Store update needs a higher `,_jsx(_components.code,{children:`versionCode`}),`. Bump `,_jsx(_components.code,{children:`SOLANA_MOBILE_VERSION_CODE`}),` and `,_jsx(_components.code,{children:`SOLANA_MOBILE_VERSION_NAME`}),` in the generated project’s `,_jsx(_components.code,{children:`gradle.properties`}),`, then build again:`]}),_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npx`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` solana-mobile@latest`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` webshell`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` build`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` my-app`})]}),`\n`]})})}),_jsx(_components.p,{children:`Because the shell loads your live site, changes you ship to the web app itself reach users without a new APK.`})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`next-steps`,children:`Next steps`}),`\n`,_jsx(_components.p,{children:`With your signed APK ready, follow the dApp Store publishing process:`}),`\n`,_jsx(Card,{title:`Submit your app`,icon:`rocket`,href:`/dapp-store/submit-new-app`,children:_jsx(_components.p,{children:`Follow the step-by-step guide to submit your APK to the Solana dApp Store.`})}),`\n`,_jsx(_MdxComponentBoundary,{name:`FooterDisclaimer`,children:_jsx(FooterDisclaimer,{})})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{FooterDisclaimer,default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Build and Sign an APK","description":"The Solana dApp Store requires a signed APK file for submission. This guide covers how to build one for Expo, native Android, and web app projects.","href":"/dapp-store/build-and-sign-an-apk"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Create a signing key","slug":"create-a-signing-key","depth":2,"children":[]},{"title":"1. Configure EAS for APK builds","slug":"1-configure-eas-for-apk-builds","depth":2,"children":[],"tabId":"expo"},{"title":"2. Build the APK","slug":"2-build-the-apk","depth":2,"children":[],"tabId":"expo"},{"title":"Verify the APK","slug":"verify-the-apk","depth":2,"children":[],"tabId":"expo"},{"title":"1. Configure signing in build.gradle","slug":"1-configure-signing-in-build-gradle","depth":2,"children":[],"tabId":"native-android"},{"title":"2. Build the APK","slug":"2-build-the-apk-2","depth":2,"children":[],"tabId":"native-android"},{"title":"3. Verify the APK","slug":"3-verify-the-apk","depth":2,"children":[],"tabId":"native-android"},{"title":"Prerequisites","slug":"prerequisites","depth":3,"children":[],"tabId":"web-app"},{"title":"1. Generate the Android project","slug":"1-generate-the-android-project","depth":2,"children":[],"tabId":"web-app"},{"title":"2. Build the APK","slug":"2-build-the-apk-3","depth":2,"children":[],"tabId":"web-app"},{"title":"3. Verify the APK","slug":"3-verify-the-apk-2","depth":2,"children":[],"tabId":"web-app"},{"title":"4. Test the APK","slug":"4-test-the-apk","depth":2,"children":[{"title":"Updating your app","slug":"updating-your-app","depth":3,"children":[],"tabId":"web-app"}],"tabId":"web-app"},{"title":"Next steps","slug":"next-steps","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":["/_mintlify/custom/solanalabs/e9d8e2dff41e3ddf/privacy-choices.js"],"dynamicCss":".mint-mt-16 {\n margin-top: 4rem\n}\n.mint-text-center {\n text-align: center\n}\n.mint-text-xs {\n font-size: 0.75rem;\n line-height: 1rem\n}\n.mint-text-gray-500 {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1))\n}\n.mint-underline {\n text-decoration-line: underline\n}\n.mint-underline-offset-2 {\n text-underline-offset: 2px\n}\n.dark\\:mint-text-gray-400:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity, 1))\n}","subdomain":"solanalabs","siteName":"Solana Mobile Docs","title":"Build and Sign an APK - Solana Mobile Docs","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-26T06:43:02.036Z","gitLastModified":"2026-10-26T06:42:51.000Z","originalFileLocation":"dapp-store/build-and-sign-an-apk.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"dark\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"The Solana dApp Store requires a signed APK file for submission. This guide covers how to build one for Expo, native Android, and web app projects.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Solana Mobile Docs\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/solanalabs/NqXin8GWnXcFlaEh/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/solanalabs/NqXin8GWnXcFlaEh/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/solanalabs/NqXin8GWnXcFlaEh/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/solanalabs/NqXin8GWnXcFlaEh/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/solanalabs/NqXin8GWnXcFlaEh/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/solanalabs/NqXin8GWnXcFlaEh/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/solanalabs/NqXin8GWnXcFlaEh/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/solanalabs/NqXin8GWnXcFlaEh/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/solanalabs/NqXin8GWnXcFlaEh/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Build and Sign an APK - Solana Mobile Docs\">\u003cmeta data-mint-head property=\"og:description\" content=\"The Solana dApp Store requires a signed APK file for submission. This guide covers how to build one for Expo, native Android, and web app projects.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Solana Mobile Docs\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.solanamobile.com/dapp-store/build-and-sign-an-apk\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://solanalabs.mintlify.site/_mintlify/api/og/v2?division=Publishing\u0026amp;title=Build+and+Sign+an+APK\u0026amp;description=The+Solana+dApp+Store+requires+a+signed+APK+file+for+submission.+This+guide+covers+how+to+build+one+for+Expo%2C+native+Android%2C+and+web+app+projects.\u0026amp;theme=1d07aafd7ef25c3eb674a743\u0026amp;signature=0f745e8dd5edae36b22892ea8f8d24a36214d7dbcb83ffb2f1e1f6e9affbc2cd\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Build and Sign an APK - Solana Mobile Docs\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"The Solana dApp Store requires a signed APK file for submission. This guide covers how to build one for Expo, native Android, and web app projects.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://solanalabs.mintlify.site/_mintlify/api/og/v2?division=Publishing\u0026amp;title=Build+and+Sign+an+APK\u0026amp;description=The+Solana+dApp+Store+requires+a+signed+APK+file+for+submission.+This+guide+covers+how+to+build+one+for+Expo%2C+native+Android%2C+and+web+app+projects.\u0026amp;theme=1d07aafd7ef25c3eb674a743\u0026amp;signature=0f745e8dd5edae36b22892ea8f8d24a36214d7dbcb83ffb2f1e1f6e9affbc2cd\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/solanalabs/NqXin8GWnXcFlaEh/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Solana Mobile Docs\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#000000\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.solanamobile.com/dapp-store/build-and-sign-an-apk\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/dapp-store/build-and-sign-an-apk.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.solanamobile.com/#organization\",\"name\":\"Solana Mobile Docs\",\"url\":\"https://docs.solanamobile.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/solanalabs/TqbmPoBvHph_ccql/logo/light.png?fit=max\u0026auto=format\u0026n=TqbmPoBvHph_ccql\u0026q=85\u0026s=1521aea54cb9a58ad8a4dc762f7e09fb\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.solanamobile.com#website\",\"name\":\"Solana Mobile Docs\",\"url\":\"https://docs.solanamobile.com\",\"publisher\":{\"@id\":\"https://docs.solanamobile.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.solanamobile.com/dapp-store/build-and-sign-an-apk#webpage\",\"url\":\"https://docs.solanamobile.com/dapp-store/build-and-sign-an-apk\",\"name\":\"Build and Sign an APK\",\"description\":\"The Solana dApp Store requires a signed APK file for submission. This guide covers how to build one for Expo, native Android, and web app projects.\",\"dateModified\":\"2026-10-26T06:42:51.000Z\",\"isPartOf\":{\"@id\":\"https://docs.solanamobile.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.solanamobile.com/dapp-store/build-and-sign-an-apk#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.solanamobile.com/dapp-store/build-and-sign-an-apk#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Solana Mobile Docs\",\"item\":\"https://docs.solanamobile.com\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Build and Sign an APK\",\"item\":\"https://docs.solanamobile.com/dapp-store/build-and-sign-an-apk\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.solanamobile.com/dapp-store/build-and-sign-an-apk#article\",\"headline\":\"Build and Sign an APK\",\"name\":\"Build and Sign an APK\",\"description\":\"The Solana dApp Store requires a signed APK file for submission. This guide covers how to build one for Expo, native Android, and web app projects.\",\"url\":\"https://docs.solanamobile.com/dapp-store/build-and-sign-an-apk\",\"mainEntityOfPage\":{\"@id\":\"https://docs.solanamobile.com/dapp-store/build-and-sign-an-apk#webpage\"},\"dateModified\":\"2026-10-26T06:42:51.000Z\",\"publisher\":{\"@id\":\"https://docs.solanamobile.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.solanamobile.com#website\"}}]}\u003c/script>","siteName":"Solana Mobile Docs","nav":{"global":null,"tabs":[{"tab":"Home","icon":"house","pages":[{"title":"Home","href":""}]},{"tab":"Get Started","icon":"book-open","pages":[{"title":"Get Started","href":"/get-started/overview"}]},{"tab":"Solana Mobile Stack","icon":"layer-group","pages":[{"title":"Solana Mobile Stack","href":"/solana-mobile-stack/overview"}]},{"tab":"CLI","icon":"terminal","pages":[{"title":"CLI","href":"/cli/overview"}]},{"tab":"dApp Store","icon":"store","groups":[{"group":"Overview","pages":[{"title":"Solana dApp Store","description":"The Solana dApp Store is the crypto-friendly app store for Solana Mobile devices.","sidebarTitle":"Overview","href":"/dapp-store/intro"}]},{"group":"Publishing","pages":[{"title":"Build and Sign an APK","href":"/dapp-store/build-and-sign-an-apk"},{"title":"Publishing from Google Play to the dApp Store","sidebarTitle":"Publishing from Google Play","description":"Learn how to publish your existing Google Play app to the dApp Store.","href":"/dapp-store/publishing-from-google-play"},{"title":"Listing Page Guidelines","sidebarTitle":"Listing Page Guidelines","href":"/dapp-store/listing-page-guidelines"},{"title":"Submit a New App","href":"/dapp-store/submit-new-app"},{"title":"Submit an Update","href":"/dapp-store/submit-an-update"},{"title":"dApp Publishing CLI","sidebarTitle":"Publishing CLI","href":"/dapp-store/publishing-cli"},{"title":"Link to your dApp listing page","href":"/dapp-store/link-to-dapp-listing-page"}]},{"group":"Terms and Agreements","pages":[{"title":"Solana Mobile Publisher Policy","sidebarTitle":"Publisher Policy","href":"/dapp-store/publisher-policy"},{"title":"SOLANA MOBILE DAPP STORE DEVELOPER AGREEMENT","sidebarTitle":"Developer Agreement","href":"/dapp-store/agreement"},{"title":"SOLANA DAPP STORE TERMS OF USE","sidebarTitle":"Solana dApp Store TOU","href":"/dapp-store/tou"},{"title":"Solana Mobile Device and dApp Store Privacy Policy","href":"/dapp-store/privacy-policy"}]},{"group":"Support","pages":[{"title":"Get support","href":"/dapp-store/support"},{"title":"FAQ","href":"/get-started/faq"}]}]},{"tab":"Recipes","icon":"utensils","pages":[{"title":"Recipes","href":"/recipes/overview"}]},{"tab":"Saga","hidden":true,"pages":[{"title":"Saga","href":"/saga/release-notes"}]},{"tab":"Sample Apps","icon":"grid-2","pages":[{"title":"Sample Apps","href":"/sample-apps/sample_app_overview"}]},{"tab":"Seeker","icon":"mobile","pages":[{"title":"Seeker","href":"/seeker/release-notes"}]},{"tab":"Security","icon":"shield-halved","pages":[{"title":"Security","href":"/security"}]}]},"basePath":"","title":"Build and Sign an APK - Solana Mobile Docs","buildId":"dpl_8LJbrAiZvr1K98WQNZXCyY5AvT34","deploymentId":"dpl_8LJbrAiZvr1K98WQNZXCyY5AvT34","dynamics":[],"chunks":[]}