1 00:00:02,410 --> 00:00:05,880 When building for the app stores, the expo CLI, 2 00:00:05,920 --> 00:00:10,780 so what we type here in the command line can help you or will help you but you might need to tweak your 3 00:00:10,780 --> 00:00:17,070 configuration in the app.json file depending on which features your application uses. 4 00:00:17,110 --> 00:00:24,160 So our application here uses a bunch of native modules, these modules all need to request permissions 5 00:00:24,250 --> 00:00:32,020 and we kind of do this with the permissions API, like for example in the image picker here when we ask 6 00:00:32,020 --> 00:00:38,590 for permissions but for Android for example, you also need to provide a list of the permissions your 7 00:00:38,590 --> 00:00:46,510 app needs in a configuration file which you, when you use React Native only have but which you don't 8 00:00:46,510 --> 00:00:53,890 have when using expo because expo provides this wrapper and does all of that for you in the expo client 9 00:00:53,890 --> 00:00:57,030 but now we don't plan on using the expo client anymore 10 00:00:57,070 --> 00:01:03,610 and whilst it will include this into your standalone app as I mentioned, you now need to tell expo which 11 00:01:03,610 --> 00:01:05,630 permissions it should request there. 12 00:01:05,890 --> 00:01:11,860 In addition for example if you're using Google Maps, you also need to provide your Google Maps API key 13 00:01:12,400 --> 00:01:17,350 and with that, I don't mean as we're doing it here which we use in some parts of our Javascript code but 14 00:01:17,350 --> 00:01:19,680 to use the React Native maps package. 15 00:01:19,720 --> 00:01:27,160 Again the expo client app basically uses its own key for development and so on but as soon as you plan 16 00:01:27,190 --> 00:01:33,670 on offering a standalone app, you need to bring your own keys so that the expo wrapper which will be 17 00:01:33,670 --> 00:01:37,480 included in your standalone app will use your key 18 00:01:37,510 --> 00:01:41,720 because the expo team won't give you a key owned by them for that. 19 00:01:42,090 --> 00:01:44,620 Again, the official docs are your friends, 20 00:01:44,620 --> 00:01:48,020 there you can learn what you can set up in the app.json file 21 00:01:48,490 --> 00:01:54,580 and let's start with Android because there, you'll have to configure a bit more before we dive into what's 22 00:01:54,670 --> 00:01:57,190 specific about iOS. 23 00:01:57,190 --> 00:02:04,210 So for Android, besides icon and so on, what you can configure there are the permissions. Now 24 00:02:04,210 --> 00:02:10,930 the thing is you can just omit the permissions key and in that case as you see here, expo will actually 25 00:02:10,930 --> 00:02:14,200 setup your app to request all permissions. 26 00:02:14,200 --> 00:02:19,600 Now I would not recommend doing that because people will look at your app in the App Store and if they 27 00:02:19,600 --> 00:02:26,980 see that your basic place management app wants permissions to read their contacts or make calls, 28 00:02:26,980 --> 00:02:30,070 well I don't know about you but I wouldn't download such an app. 29 00:02:30,070 --> 00:02:35,680 So my recommendation would be that you are specific regarding the permissions your app needs and you 30 00:02:35,680 --> 00:02:41,860 do that by going to your app.json file and there in the Android node, you add the permissions 31 00:02:42,130 --> 00:02:45,030 key and now you add permissions. 32 00:02:45,040 --> 00:02:51,130 Now some base permissions will always be requested and you find these permissions here, for example permissions 33 00:02:51,130 --> 00:02:57,040 to get data from the Internet and so on but you can now also for example add permissions to use the user 34 00:02:57,040 --> 00:03:01,100 location and access the camera because that's something we will do. 35 00:03:01,100 --> 00:03:06,670 So let's add these keys here to permissions like this, to string keys with double quotes by the way, that's 36 00:03:06,670 --> 00:03:07,960 important in this file, 37 00:03:07,990 --> 00:03:09,480 added to this permissions array. 38 00:03:10,520 --> 00:03:20,350 Now we will also need the write external storage permission to save our image, so we should add that 39 00:03:20,350 --> 00:03:21,520 as well 40 00:03:21,520 --> 00:03:26,410 and with that we should be good for this application but of course depending on the application 41 00:03:26,410 --> 00:03:29,940 you're building, carefully check which permissions your app will need, 42 00:03:30,010 --> 00:03:36,190 you can always consult the documentation pages of the native module packages you're using, there you 43 00:03:36,190 --> 00:03:38,570 should normally find a description of the permissions 44 00:03:38,620 --> 00:03:43,430 this package needs. So permissions are one thing, 45 00:03:43,650 --> 00:03:48,840 in addition if you're using Google Maps, you should add the Google Maps 46 00:03:48,840 --> 00:03:51,530 node to your Android configuration. 47 00:03:51,690 --> 00:03:52,170 So here 48 00:03:52,170 --> 00:04:00,210 after permissions, we can add Google maps like this which also holds an object as a value and in that 49 00:04:00,270 --> 00:04:00,740 object, 50 00:04:00,750 --> 00:04:02,440 you set up the API key. 51 00:04:02,490 --> 00:04:09,480 Again you didn't need that for the expo client when we publish the app to this expo page and used 52 00:04:09,510 --> 00:04:15,190 the expo client app because there the expo team basically gives you their own Google Maps key 53 00:04:15,330 --> 00:04:18,480 but if you're building a standalone app, you need to provide your own one. 54 00:04:18,480 --> 00:04:27,000 So for that, make sure you use your key here like this and also important and I mentioned this in the 55 00:04:27,360 --> 00:04:29,530 non-expo module already, 56 00:04:29,580 --> 00:04:40,260 make sure that in the Google APIs, so in the Google cloud console when you check your API library, you 57 00:04:40,260 --> 00:04:47,390 make sure that the maps SDK for Android is enabled for this project to which this API key you provided 58 00:04:47,400 --> 00:04:48,080 belongs. 59 00:04:48,090 --> 00:04:49,440 So here it is enabled, 60 00:04:49,440 --> 00:04:54,720 this has to belong to the project for which you created that API key which you now are providing here, 61 00:04:54,720 --> 00:05:00,770 otherwise this won't work. So these are the permissions and Google Map settings and you might need other 62 00:05:00,770 --> 00:05:02,980 specific settings which you can learn about 63 00:05:02,980 --> 00:05:06,710 here in the app.json file depending on which features you're using. 64 00:05:06,710 --> 00:05:10,220 You can also configure Of course everything else and so many things, 65 00:05:10,220 --> 00:05:18,540 one thing you absolutely need to provide to build your app is also this package key. 66 00:05:18,540 --> 00:05:21,940 This is something you always have to add no matter what your app uses, 67 00:05:22,050 --> 00:05:27,800 here in the Android node, you need to provide the package key and this now has to have a certain format. 68 00:05:27,810 --> 00:05:33,870 It's basically an inverse URL, a fictional URL which doesn't have to exist but which acts 69 00:05:33,870 --> 00:05:37,110 as a unique identifier across the entire Google Play Store, 70 00:05:37,110 --> 00:05:42,060 so it should be an inverse URL which no one else has used before and therefore typically if you 71 00:05:42,120 --> 00:05:48,210 own a domain, you would use your domain for example com.academind, so an inverse domain and then 72 00:05:48,270 --> 00:05:53,700 a unique identifier, like great places. You can come up with any URL you want here 73 00:05:53,790 --> 00:05:58,920 but of course again it should be unique and you should therefore use your own domain or a fictional 74 00:05:58,920 --> 00:06:00,890 domain which isn't owned by anyone, 75 00:06:00,990 --> 00:06:07,530 so not academind because I do own this, so any other domain, any other fictional identifier which should 76 00:06:07,530 --> 00:06:08,880 have this format, 77 00:06:08,880 --> 00:06:10,790 that's what you provide here. 78 00:06:10,860 --> 00:06:14,860 You also need to provide something similar on iOS, there 79 00:06:14,970 --> 00:06:21,480 if you go to iOS, you don't need to provide this permission setting stuff because iOS permissions 80 00:06:21,480 --> 00:06:22,580 work differently, 81 00:06:22,650 --> 00:06:28,020 you would need to provide a Google Maps API key if you use the Google Maps version of the maps 82 00:06:28,020 --> 00:06:33,600 package for iOS, the default of this package however is to use Apple Maps and I haven't changed this 83 00:06:33,600 --> 00:06:37,200 in my app so I don't need to provide Google Maps API here 84 00:06:37,440 --> 00:06:45,260 but what you definitely need to provide here is a bundle identifier. So replace package with bundle 85 00:06:45,260 --> 00:06:47,240 identifier and the format is the same, 86 00:06:47,240 --> 00:06:54,050 you have this inverse URL syntax here and I'll name it com.academind.great-places course and 87 00:06:54,080 --> 00:06:56,630 also use that -course edition here on Android. 88 00:06:56,810 --> 00:07:02,090 So bundle identifier for iOS and package for Android needs to be set to such an inverse unique URL. 89 00:07:02,090 --> 00:07:07,830 Now besides these identifiers, you also need to set something else, on 90 00:07:07,840 --> 00:07:15,290 iOS you need to add a build number, also here in the iOS node therefore and the build number should be a string 91 00:07:15,290 --> 00:07:23,020 which identifies your build. There, you should have a build number just like this version up there 92 00:07:23,530 --> 00:07:25,800 and working in the way I explained it up there. 93 00:07:25,810 --> 00:07:33,100 So it should be a number consisting of three digits where you have a patch number for 94 00:07:33,110 --> 00:07:39,780 patches, bug fixes, then this minor update number for new features which don't break everything 95 00:07:39,780 --> 00:07:41,820 though and this major update number, 96 00:07:41,850 --> 00:07:46,260 you can change this however you want but you should change it for every new version you publish and 97 00:07:46,260 --> 00:07:51,910 you deploy and you should of course change it such that you reflect what changed. 98 00:07:51,920 --> 00:07:53,970 Now you need something similar for Android, 99 00:07:53,970 --> 00:08:01,710 if we go back to the Android documentation, there we also need a version code. So here we add version code 100 00:08:01,870 --> 00:08:07,030 and now here this is not a string but a number which you should simply increment by one for every new 101 00:08:07,030 --> 00:08:07,810 release. 102 00:08:07,810 --> 00:08:09,170 So you start at one, 103 00:08:09,190 --> 00:08:14,950 the next version you release, even if it's just containing some tiny fixes should be two and then to 104 00:08:14,950 --> 00:08:15,910 three and so on. 105 00:08:15,910 --> 00:08:20,890 So that's what you should set up here, this is how it works for Android, you also find that description here 106 00:08:20,950 --> 00:08:23,000 in the documentation 107 00:08:23,140 --> 00:08:28,000 and with that, we're now prepared to deploy this or to build it first 108 00:08:28,000 --> 00:08:32,860 and as I mentioned, the cool thing about expo managed is that now you can build this on expo's cloud 109 00:08:32,860 --> 00:08:33,960 servers. 110 00:08:34,150 --> 00:08:41,440 So what you should do is you should run expo publish to publish the latest version of your app to expo's 111 00:08:41,500 --> 00:08:46,100 servers just like that which will not yet build it as a standalone app and 112 00:08:47,370 --> 00:08:54,190 now what I get here are a couple of warnings or errors. So we see that Android should not have additional 113 00:08:54,190 --> 00:08:55,360 property Google Maps, 114 00:08:59,710 --> 00:09:02,300 yes because that should be in a config node, 115 00:09:02,410 --> 00:09:03,490 my mistake. 116 00:09:03,490 --> 00:09:08,890 So you should add config here and in config, you might have this Google Maps key, 117 00:09:08,890 --> 00:09:15,780 that's a tiny mistake on my side and here for the package, Android actually doesn't like dashes in there 118 00:09:15,850 --> 00:09:24,170 but you may use underscores, so let's use this. With that fixed, now let's run expo publish again to again 119 00:09:24,170 --> 00:09:27,230 validate this and then publish the most recent version 120 00:09:27,320 --> 00:09:33,890 to expo's servers which again will not start the build process yet but which is an important preparation 121 00:09:35,170 --> 00:09:40,360 and once this is done, you're ready to also build your app for Android 122 00:09:40,390 --> 00:09:41,120 and iOS. 123 00:09:41,170 --> 00:09:45,910 Now the difference between publishing and building is that publishing just pushes your code and configuration 124 00:09:45,910 --> 00:09:50,540 to expo's servers and you can then scan the barcode with the expo client and so on. 125 00:09:50,560 --> 00:09:56,590 Building means that you'll leverage expo's cloud build service to really build an Android app bundle 126 00:09:56,830 --> 00:09:59,480 or an iOS IPA file, 127 00:09:59,500 --> 00:10:04,090 these are the files which you then upload to the app stores thereafter so there is a huge difference 128 00:10:04,090 --> 00:10:06,780 here. Now these bundles which you build 129 00:10:06,800 --> 00:10:10,220 as mentioned before include the expo client 130 00:10:10,220 --> 00:10:15,290 so to say, they include this as a wrapper around your app but it's a real native app therefore after 131 00:10:15,290 --> 00:10:15,520 all, 132 00:10:15,530 --> 00:10:19,410 so it's a native app with just this little extra tiny wrapper around it 133 00:10:19,490 --> 00:10:24,840 taking into account the configuration you set up here for example regarding the permissions. 134 00:10:24,870 --> 00:10:31,890 In addition, these apps which you build on expo's servers which you then can distribute through the 135 00:10:31,890 --> 00:10:39,300 app stores will talk to expo's servers for the over the air updating functionality. So you will still 136 00:10:39,300 --> 00:10:45,750 just publish new updates with expo publish thereafter and your standalone apps which are running on 137 00:10:45,750 --> 00:10:48,900 other devices will get these published updates, 138 00:10:48,900 --> 00:10:53,820 so publishing is still important even if you're building standalone apps, if you're building app bundles 139 00:10:54,000 --> 00:10:59,160 because these app bundles will continue to talk to expo's servers to get new versions. 140 00:10:59,280 --> 00:11:01,720 But speaking of that, how do we build these bundles now? 141 00:11:01,720 --> 00:11:07,770 You do this with the expo build command and there, you have build: Android and build: 142 00:11:07,770 --> 00:11:08,780 iOS. 143 00:11:08,880 --> 00:11:16,020 Well let's start with build: Android and as the name suggests, this builds an app for Android. 144 00:11:16,020 --> 00:11:21,540 You can learn all about the standalone build process in the building standalone apps expo docs which 145 00:11:21,540 --> 00:11:27,210 you also find attached here and there you find the basic configuration you need and what you should 146 00:11:27,210 --> 00:11:33,710 take into account there. For Android, here you find that you also right now at least can choose whether 147 00:11:33,710 --> 00:11:39,200 you want to build an APK or an app bundle file, building an app bundle file is recommended because that 148 00:11:39,260 --> 00:11:40,780 is the preferred format 149 00:11:40,850 --> 00:11:47,330 Google wants and for this, you can run instead of just expo build Android, you run expo build Android 150 00:11:47,330 --> 00:11:54,710 -t app add-bundle. If you now hit enter, this will in the end validate your setup and then push 151 00:11:54,710 --> 00:12:00,350 your code to expo's cloud build servers where this will now be scheduled. 152 00:12:00,350 --> 00:12:05,330 Now first of all, it will ask you because apps need to be signed, 153 00:12:05,360 --> 00:12:10,210 that happens with a private public key pair which in the end is used to identify you 154 00:12:10,220 --> 00:12:13,200 as the author of the app, future updates of the app 155 00:12:13,220 --> 00:12:18,250 and with that I don't mean updates which you published to expo's servers with the expo publish command 156 00:12:18,410 --> 00:12:23,600 but when you rebuild the app, when you rebuild the package which you then reupload to the app stores 157 00:12:23,900 --> 00:12:28,940 which you'll occasionally need to do if you for example change the icon or something else which can't 158 00:12:28,940 --> 00:12:30,670 be shared with expo publish, 159 00:12:30,740 --> 00:12:36,890 in such cases, you need to sign the update with the same keys you used for creating the original app 160 00:12:37,130 --> 00:12:39,050 to identify you as the author 161 00:12:39,050 --> 00:12:45,530 otherwise the App Store will deny this update, it will not accept your next version of the app. So therefore 162 00:12:45,530 --> 00:12:50,120 you need to sign your app and if you know what you're doing, you can create and upload your own keys 163 00:12:50,120 --> 00:12:50,770 store 164 00:12:50,810 --> 00:12:54,090 but here I will stick to version one and let expo handle that 165 00:12:54,170 --> 00:13:00,300 which means it will create such a key for assigning and do all the signing stuff for you on their servers, 166 00:13:00,350 --> 00:13:01,520 so that's what I choose here. 167 00:13:04,640 --> 00:13:13,820 Now with that, it again builds the app just as for publishing and even though I'm building Android app, 168 00:13:13,820 --> 00:13:19,700 it still builds it for iOS here because in the end what it does here is it publishes the app. So let's 169 00:13:19,700 --> 00:13:27,160 wait for this to finish, now it's just doing the same as expo publish it 170 00:13:27,190 --> 00:13:32,310 but thereafter, it will schedule this to be built on expo's servers. 171 00:13:32,350 --> 00:13:38,060 So now publishing is done and now it schedules such a build and it queues it up, this 172 00:13:38,170 --> 00:13:42,670 by the way is a process you can now quit as it says here, you can always check the status of your build 173 00:13:42,940 --> 00:13:44,570 by entering this URL, 174 00:13:44,620 --> 00:13:48,720 you'll need to log in with your expo account there and then you can see the build status. 175 00:13:48,880 --> 00:13:49,700 Now important, 176 00:13:49,810 --> 00:13:51,380 this build can take very long, 177 00:13:51,430 --> 00:13:57,100 the build itself not so much but until your build is built because it's scheduled, 178 00:13:57,100 --> 00:13:59,260 keep in mind that this is a free service, 179 00:13:59,380 --> 00:14:03,800 so of course it's not built immediately but when the expo's servers have room for it. 180 00:14:03,910 --> 00:14:08,240 This can take a couple of minutes, even hours until that happens, 181 00:14:08,320 --> 00:14:13,030 so don't worry if that takes some time, you can always check this URL which you're seeing in your 182 00:14:13,060 --> 00:14:16,490 command line to see what's happening. So you can quit this, 183 00:14:16,500 --> 00:14:20,740 this is also a URL where you will later find the build files, 184 00:14:20,740 --> 00:14:26,830 so here's my build status if we check it, you see it's cute 185 00:14:26,830 --> 00:14:28,380 and right now, nothing else is happening, 186 00:14:28,380 --> 00:14:33,820 we can revisit this later to see the build process and download the finished app bundle and for now, 187 00:14:33,820 --> 00:14:35,890 let's do the same for iOS therefore. 188 00:14:35,950 --> 00:14:38,500 This can be done by running expo build 189 00:14:38,610 --> 00:14:44,890 iOS. Now important, to build iOS apps, you need a paid Apple Developer account, 190 00:14:44,890 --> 00:14:46,270 that's a must have. 191 00:14:46,690 --> 00:14:53,590 So you will need to go to developer.apple.com and there, you will need to login with your Apple 192 00:14:53,590 --> 00:14:59,650 ID and then basically get such a paid account, so you will need to add your credit card and pay a fee 193 00:14:59,650 --> 00:15:02,050 of $99. That is required, 194 00:15:02,050 --> 00:15:03,230 there is no way around that, 195 00:15:03,310 --> 00:15:07,930 Apple requires that for you to build apps which you want to publish to their stores. 196 00:15:07,930 --> 00:15:10,210 You don't need that during development 197 00:15:10,210 --> 00:15:13,200 but now for sharing the app, you need to have that. 198 00:15:13,240 --> 00:15:20,290 It's basically a fee that's there to only allow people to the store who have at least some kind of serious 199 00:15:20,680 --> 00:15:22,510 goals there I guess. 200 00:15:22,510 --> 00:15:28,210 So make sure you sign in here and set up your paid Apple Developer account to join the Apple Developer 201 00:15:28,210 --> 00:15:31,490 Program and thereafter, you can run this command and 202 00:15:31,560 --> 00:15:38,440 it will ask you to log in with your apple developer account. So you log in with your Apple ID and password 203 00:15:38,500 --> 00:15:42,880 and that data will not be stored on expo's servers, 204 00:15:42,880 --> 00:15:43,960 no worries 205 00:15:43,960 --> 00:15:49,660 but it needs it to set up everything to build your app because for the Apple build process, you need 206 00:15:49,660 --> 00:15:54,550 special certificates and so on which it can request on your behalf with this data. 207 00:15:54,640 --> 00:15:59,800 Once you did log in, it asks you how you want to handle your credentials, just as before if you don't 208 00:15:59,800 --> 00:16:04,330 know what you're doing, you should let expo handle all of that because as I mentioned, you need a couple 209 00:16:04,330 --> 00:16:11,920 of special certificates to in the end build your iOS app and expo can request all of that for you and 210 00:16:11,920 --> 00:16:17,650 set all of that for you, so I'll let expo do this for all these steps 211 00:16:17,960 --> 00:16:21,080 and now it will basically do all that for you. 212 00:16:21,080 --> 00:16:26,500 Now this also builds my app here for iOS and publishes it again first, 213 00:16:26,510 --> 00:16:33,940 that's the same we did before for Android and now we also got a build scheduled for iOS. Just as before, 214 00:16:33,960 --> 00:16:40,020 this is queued up, you can quit that and just watch your build here in the browser. 215 00:16:40,030 --> 00:16:45,660 So now we don't just have that queued up Android build but we also have that queued up iOS build and both 216 00:16:45,660 --> 00:16:48,680 will take a while until they're finished. 217 00:16:48,690 --> 00:16:53,460 Now there is one important thing you also have to do after this Android build is done which it isn't 218 00:16:53,460 --> 00:16:54,510 yet, 219 00:16:54,510 --> 00:17:00,300 you should run expo fetch:android:keystore. 220 00:17:00,300 --> 00:17:05,580 Again this only works after the build completed because this will then fetch this automatically generated 221 00:17:05,580 --> 00:17:12,900 keystore which expo generates for you if you chose that in the setup which you need for future updates 222 00:17:13,030 --> 00:17:17,420 of this app. You will definitely need that and in future updates when you rebuild the app, 223 00:17:17,460 --> 00:17:22,070 you then have to choose that you provide your own keystore and you need to provide this keystore 224 00:17:22,070 --> 00:17:22,310 then, 225 00:17:22,320 --> 00:17:25,330 so enter the path to this keystore which you then download. 226 00:17:25,350 --> 00:17:30,630 So this command will in the end download a file generated on expo's servers which you need to store 227 00:17:30,630 --> 00:17:33,570 on your system for future update of the same app, 228 00:17:33,600 --> 00:17:35,980 otherwise you'll not be able to update. 229 00:17:36,000 --> 00:17:41,040 So that's some important command you'll need to run once this build is done. Well and with that, let's 230 00:17:41,040 --> 00:17:42,600 wait for it to be finished, 231 00:17:42,600 --> 00:17:46,610 iOS actually is already building, Android is still queued up 232 00:17:46,620 --> 00:17:49,120 but iOS is already on the go, 233 00:17:49,120 --> 00:17:53,830 so let's wait for the iOS build to finish and now this is done, 234 00:17:53,830 --> 00:17:57,200 now my iOS build is done. 235 00:17:57,330 --> 00:18:02,730 Now you can also check the official docs on how you can continue with testing this on your device or 236 00:18:02,730 --> 00:18:08,720 simulator or then go to the part where you upload the app to the Apple App Store and Google Play Store. 237 00:18:08,730 --> 00:18:09,690 So we build the app, 238 00:18:09,690 --> 00:18:16,930 now you can upload it by running expo upload:ios, this will by default use your latest app and 239 00:18:17,020 --> 00:18:18,630 upload it to the App Store. 240 00:18:18,640 --> 00:18:24,100 Now it's the part which I will not do here because I don't really want to publish this app here but 241 00:18:24,100 --> 00:18:25,710 it is what you would now do, 242 00:18:25,780 --> 00:18:30,570 it would use this application which was just built here for iOS or for Android, 243 00:18:30,580 --> 00:18:36,160 Android build is now also running as I see, so it would use this and then publish this either with this command 244 00:18:36,160 --> 00:18:40,780 to iOS or with this command to the Android, to the Google Play Store. 245 00:18:40,780 --> 00:18:45,970 Now follow the steps you find here in the docs to create the appropriate accounts and set up everything 246 00:18:45,970 --> 00:18:49,150 correctly so that this command can succeed 247 00:18:49,150 --> 00:18:55,450 and with that, you will have your app deployed to the Apple App Store and to the Google Play Store so that 248 00:18:55,450 --> 00:19:02,140 you can get your app to any user around the world as a standalone app, not dependent on the expo 249 00:19:02,140 --> 00:19:05,440 client being installed on the devices which is pretty neat.