1"use strict";(self.webpackChunkionic_docs=self.webpackChunkionic_docs||[]).push([["3110"],{56791(e,i,n){n.r(i),n.d(i,{metadata:()=>t,default:()=>p,frontMatter:()=>r,contentTitle:()=>s,toc:()=>c,assets:()=>d});var t=JSON.parse('{"id":"angular/your-first-app/deploying-mobile","title":"Deploying to iOS and Android","description":"Adding Mobile Support with Angular | Ionic Capacitor Camera","source":"@site/docs/angular/your-first-app/6-deploying-mobile.md","sourceDirName":"angular/your-first-app","slug":"/angular/your-first-app/deploying-mobile","permalink":"/docs/angular/your-first-app/deploying-mobile","draft":false,"unlisted":false,"editUrl":"https://github.com/ionic-team/ionic-docs/edit/main/docs/angular/your-first-app/6-deploying-mobile.md","tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"title":"Deploying to iOS and Android","sidebar_label":"\u30E2\u30D0\u30A4\u30EB\u3078\u306E\u30C7\u30D7\u30ED\u30A4"},"sidebar":"docs","previous":{"title":"Adding Mobile","permalink":"/docs/angular/your-first-app/adding-mobile"},"next":{"title":"\u30E9\u30A4\u30D6\u30EA\u30ED\u30FC\u30C9","permalink":"/docs/angular/your-first-app/live-reload"}}'),o=n(74848),a=n(28453);let r={title:"Deploying to iOS and Android",sidebar_label:"\u30E2\u30D0\u30A4\u30EB\u3078\u306E\u30C7\u30D7\u30ED\u30A4"},s,d={},c=[{value:"Capacitor Setup",id:"capacitor-setup",level:2},{value:"iOS Deployment",id:"ios-deployment",level:2},{value:"Android Deployment",id:"android-deployment",level:2}];function l(e){let i={a:"a",admonition:"admonition",code:"code",h2:"h2",img:"img",p:"p",pre:"pre",...(0,a.R)(),...e.components},{Head:t}=i;return t||function(e,i){throw Error("Expected "+(i?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Head",!0),(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t,{children:[(0,o.jsx)("title",{children:"Adding Mobile Support with Angular | Ionic Capacitor Camera"}),(0,o.jsx)("meta",{name:"description",content:"Deploying to iOS and Android is easy with Capacitor setup for Ionic Framework apps. Read to learn more about deployment in our Ionic Documentation."})]}),"\n",(0,o.jsx)(i.p,{children:"Since we added Capacitor to our project when it was first created, there\u2019s only a handful of steps remaining until the Photo Gallery app is on our device!"}),"\n",(0,o.jsx)(i.h2,{id:"capacitor-setup",children:"Capacitor Setup"}),"\n",(0,o.jsxs)(i.p,{children:["Capacitor \u306F Ionic \u306E\u516C\u5F0F\u30A2\u30D7\u30EA\u30E9\u30F3\u30BF\u30A4\u30E0\u3067\u3001Web \u30A2\u30D7\u30EA\u3092 iOS\u3001Android \u306A\u3069\u306E\u30CD\u30A4\u30C6\u30A3\u30D6\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u306B\u7C21\u5358\u306B\u30C7\u30D7\u30ED\u30A4\u3067\u304D\u308B\u3088\u3046\u306B\u3057\u307E\u3059\u3002\u904E\u53BB\u306B Cordova \u3092\u4F7F\u7528\u3057\u305F\u3053\u3068\u304C\u3042\u308B\u5834\u5408\u306F\u3001Capacitor \u3068 Cordova \u306E",(0,o.jsx)(i.a,{href:"https://capacitorjs.com/docs/cordova#differences-between-capacitor-and-cordova",children:"\u9055\u3044"}),"\u306B\u3064\u3044\u3066\u3055\u3089\u306B\u8AAD\u3080\u3053\u3068\u3092\u691C\u8A0E\u3057\u3066\u304F\u3060\u3055\u3044\u3002"]}),"\n",(0,o.jsxs)(i.p,{children:["If you\u2019re still running ",(0,o.jsx)(i.code,{children:"ionic serve"})," in the terminal, cancel it. Complete a fresh build of the Ionic project, fixing any errors that it reports:"]}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-shell",children:"ionic build\n"})}),"\n",(0,o.jsx)(i.p,{children:"Next, create both the iOS and Android projects:"}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-shell",children:"ionic cap add ios\nionic cap add android\n"})}),"\n",(0,o.jsx)(i.p,{children:"Both android and ios folders at the root of the project are created. These are entirely standalone native projects that should be considered part of your Ionic app (i.e., check them into source control, edit them using their native tooling, etc.)."}),"\n",(0,o.jsxs)(i.p,{children:["Every time you perform a build (e.g. ",(0,o.jsx)(i.co
1de,{children:"ionic build"}),") that updates your web directory (default: ",(0,o.jsx)(i.code,{children:"www"}),"), you'll need to copy those changes into your native projects:"]}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-shell",children:"ionic cap copy\n"})}),"\n",(0,o.jsxs)(i.p,{children:["Note: After making updates to the native portion of the code (such as adding a new plugin), use the ",(0,o.jsx)(i.code,{children:"sync"})," command:"]}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-shell",children:"ionic cap sync\n"})}),"\n",(0,o.jsx)(i.h2,{id:"ios-deployment",children:"iOS Deployment"}),"\n",(0,o.jsx)(i.admonition,{type:"important",children:(0,o.jsx)(i.p,{children:"To build an iOS app, you\u2019ll need a Mac computer."})}),"\n",(0,o.jsxs)(i.p,{children:["Capacitor iOS apps are configured and managed through Xcode (Apple\u2019s iOS/Mac IDE), with dependencies managed by ",(0,o.jsx)(i.a,{href:"https://cocoapods.org/",children:"CocoaPods"}),". Before running this app on an iOS device, there's a couple of steps to complete."]}),"\n",(0,o.jsxs)(i.p,{children:["First, run the Capacitor ",(0,o.jsx)(i.code,{children:"open"})," command, which opens the native iOS project in Xcode:"]}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-shell",children:"ionic cap open ios\n"})}),"\n",(0,o.jsxs)(i.p,{children:["\u4E00\u90E8\u306E\u30CD\u30A4\u30C6\u30A3\u30D6\u30D7\u30E9\u30B0\u30A4\u30F3\u3092\u52D5\u4F5C\u3055\u305B\u308B\u305F\u3081\u306B\u306F\u3001\u30E6\u30FC\u30B6\u30FC\u306E\u6A29\u9650\u8A2D\u5B9A\u304C\u5FC5\u8981\u3067\u3059\u3002\u79C1\u305F\u3061\u306E\u30D5\u30A9\u30C8\u30AE\u30E3\u30E9\u30EA\u30FC\u30A2\u30D7\u30EA\u3067\u306F\u3001\u3053\u308C\u306B\u306F\u30AB\u30E1\u30E9\u30D7\u30E9\u30B0\u30A4\u30F3\u304C\u542B\u307E\u308C\u307E\u3059\uFF1AiOS \u3067\u306F\u3001",(0,o.jsx)(i.code,{children:"Camera.getPhoto()"})," \u304C\u6700\u521D\u306B\u547C\u3073\u51FA\u3055\u308C\u305F\u5F8C\u3001\u81EA\u52D5\u7684\u306B\u30E2\u30FC\u30C0\u30EB\u30C0\u30A4\u30A2\u30ED\u30B0\u304C\u8868\u793A\u3055\u308C\u3001\u30E6\u30FC\u30B6\u30FC\u306B\u30A2\u30D7\u30EA\u306B\u3088\u308B\u30AB\u30E1\u30E9\u306E\u4F7F\u7528\u8A31\u53EF\u3092\u6C42\u3081\u307E\u3059\u3002\u3053\u306E\u6A29\u9650\u306F\u300C\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC - \u30AB\u30E1\u30E9\u4F7F\u7528\u300D\u3068\u8868\u793A\u3055\u308C\u307E\u3059\u3002\u8A2D\u5B9A\u3059\u308B\u306B\u306F\u3001",(0,o.jsx)(i.code,{children:"Info.plist"})," \u30D5\u30A1\u30A4\u30EB\u3092\u4FEE\u6B63\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF08",(0,o.jsx)(i.a,{href:"https://capacitorjs.com/docs/ios/configuration",children:"iOS \u69CB\u6210\u306E\u8A73\u7D30"}),"\uFF09\u3002\u30A2\u30AF\u30BB\u30B9\u3059\u308B\u306B\u306F\u3001\u300CInfo\u300D\u3092\u30AF\u30EA\u30C3\u30AF\u3057\u3001\u300C\u30AB\u30B9\u30BF\u30E0 iOS \u30BF\u30FC\u30B2\u30C3\u30C8\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u300D\u3092\u5C55\u958B\u3057\u307E\u3059\u3002"]}),"\n",(0,o.jsx)(i.p,{children:(0,o.jsx)(i.img,{alt:"The Info.plist file in Xcode showing the NSCameraUsageDescription key added for camera access.",src:n(16814).A+"",title:"Xcode Info.plist Configuration",width:"814",height:"281"})}),"\n",(0,o.jsxs)(i.p,{children:["Each setting in ",(0,o.jsx)(i.code,{children:"Info.plist"}),' has a low-level parameter name and a high-level name. By default, the property list editor shows the high-level names, but it\'s often useful to switch to showing the raw, low-level names. To do this, right-click anywhere in the property list editor and toggle "Raw Keys/Values."']}),"\n",(0,o.jsxs)(i.p,{children:["Add the ",(0,o.jsx)(i.code,{children:"NSCameraUsageDescription"}),' Key and set the Value to something that describes why the app needs to use the camera, such as "To Take Photos." The Value field is displayed to the app user when the permission prompt opens.']}),"\n",(0,o.jsxs)(i.p,{children:["Follow the same process to add the other two Keys required of the Camera plugin: ",(0,o.jsx)(i.code,{children:"NSPhotoLibraryAddUsageDescription"}
1)," and ",(0,o.jsx)(i.code,{children:"NSPhotoLibraryUsageDescription"}),"."]}),"\n",(0,o.jsxs)(i.p,{children:["Next, click on ",(0,o.jsx)(i.code,{children:"App"})," in the Project Navigator on the left-hand side, then within the ",(0,o.jsx)(i.code,{children:"Signing & Capabilities"})," section, select your Development Team."]}),"\n",(0,o.jsx)(i.p,{children:(0,o.jsx)(i.img,{alt:"The Xcode interface displaying the Signing and Capabilities tab for an iOS app project.",src:n(56240).A+"",title:"Xcode Signing & Capabilities",width:"2484",height:"898"})}),"\n",(0,o.jsxs)(i.p,{children:["With permissions in place and Development Team selected, we are ready to try out the app on a real device! Connect an iOS device to your Mac computer, select it (",(0,o.jsx)(i.code,{children:"App -> Matthew\u2019s iPhone"}),' for me) then click the "Build" button to build, install, and launch the app on your device:']}),"\n",(0,o.jsx)(i.p,{children:(0,o.jsx)(i.img,{alt:"Xcode toolbar highlighting the Build button used to compile and run an iOS app.",src:n(17560).A+"",title:"Xcode Build Button",width:"359",height:"110"})}),"\n",(0,o.jsx)(i.p,{children:"Upon tapping the Camera button on the Photo Gallery tab, the permission prompt will display. Tap OK, then take a picture with the Camera. Afterward, the photo shows in the app!"}),"\n",(0,o.jsx)(i.p,{children:(0,o.jsx)(i.img,{alt:"Two iPhones side by side, one showing the camera permission prompt and the other displaying a photo taken with the app.",src:n(50306).A+"",title:"iOS Camera Permission Prompt and Photo Result",width:"1454",height:"1304"})}),"\n",(0,o.jsx)(i.h2,{id:"android-deployment",children:"Android Deployment"}),"\n",(0,o.jsx)(i.p,{children:"Capacitor Android apps are configured and managed through Android Studio. Before running this app on an Android device, there's a couple of steps to complete."}),"\n",(0,o.jsxs)(i.p,{children:["First, run the Capacitor ",(0,o.jsx)(i.code,{children:"open"})," command, which opens the native Android project in Android Studio:"]}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-shell",children:"ionic cap open android\n"})}),"\n",(0,o.jsxs)(i.p,{children:["Similar to iOS, we must enable the correct permissions to use the Camera. Configure these in the ",(0,o.jsx)(i.code,{children:"AndroidManifest.xml"})," file. Android Studio will likely open this file automatically, but in case it doesn't, locate it under ",(0,o.jsx)(i.code,{children:"android/app/src/main/"}),"."]}),"\n",(0,o.jsx)(i.p,{children:(0,o.jsx)(i.img,{alt:"Android Studio editor showing the AndroidManifest.xml file with camera permissions.",src:n(9840).A+"",title:"Android Manifest Permissions",width:"995",height:"718"})}),"\n",(0,o.jsxs)(i.p,{children:["Scroll to the ",(0,o.jsx)(i.code,{children:"Permissions"})," section and ensure these entries are included:"]}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-xml",children:'<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>\n<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />\n'})}),"\n",(0,o.jsx)(i.p,{children:'Save the file. With permissions in place, we are ready to try out the app on a real device! Connect an Android device to your computer. Within Android Studio, click the "Run" button, select the attached Android device, then click OK to build, install, and launch the app on your device.'}),"\n",(0,o.jsx)(i.p,{children:(0,o.jsx)(i.img,{alt:"The Android Studio interface with arrows pointing to the Run button and the connected device.",src:n(86913).A+"",title:"Android Studio Run Configuration",width:"628",height:"281"})}),"\n",(0,o.jsx)(i.p,{children:"Once again, upon tapping the Camera button on the Photo Gallery tab, the permission prompt should be displayed. Tap OK, then take a picture with the Camera. Afterward, the photo should appear in the app."}),"\n",(0,o.jsx)(i.p,{children:(0,o.jsx)(i.img,{alt:"Two Android phones side by side, one showing the camera permission prompt and the other displaying a photo taken with the app.",src:n(80056).A+"",title:"Android Permissions and Photo Capture",width:"1460",height:"1272"})}),"\n",(0,o.jsx)(i.p,{children:"Our Photo Gallery app has just been deployed to Android and iOS devices. \u{1F389}"}),"\n",(0,o.jsx)(i.p,{children:"In the final portion of this tutorial, we\u2019ll use the Ionic CLI\u2019s Live Reload functionality to quickly implement photo deletion - thus completing our Photo Gallery feature."})]})}function p(e={}){let{wrapper:i}={...(0,a.R)(),...e.components};return i?(0,o.jsx)(i,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},86913(e,i,n){n.d(i,{A:()=>t});let t=n.p+"assets/images/android-device-8b3018202541360e0e96a79e2450000b.png"},9840(e,i,n){n.d(i,{A:()=>t});let t=n.p+"assets/images/android-manifest-647a7d01c724948e2425de15485b32fa.png"},80056(e,i,n){n.d(i,{A:()=>t});
1let t=n.p+"assets/images/android-permissions-photo-8d864969f3b5c99f5e420c2d03d34c25.png"},50306(e,i,n){n.d(i,{A:()=>t});let t=n.p+"assets/images/ios-permissions-photo-60dc28e6596c4d3705f87a11aafa1791.png"},17560(e,i,n){n.d(i,{A:()=>t});let t=n.p+"assets/images/xcode-build-button-8c12390e6aa4be6b7660a17ff2638ddd.png"},16814(e,i,n){n.d(i,{A:()=>t});let t=n.p+"assets/images/xcode-info-plist-c32d110907f566a8c66942fe4b9c8972.png"},56240(e,i,n){n.d(i,{A:()=>t});let t=n.p+"assets/images/xcode-signing-8ed68e36b712b826ee29b0b3c805d664.png"},28453(e,i,n){n.d(i,{R:()=>r,x:()=>s});var t=n(96540);let o={},a=t.createContext(o);function r(e){let i=t.useContext(a);return t.useMemo(function(){return"function"==typeof e?e(i):{...i,...e}},[i,e])}function s(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),t.createElement(a.Provider,{value:i},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.