When building for the app stores, the expo CLI,
so what we type here in the command line can help you or will help you but you might need to tweak your
configuration in the app.json file depending on which features your application uses.
So our application here uses a bunch of native modules, these modules all need to request permissions
and we kind of do this with the permissions API, like for example in the image picker here when we ask
for permissions but for Android for example, you also need to provide a list of the permissions your
app needs in a configuration file which you, when you use React Native only have but which you don't
have when using expo because expo provides this wrapper and does all of that for you in the expo client
but now we don't plan on using the expo client anymore
and whilst it will include this into your standalone app as I mentioned, you now need to tell expo which
permissions it should request there.
In addition for example if you're using Google Maps, you also need to provide your Google Maps API key
and with that, I don't mean as we're doing it here which we use in some parts of our Javascript code but
to use the React Native maps package.
Again the expo client app basically uses its own key for development and so on but as soon as you plan
on offering a standalone app, you need to bring your own keys so that the expo wrapper which will be
included in your standalone app will use your key
because the expo team won't give you a key owned by them for that.
Again, the official docs are your friends,
there you can learn what you can set up in the app.json file
and let's start with Android because there, you'll have to configure a bit more before we dive into what's
specific about iOS.
So for Android, besides icon and so on, what you can configure there are the permissions. Now
the thing is you can just omit the permissions key and in that case as you see here, expo will actually
setup your app to request all permissions.
Now I would not recommend doing that because people will look at your app in the App Store and if they
see that your basic place management app wants permissions to read their contacts or make calls,
well I don't know about you but I wouldn't download such an app.
So my recommendation would be that you are specific regarding the permissions your app needs and you
do that by going to your app.json file and there in the Android node, you add the permissions
key and now you add permissions.
Now some base permissions will always be requested and you find these permissions here, for example permissions
to get data from the Internet and so on but you can now also for example add permissions to use the user
location and access the camera because that's something we will do.
So let's add these keys here to permissions like this, to string keys with double quotes by the way, that's
important in this file,
added to this permissions array.
Now we will also need the write external storage permission to save our image, so we should add that
as well
and with that we should be good for this application but of course depending on the application
you're building, carefully check which permissions your app will need,
you can always consult the documentation pages of the native module packages you're using, there you
should normally find a description of the permissions
this package needs. So permissions are one thing,
in addition if you're using Google Maps, you should add the Google Maps
node to your Android configuration.
So here
after permissions, we can add Google maps like this which also holds an object as a value and in that
object,
you set up the API key.
Again you didn't need that for the expo client when we publish the app to this expo page and used
the expo client app because there the expo team basically gives you their own Google Maps key
but if you're building a standalone app, you need to provide your own one.
So for that, make sure you use your key here like this and also important and I mentioned this in the
non-expo module already,
make sure that in the Google APIs, so in the Google cloud console when you check your API library, you
make sure that the maps SDK for Android is enabled for this project to which this API key you provided
belongs.
So here it is enabled,
this has to belong to the project for which you created that API key which you now are providing here,
otherwise this won't work. So these are the permissions and Google Map settings and you might need other
specific settings which you can learn about
here in the app.json file depending on which features you're using.
You can also configure Of course everything else and so many things,
one thing you absolutely need to provide to build your app is also this package key.
This is something you always have to add no matter what your app uses,
here in the Android node, you need to provide the package key and this now has to have a certain format.
It's basically an inverse URL, a fictional URL which doesn't have to exist but which acts
as a unique identifier across the entire Google Play Store,
so it should be an inverse URL which no one else has used before and therefore typically if you
own a domain, you would use your domain for example com.academind, so an inverse domain and then
a unique identifier, like great places. You can come up with any URL you want here
but of course again it should be unique and you should therefore use your own domain or a fictional
domain which isn't owned by anyone,
so not academind because I do own this, so any other domain, any other fictional identifier which should
have this format,
that's what you provide here.
You also need to provide something similar on iOS, there
if you go to iOS, you don't need to provide this permission setting stuff because iOS permissions
work differently,
you would need to provide a Google Maps API key if you use the Google Maps version of the maps
package for iOS, the default of this package however is to use Apple Maps and I haven't changed this
in my app so I don't need to provide Google Maps API here
but what you definitely need to provide here is a bundle identifier. So replace package with bundle
identifier and the format is the same,
you have this inverse URL syntax here and I'll name it com.academind.great-places course and
also use that -course edition here on Android.
So bundle identifier for iOS and package for Android needs to be set to such an inverse unique URL.
Now besides these identifiers, you also need to set something else, on
iOS you need to add a build number, also here in the iOS node therefore and the build number should be a string
which identifies your build. There, you should have a build number just like this version up there
and working in the way I explained it up there.
So it should be a number consisting of three digits where you have a patch number for
patches, bug fixes, then this minor update number for new features which don't break everything
though and this major update number,
you can change this however you want but you should change it for every new version you publish and
you deploy and you should of course change it such that you reflect what changed.
Now you need something similar for Android,
if we go back to the Android documentation, there we also need a version code. So here we add version code
and now here this is not a string but a number which you should simply increment by one for every new
release.
So you start at one,
the next version you release, even if it's just containing some tiny fixes should be two and then to
three and so on.
So that's what you should set up here, this is how it works for Android, you also find that description here
in the documentation
and with that, we're now prepared to deploy this or to build it first
and as I mentioned, the cool thing about expo managed is that now you can build this on expo's cloud
servers.
So what you should do is you should run expo publish to publish the latest version of your app to expo's
servers just like that which will not yet build it as a standalone app and
now what I get here are a couple of warnings or errors. So we see that Android should not have additional
property Google Maps,
yes because that should be in a config node,
my mistake.
So you should add config here and in config, you might have this Google Maps key,
that's a tiny mistake on my side and here for the package, Android actually doesn't like dashes in there
but you may use underscores, so let's use this. With that fixed, now let's run expo publish again to again
validate this and then publish the most recent version
to expo's servers which again will not start the build process yet but which is an important preparation
and once this is done, you're ready to also build your app for Android
and iOS.
Now the difference between publishing and building is that publishing just pushes your code and configuration
to expo's servers and you can then scan the barcode with the expo client and so on.
Building means that you'll leverage expo's cloud build service to really build an Android app bundle
or an iOS IPA file,
these are the files which you then upload to the app stores thereafter so there is a huge difference
here. Now these bundles which you build
as mentioned before include the expo client
so to say, they include this as a wrapper around your app but it's a real native app therefore after
all,
so it's a native app with just this little extra tiny wrapper around it
taking into account the configuration you set up here for example regarding the permissions.
In addition, these apps which you build on expo's servers which you then can distribute through the
app stores will talk to expo's servers for the over the air updating functionality. So you will still
just publish new updates with expo publish thereafter and your standalone apps which are running on
other devices will get these published updates,
so publishing is still important even if you're building standalone apps, if you're building app bundles
because these app bundles will continue to talk to expo's servers to get new versions.
But speaking of that, how do we build these bundles now?
You do this with the expo build command and there, you have build: Android and build:
iOS.
Well let's start with build: Android and as the name suggests, this builds an app for Android.
You can learn all about the standalone build process in the building standalone apps expo docs which
you also find attached here and there you find the basic configuration you need and what you should
take into account there. For Android, here you find that you also right now at least can choose whether
you want to build an APK or an app bundle file, building an app bundle file is recommended because that
is the preferred format
Google wants and for this, you can run instead of just expo build Android, you run expo build Android
-t app add-bundle. If you now hit enter, this will in the end validate your setup and then push
your code to expo's cloud build servers where this will now be scheduled.
Now first of all, it will ask you because apps need to be signed,
that happens with a private public key pair which in the end is used to identify you
as the author of the app, future updates of the app
and with that I don't mean updates which you published to expo's servers with the expo publish command
but when you rebuild the app, when you rebuild the package which you then reupload to the app stores
which you'll occasionally need to do if you for example change the icon or something else which can't
be shared with expo publish,
in such cases, you need to sign the update with the same keys you used for creating the original app
to identify you as the author
otherwise the App Store will deny this update, it will not accept your next version of the app. So therefore
you need to sign your app and if you know what you're doing, you can create and upload your own keys
store
but here I will stick to version one and let expo handle that
which means it will create such a key for assigning and do all the signing stuff for you on their servers,
so that's what I choose here.
Now with that, it again builds the app just as for publishing and even though I'm building Android app,
it still builds it for iOS here because in the end what it does here is it publishes the app. So let's
wait for this to finish, now it's just doing the same as expo publish it
but thereafter, it will schedule this to be built on expo's servers.
So now publishing is done and now it schedules such a build and it queues it up, this
by the way is a process you can now quit as it says here, you can always check the status of your build
by entering this URL,
you'll need to log in with your expo account there and then you can see the build status.
Now important,
this build can take very long,
the build itself not so much but until your build is built because it's scheduled,
keep in mind that this is a free service,
so of course it's not built immediately but when the expo's servers have room for it.
This can take a couple of minutes, even hours until that happens,
so don't worry if that takes some time, you can always check this URL which you're seeing in your
command line to see what's happening. So you can quit this,
this is also a URL where you will later find the build files,
so here's my build status if we check it, you see it's cute
and right now, nothing else is happening,
we can revisit this later to see the build process and download the finished app bundle and for now,
let's do the same for iOS therefore.
This can be done by running expo build
iOS. Now important, to build iOS apps, you need a paid Apple Developer account,
that's a must have.
So you will need to go to developer.apple.com and there, you will need to login with your Apple
ID and then basically get such a paid account, so you will need to add your credit card and pay a fee
of $99. That is required,
there is no way around that,
Apple requires that for you to build apps which you want to publish to their stores.
You don't need that during development
but now for sharing the app, you need to have that.
It's basically a fee that's there to only allow people to the store who have at least some kind of serious
goals there I guess.
So make sure you sign in here and set up your paid Apple Developer account to join the Apple Developer
Program and thereafter, you can run this command and
it will ask you to log in with your apple developer account. So you log in with your Apple ID and password
and that data will not be stored on expo's servers,
no worries
but it needs it to set up everything to build your app because for the Apple build process, you need
special certificates and so on which it can request on your behalf with this data.
Once you did log in, it asks you how you want to handle your credentials, just as before if you don't
know what you're doing, you should let expo handle all of that because as I mentioned, you need a couple
of special certificates to in the end build your iOS app and expo can request all of that for you and
set all of that for you, so I'll let expo do this for all these steps
and now it will basically do all that for you.
Now this also builds my app here for iOS and publishes it again first,
that's the same we did before for Android and now we also got a build scheduled for iOS. Just as before,
this is queued up, you can quit that and just watch your build here in the browser.
So now we don't just have that queued up Android build but we also have that queued up iOS build and both
will take a while until they're finished.
Now there is one important thing you also have to do after this Android build is done which it isn't
yet,
you should run expo fetch:android:keystore.
Again this only works after the build completed because this will then fetch this automatically generated
keystore which expo generates for you if you chose that in the setup which you need for future updates
of this app. You will definitely need that and in future updates when you rebuild the app,
you then have to choose that you provide your own keystore and you need to provide this keystore
then,
so enter the path to this keystore which you then download.
So this command will in the end download a file generated on expo's servers which you need to store
on your system for future update of the same app,
otherwise you'll not be able to update.
So that's some important command you'll need to run once this build is done. Well and with that, let's
wait for it to be finished,
iOS actually is already building, Android is still queued up
but iOS is already on the go,
so let's wait for the iOS build to finish and now this is done,
now my iOS build is done.
Now you can also check the official docs on how you can continue with testing this on your device or
simulator or then go to the part where you upload the app to the Apple App Store and Google Play Store.
So we build the app,
now you can upload it by running expo upload:ios, this will by default use your latest app and
upload it to the App Store.
Now it's the part which I will not do here because I don't really want to publish this app here but
it is what you would now do,
it would use this application which was just built here for iOS or for Android,
Android build is now also running as I see, so it would use this and then publish this either with this command
to iOS or with this command to the Android, to the Google Play Store.
Now follow the steps you find here in the docs to create the appropriate accounts and set up everything
correctly so that this command can succeed
and with that, you will have your app deployed to the Apple App Store and to the Google Play Store so that
you can get your app to any user around the world as a standalone app, not dependent on the expo
client being installed on the devices which is pretty neat.