「NativeScript」の版間の差分
(→インストール) |
|||
(同じ利用者による、間の17版が非表示) | |||
1行目: | 1行目: | ||
− | NativeScript | + | NativeScript はクロスプラットフォーム (iOS と Android) のアプリケーションを構築するフレームワーク。 |
HTML, CSS, JavaScript を使用して OS native の API にアクセスする。[[Category:How-To]] | HTML, CSS, JavaScript を使用して OS native の API にアクセスする。[[Category:How-To]] | ||
− | + | 公式ドキュメントは https://docs.nativescript.org/ にある。 | |
== [https://play.nativescript.org/ NativeScript Playground] == | == [https://play.nativescript.org/ NativeScript Playground] == | ||
16行目: | 16行目: | ||
== CLI (コマンドラインインターフェイス) == | == CLI (コマンドラインインターフェイス) == | ||
+ | === インストール === | ||
+ | Xcode に依存しているので、あらかじめ App Store から Xcode をインストールしておく。 | ||
+ | |||
+ | cocoapods, xcodeproj に依存しているので、インストールする。 | ||
+ | <pre> | ||
+ | $ sudo gem install cocoapods xcodeproj | ||
+ | </pre> | ||
+ | |||
node.js に依存しているので、node.js をインストールする。 | node.js に依存しているので、node.js をインストールする。 | ||
Mac の場合は、[[homebrew]] を使って、 | Mac の場合は、[[homebrew]] を使って、 | ||
71行目: | 79行目: | ||
これで一応はテストができる。 | これで一応はテストができる。 | ||
− | === | + | === Simulatorでのテスト === |
xcode のデバイスシミュレーターでテストする時は、 | xcode のデバイスシミュレーターでテストする時は、 | ||
<pre> | <pre> | ||
88行目: | 96行目: | ||
と叩く。 | と叩く。 | ||
− | + | [[#Development provisioning profile|あとで]]説明する Developer provisioning profile を作り、そこにリアルデバイス (iPhone, iPad) の device id を登録しておくと、実機でのテストもできる。 | |
+ | 同じ <code>instruments</code> コマンドで Mac につながっている実機の device id もわかる。 | ||
== App Store に載せるまで == | == App Store に載せるまで == | ||
286行目: | 295行目: | ||
いろいろ試したが、次のようにやったらうまくいった。 | いろいろ試したが、次のようにやったらうまくいった。 | ||
+ | |||
+ | App_Resources/iOS/build.xcconfig に以下の2行を追加。 | ||
+ | <pre> | ||
+ | PROVISIONING_PROFILE = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx; | ||
+ | PROVISIONING_PROFILE_SPECIFIER = <distribution-profile-name>; | ||
+ | </pre> | ||
<pre> | <pre> | ||
$ tns publish ios --provision xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --appleApplicationSpecificPassword xxxx-xxxx-xxxx-xxxx | $ tns publish ios --provision xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --appleApplicationSpecificPassword xxxx-xxxx-xxxx-xxxx | ||
304行目: | 319行目: | ||
入力を迷った項目: | 入力を迷った項目: | ||
− | * 暗号を使うか? = REST API を https | + | * 暗号を使うか? = REST API を https で呼んでいるので、yes。ただし、https のみを使用にチェック。 |
* IDFAを使うか? = 広告を表示するので (自分は使わないが) 広告配信サービスが使うだろうから yes。 | * IDFAを使うか? = 広告を表示するので (自分は使わないが) 広告配信サービスが使うだろうから yes。 | ||
+ | |||
+ | == Plugin == | ||
+ | |||
+ | === Geolocation Plugin === | ||
+ | |||
+ | ==== インストール ==== | ||
+ | <pre> | ||
+ | $ tns plugin add nativescript-geolocation | ||
+ | </pre> | ||
+ | |||
+ | ==== 使い方 ==== | ||
+ | https://github.com/NativeScript/nativescript-geolocation 参照 | ||
+ | |||
+ | === NativeScript Plugin for Google Maps === | ||
+ | |||
+ | ==== インストール ==== | ||
+ | <pre> | ||
+ | $ tns plugin add nativescript-google-maps-sdk | ||
+ | </pre> | ||
+ | |||
+ | ==== 使い方 ==== | ||
+ | 詳細は https://www.npmjs.com/package/nativescript-google-maps-sdk を参照。 | ||
+ | |||
+ | <code>app.module.ts</code>に以下のコードを追加: | ||
+ | <pre> | ||
+ | import * as platform from "platform"; | ||
+ | declare var GMSServices: any; | ||
+ | |||
+ | .... | ||
+ | |||
+ | if (platform.isIOS) { | ||
+ | GMSServices.provideAPIKey("PUT_API_KEY_HERE"); | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | 地図を使うコンポーネント (例: <code>map.component.*</code>) に以下のようなコードを埋める。 | ||
+ | <pre>map.component.html | ||
+ | <GridLayout> | ||
+ | <MapView | ||
+ | [latitude]="latitude" | ||
+ | [longitude]="longitude" | ||
+ | [zoom]="zoom" | ||
+ | [bearing]="bearing" | ||
+ | [tilt]="tilt" | ||
+ | [mapAnimationsEnabled]="mapAnimationsEnabled" | ||
+ | [padding]="padding" | ||
+ | (mapReady)="onMapReady($event)" | ||
+ | (markerSelect)="onMarkerSelect($event)" | ||
+ | (markerBeginDragging)="onMarkerBeginDragging()" | ||
+ | (markerEndDragging)="onMarkerEndDragging()" | ||
+ | (markerDrag)="onMarkerDrag()" | ||
+ | (cameraChanged)="onCameraChanged()" | ||
+ | (cameraMove)="onCameraMove()"></MapView> | ||
+ | </GridLayout> | ||
+ | </pre> | ||
+ | |||
+ | <pre>map.component.ts | ||
+ | import { MapView, Marker, Position, Polyline } from "nativescript-google-maps-sdk"; | ||
+ | ... | ||
+ | export class MapComonent implements OnInit { | ||
+ | private mapView: MapView; | ||
+ | |||
+ | onMapRead(event): void { | ||
+ | this.mapView = event.object; | ||
+ | ... | ||
+ | } | ||
+ | |||
+ | onMarkerSelect(event): void { | ||
+ | const marker = event.marker; | ||
+ | const userData = marker.userData; | ||
+ | ... | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | === NativeScript Plugin for Google Admob === | ||
+ | [https://admob.google.com/home/ Google Admob] はモバイルアプリむけの広告配信サービス。 | ||
+ | 狭いスマホの画面で広告は邪魔だが、on/off をコントロールできたら、使える事もある (かも)。 | ||
+ | |||
+ | [https://www.nsplugins.com/plugin/nativescript-admob NativeScript AdMob plugin] はこれを実現してくれる。 | ||
+ | |||
+ | ==== Install ==== | ||
+ | <pre> | ||
+ | $ tns plugin add nativescript-admob | ||
+ | </pre> | ||
+ | |||
+ | ==== 使い方 ==== | ||
+ | NativeScript 4.0 以降は<code>App_Resources/iOS/Info.plist</code> にこれが必要。 | ||
+ | <pre> | ||
+ | <key>GADApplicationIdentifier</key> | ||
+ | <string>ca-app-pub-9517346003011652~2508636525</string> | ||
+ | </pre> | ||
+ | さらに、次のコマンドを叩いておく。 | ||
+ | <pre> | ||
+ | $ pod repo update | ||
+ | </pre> | ||
+ | |||
+ | Banner広告の出し方。 | ||
+ | |||
+ | トップレベルのコンポーネント (app.component.ts) か、Injectable なサービスに以下のコードを追加 | ||
+ | <pre> | ||
+ | import * as Admob from "nativescript-admob"; | ||
+ | import { isIOS } from "tns-core-modules/platform"; | ||
+ | |||
+ | ... | ||
+ | |||
+ | private testing: boolean = true; | ||
+ | private iosBannerId = "ca-app-pub-xxxxxxxxxxxxxxxx/xxxxxxxxxx"; | ||
+ | private androidBannerId = "ca-app-pub-xxxxxxxxxxxxxxxx/xxxxxxxxxx"; | ||
+ | |||
+ | public createBanner() { | ||
+ | Admob.createBanner({ | ||
+ | testing: this.testing, | ||
+ | size: Admob.AD_SIZE.SMART_BANNER, | ||
+ | iosBannerId: this.iosBannerId, | ||
+ | androidBannerId: this.androidBannerId, | ||
+ | iosTestDeviceIds: ["4DC032A6-954E-4AE7-885F-8F32C14C5FAA"], | ||
+ | margins: { | ||
+ | // top: 50 | ||
+ | bottom: 80 | ||
+ | } | ||
+ | }).then(function() { | ||
+ | console.log("admob createBanner done"); | ||
+ | }, function(error) { | ||
+ | console.log("admob createBanner error: " + error); | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | public hideBanner() { | ||
+ | Admob.hideBanner().then(function() { | ||
+ | console.log("admob hideBanner done"); | ||
+ | }, function(error) { | ||
+ | console.log("admob hideBanner error: " + error); | ||
+ | }); | ||
+ | } | ||
+ | </pre> | ||
+ | この createBanner() を呼び出すと広告が表示され、hideBanner() を呼び出すと消える。 | ||
+ | |||
+ | <code>bottom:</code> が広告が表示される位置になる。<code>top:</code> と上からの座標を書く事もできる。 | ||
+ | |||
+ | <pre> | ||
+ | public createInterstitial() { | ||
+ | admob.createInterstitial({ | ||
+ | testing: true, | ||
+ | iosInterstitialId: "ca-app-pub-XXXXXX/YYYYY2", // add your own | ||
+ | androidInterstitialId: "ca-app-pub-AAAAAAAA/BBBBBB2", // add your own | ||
+ | // Android automatically adds the connected device as test device with testing:true, iOS does not | ||
+ | iosTestDeviceIds: ["ce97330130c9047ce0d4430d37d713b2"], | ||
+ | keywords: ["keyword1", "keyword2"], // add keywords for ad targeting | ||
+ | onAdClosed: function () { console.log("interstitial closed") } | ||
+ | }).then( | ||
+ | function() { | ||
+ | console.log("admob createInterstitial done"); | ||
+ | }, | ||
+ | function(error) { | ||
+ | console.log("admob createInterstitial error: " + error); | ||
+ | } | ||
+ | ); | ||
+ | } | ||
+ | </pre> | ||
+ | これを呼び出すと interstitial (区切りの良いところで表示される全面広告) が表示される。 | ||
+ | |||
+ | == Tips == | ||
+ | === スクリーンサイズを取得する === | ||
+ | <pre> | ||
+ | import { screen } from "tns-core-modules/platform/platform"; | ||
+ | ... | ||
+ | some_method() { | ||
+ | console.log(`widthDIPs=${screen.mainScreen.widthDIPs}`); | ||
+ | console.log(`widthPixels=${screen.mainScreen.widthPixels}`); | ||
+ | console.log(`heightDIPs=${screen.mainScreen.heightDIPs}`); | ||
+ | console.log(`heightPixels=${screen.mainScreen.heightPixels}`); | ||
+ | console.log(`scale=${screen.mainScreen.scale}`); | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | === iconを使う === | ||
+ | <pre>html | ||
+ | <Image src="font://" class="fas t-36"> | ||
+ | <Label text="" class="fas t-36"/> | ||
+ | <Label [text]="text" class="fas t-36"/> | ||
+ | </pre> | ||
+ | |||
+ | iconを program から変更するには、3行目のパターン。ただし、text は <nowiki>&#xXXXX;</nowiki> は使えないので、次のように記述する。 | ||
+ | |||
+ | <pre>typescript | ||
+ | text = String.fromCharCode(0xf5a0); | ||
+ | </pre> | ||
+ | |||
+ | icon のコードは https://fontawesome.com/icons?d=gallery で探す。 | ||
+ | |||
+ | == 参考文献 == | ||
+ | * [https://www.nativescript.org/ NativeScript.org] | ||
+ | * [https://www.npmjs.com/package/nativescript-google-maps-sdk NativeScript plugin for the Google Maps SDK] or https://market.nativescript.org/plugins/nativescript-google-maps-sdk | ||
+ | * [https://www.nativescript.org/blog/5-plugins-to-monetize-your-nativescript-app 5 Plugins to Monetize Your NativeScript App] | ||
+ | * [https://r17n.page/2020/02/20/nativescript-icon-and-splash-screen/ NativeScript で アイコン/スプラッシュスクリーン を 生成/設定] | ||
+ | * [http://examination-03.hatenablog.com/ サルでもできるiOSアプリ公開手順~App store 登録~] |
2020年12月9日 (水) 01:41時点における最新版
NativeScript はクロスプラットフォーム (iOS と Android) のアプリケーションを構築するフレームワーク。 HTML, CSS, JavaScript を使用して OS native の API にアクセスする。
公式ドキュメントは https://docs.nativescript.org/ にある。
NativeScript Playground
NativeScript を使い始めるための、ブラウザー上の開発環境。
モバイルデバイスと組み合わせて使う。iOSの場合、
をインストールしておく。
Tutorialで NativeScript の機能を試してみることができる。 モバイルデバイスにインストールした NativeScript Preview で見た目や動作が確認できる。
CLI (コマンドラインインターフェイス)
インストール
Xcode に依存しているので、あらかじめ App Store から Xcode をインストールしておく。
cocoapods, xcodeproj に依存しているので、インストールする。
$ sudo gem install cocoapods xcodeproj
node.js に依存しているので、node.js をインストールする。 Mac の場合は、homebrew を使って、
$ brew install node
でOK。
CLI は npm を使って、
$ npm install --global nativescript
を実行。すると、いろいろ聞いてくるので、適当に答えると、 tns
というコマンドが使えるようになる。
なお、2020/5現在、node のバージョンが新しすぎると警告がたくさん出る。nvm で v13.13.0 にセットして黙らせる。
プロジェクトの作成
新しいプロジェクトの名前を "my-project" として、新規に作成するために、次のコマンドを叩く。
$ tns create my-project
すると、2つの質問に順番に答えていく (カーソルキー上下で選ぶ。)
? First, which style of NativeScript project would you like to use: ❯ Angular | Learn more at https://nativescript.org/angular Vue.js | Learn more at https://nativescript.org/vue Plain TypeScript | Learn more at https://nativescript.org/typescript Plain JavaScript | Use NativeScript without any framework ? Next, which template would you like to start from: Hello World | A Hello World app ❯ SideDrawer | An app with pre-built pages that uses a drawer for navigation Tabs | An app with pre-built pages that uses tabs for navigation
ここでは、Angular と SideDrawer を選んでみた。 すると、カレントディレクトリに my-project というディレクトリができて、その中に開発環境が作られる。
この辺りのドキュメントを読みながらアプリを作成する。
Preview
プロジェクトディレクトリに移動して、開発する。
$ cd my-project
Angular を選んだので、src/app
のしたに app.component.ts, app.module.ts などのソースコードが展開されている。
これらのファイルをエディットしてアプリを作っていく。
試したくなったら (というか、何も変更しなくても最初からサンプルアプリになっているので)、preview コマンドを叩く。
$ tns preview
すると、QRコードが画面表示されるので、モバイルデバイスにインストールした NativeScript Playground でスキャンする。 しばらくコンパイルに時間がかかったあと、モバイルデバイスが画面遷移して NativeScript Preview 上でアプリが実行される。
これで一応はテストができる。
Simulatorでのテスト
xcode のデバイスシミュレーターでテストする時は、
$ tns run ios
と叩く。
特定のデバイスで実行したいなら、
$ instruments -s devices
を実行すると、Simulator上の様々な種類のデバイスの device id のリストが表示されるので、
$ tns run ios --device <device id>
と叩く。
あとで説明する Developer provisioning profile を作り、そこにリアルデバイス (iPhone, iPad) の device id を登録しておくと、実機でのテストもできる。
同じ instruments
コマンドで Mac につながっている実機の device id もわかる。
App Store に載せるまで
https://docs.nativescript.org/tooling/publishing/publishing-ios-apps を参考にやってみる。
まず Apple の Developer Member になる必要がある。https://developer.apple.com/membercenter で登録する。 年間11,800円かかる。
Bundle ID
Bundle ID を決める。Bundle ID は reverse domain name notation に従う。
例えば、com.fukudat.<application-name>
のようなもの。
これを、package.json
ファイルの "nativescript/id" の値に書き込む。
App name
アプリケーションの表示名を決める。アプリケーションアイコンのしたに表示される。
App_Resources/iOS/Info.plist
ファイルの CFBundleDisplayName
key の値として設定する。
App icons
標準の名前でよければ、App_Resoures/iOS
のしたにあるicon.png
, icon@2x.png
, icon@3x.png
を書き換える。
ファイル名を変えたい時は、App_Resources/iOS/Info.plist
を以下のように書き換える。
... <key>CFBundleIconFiles</key> <array> <string>Icon@2x.png</string> <string>Icon.png</string> <string>Icon-Small@3x.png</string> <string>Icon-Small@2x.png</string> <string>Icon-Small.png</string> <string>Icon-Small-50@2x.png</string> <!-- etc --> </array> ...
これをやってくれる便利なコマンドがあることが判明。まずは画像を images/icon.png に用意して、
$ tns resources generate icons images/icon.png Generating icons ... Icons generation completed.
すると以下のファイルが生成される。
- app/App_Resources/Android/src/main/res/drawable-hdpi/icon.png
- app/App_Resources/Android/src/main/res/drawable-ldpi/icon.png
- app/App_Resources/Android/src/main/res/drawable-mdpi/icon.png
- app/App_Resources/Android/src/main/res/drawable-xhdpi/icon.png
- app/App_Resources/Android/src/main/res/drawable-xxhdpi/icon.png
- app/App_Resources/Android/src/main/res/drawable-xxxhdpi/icon.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png
- app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png
Splash screen
起動時に表示されるスクリーン。カッコよく作るとアプリの印象が良い。
App_Resoures/iOS/Assets.xcassets/LaunchScreen.Center.imageset
のしたにある png ファイルをサイズをそのままに書き換える。
実はこれもコマンドで生成できる。
$ tns resources generate splashes images/icon_transparent.png --background "#123456"
ここで、--background
の引数は背景色 (default = #FFFFFF (白))。
以下のファイルが生成される。
- app/App_Resources/Android/src/main/res/drawable-hdpi/background.png
- app/App_Resources/Android/src/main/res/drawable-hdpi/logo.png
- app/App_Resources/Android/src/main/res/drawable-ldpi/background.png
- app/App_Resources/Android/src/main/res/drawable-ldpi/logo.png
- app/App_Resources/Android/src/main/res/drawable-mdpi/background.png
- app/App_Resources/Android/src/main/res/drawable-mdpi/logo.png
- app/App_Resources/Android/src/main/res/drawable-xhdpi/background.png
- app/App_Resources/Android/src/main/res/drawable-xhdpi/logo.png
- app/App_Resources/Android/src/main/res/drawable-xxhdpi/background.png
- app/App_Resources/Android/src/main/res/drawable-xxhdpi/logo.png
- app/App_Resources/Android/src/main/res/drawable-xxxhdpi/background.png
- app/App_Resources/Android/src/main/res/drawable-xxxhdpi/logo.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-1125h.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-X.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-XR.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-XS-Max.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait-XR.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait-XS-Max.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png
- app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png
- app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png
- app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png
- app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@3x.png
- app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png
- app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png
- app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@3x.png
素晴らしい。
Development certificates
Development certificate は iOS app を開発者が誰かわかるようにサインするために用いられる。
https://developer.apple.com/account/resources/certificates/list を開いて '+' ボタンをクリック。指示に従って 'iOS App Development' certificate を作成する。 ダウンロードした certificate file をダブルクリックすると、keychain に格納される。
Distribution certificate
Distribution certificate は iTune Connect への申請が誰のものか分かるように、application binary (IPA file) にサインするために用いられる。
https://developer.apple.com/account/resources/certificates/list を開いて '+' ボタンをクリック。指示に従って 'iOS Distribution' certificate を作成する。 ダウンロードした certificate file をダブルクリックすると、keychain に格納される。
Identifiers - App ID
アプリケーションをデバイス上でテストしたり、App Store に申請するには、App ID が必要となる。
App ID は Apple が生成した prefix (Team IDとも呼ばれる) と、自分で決めた Bundle ID とマッチする文字列との組み合わせからなる。
例えば、com.fukudat.*
を App ID に選ぶと、com.fukudat.
で始まる全ての Bundle ID のアプリケーションとマッチする。
この App ID はあとで provisioning profiles で使用する。
Device
テストで使うデバイスは、https://developer.apple.com/account/resources/devices/list で登録しておく必要がある。
デバイスが接続されている Mac で、
$ instruments -s devices
と叩くと、device の UDID が表示されるので、それを使って登録する。
Development provisioning profile
Development provisioning profile は開発者 (の development certificate) と、App ID と device ID を関連づける。
https://developer.apple.com/account/resources/profiles/list を開いて、'+' ボタンをクリックし、'Development/iOS App Development' を選び、指示に従って新しい development provisioning profile を作成する。 これは、app store への申請には必要ないが、実デバイスでのテストに必要となる。
Distribution provisioning profile
Distribution provisioning profile には複数の種類がある。App Store での申請に必要な種類は 'App Store Distribution Provisioning Profile' である。 Development provisioning profile と同様に、distribution certificate, App ID を関連付ける。
https://developer.apple.com/account/resources/profiles/list を開いて '+' ボタンをクリックし、'Distribution/App Store' を選び、指示に従って新しい distribution provisioning profile を作成する。
App Store Connect
https://appstoreconnect.apple.com/ を開いて、'My App' をクリック。'+'ボタンを押して新規Appをクリック。
ウィンドウがポップアップしてくるので、
- プラットフォーム = iOS
- 名前 = 好きな名前を30文字以内で
- プライマリ言語 = 日本語とか英語とか
- バンドルID = 上記 Bundle ID の項目で作った ID。選択できる。
- SKU = 重複しない名前をつける。Bundle ID と同じような reverse domain notation でも良い。
- ユーザアクセス = 制限ありかなしか
を入力して、作成をクリック。
さらにApp情報と価格を決めて入力し、保存を押す。
Build & Upload
アプリの情報を https://appstoreconnect.apple.com に登録したら、アプリケーションをビルドする。
Bundle Short Version String と Bundle Version String を設定する。
- Bundle Short Version String は外部に公開するバージョン '2.1' のような番号で、リリースごとに数字を大きくする。
- Bundle Version String は内部的なバージョン番号で、公開バージョンの下に存在する複数のリリース候補を区別するために用いる。例えば '2.1.1', '2.1.2' など。
iTune Connect は同じバージョンで2回アップロードすることはできないので、必ず Bundle Version String を毎回更新する必要がある。
Bundle Short Version String はアプリがアップロードされて、承認申請に送られて、承認されたら更新する。
どちらの値も、App_Resources/iOS/Info.plist
に書き込む。
CFBundleShortVersionString
key に Bundle Short Version String を格納しCFBundleVersion
key に Bundle Version String を格納する。
xcode のビルドツールが apple id にアクセスする。2ファクタ認証が設定されている場合、application specific password を設定しておく必要がある。
https://appleid.apple.com/account/manage にアクセスして、tns 用のパスワードを生成する。xxxx-xxxx-xxxx-xxxx
のようなパスワードが手に入る。
いよいよビルドする。
$ tns publish ios --appleApplicationSpecificPassword xxxx-xxxx-xxxx-xxxx
と叩く。
これでうまくいくはずなのだが、現在の tns のバージョン (6.5.0) だと、
error: exportArchive: Provisioning profile "<distribution-provisioning-profile-name>" doesn't include signing certificate "Apple Distribution: <YOUR NAME> (<TEAM-ID>)".
(profileにcertificateが含まれていない)というエラーが出て、アプリの提出に失敗してしまう。しかし確かに profile には certificate が含まれている。
いろいろ試したが、次のようにやったらうまくいった。
App_Resources/iOS/build.xcconfig に以下の2行を追加。
PROVISIONING_PROFILE = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx; PROVISIONING_PROFILE_SPECIFIER = <distribution-profile-name>;
$ tns publish ios --provision xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --appleApplicationSpecificPassword xxxx-xxxx-xxxx-xxxx
ただし、--provision
の引数に与えたのは distribution provisioning profile の UUIDで、ダウンロードした profile の中に埋まっている。
うまくいくと、
1 packages were uploaded successfully: /tmp/itms-xxxxxx-xxxxx-xxxxxxx.xxxx/mybundle.itmsp [YYYY-MM-DD HH:mm:ss JST] <main> DBG-X: Returning 0
てなメッセージが出る。
https://appstoreconnect.apple.com/ に戻り、My App から提出準備中のアプリを開いて、提出したビルドが現れるのを待つ。しばらく(数分)時間がかかる。
あとは、必要な情報を埋めて、右上の提出ボタンを押したら完了。初回の審査には1-2週間かかるらしい。
入力を迷った項目:
- 暗号を使うか? = REST API を https で呼んでいるので、yes。ただし、https のみを使用にチェック。
- IDFAを使うか? = 広告を表示するので (自分は使わないが) 広告配信サービスが使うだろうから yes。
Plugin
Geolocation Plugin
インストール
$ tns plugin add nativescript-geolocation
使い方
https://github.com/NativeScript/nativescript-geolocation 参照
NativeScript Plugin for Google Maps
インストール
$ tns plugin add nativescript-google-maps-sdk
使い方
詳細は https://www.npmjs.com/package/nativescript-google-maps-sdk を参照。
app.module.ts
に以下のコードを追加:
import * as platform from "platform"; declare var GMSServices: any; .... if (platform.isIOS) { GMSServices.provideAPIKey("PUT_API_KEY_HERE"); }
地図を使うコンポーネント (例: map.component.*
) に以下のようなコードを埋める。
map.component.html <GridLayout> <MapView [latitude]="latitude" [longitude]="longitude" [zoom]="zoom" [bearing]="bearing" [tilt]="tilt" [mapAnimationsEnabled]="mapAnimationsEnabled" [padding]="padding" (mapReady)="onMapReady($event)" (markerSelect)="onMarkerSelect($event)" (markerBeginDragging)="onMarkerBeginDragging()" (markerEndDragging)="onMarkerEndDragging()" (markerDrag)="onMarkerDrag()" (cameraChanged)="onCameraChanged()" (cameraMove)="onCameraMove()"></MapView> </GridLayout>
map.component.ts import { MapView, Marker, Position, Polyline } from "nativescript-google-maps-sdk"; ... export class MapComonent implements OnInit { private mapView: MapView; onMapRead(event): void { this.mapView = event.object; ... } onMarkerSelect(event): void { const marker = event.marker; const userData = marker.userData; ... } }
NativeScript Plugin for Google Admob
Google Admob はモバイルアプリむけの広告配信サービス。 狭いスマホの画面で広告は邪魔だが、on/off をコントロールできたら、使える事もある (かも)。
NativeScript AdMob plugin はこれを実現してくれる。
Install
$ tns plugin add nativescript-admob
使い方
NativeScript 4.0 以降はApp_Resources/iOS/Info.plist
にこれが必要。
<key>GADApplicationIdentifier</key> <string>ca-app-pub-9517346003011652~2508636525</string>
さらに、次のコマンドを叩いておく。
$ pod repo update
Banner広告の出し方。
トップレベルのコンポーネント (app.component.ts) か、Injectable なサービスに以下のコードを追加
import * as Admob from "nativescript-admob"; import { isIOS } from "tns-core-modules/platform"; ... private testing: boolean = true; private iosBannerId = "ca-app-pub-xxxxxxxxxxxxxxxx/xxxxxxxxxx"; private androidBannerId = "ca-app-pub-xxxxxxxxxxxxxxxx/xxxxxxxxxx"; public createBanner() { Admob.createBanner({ testing: this.testing, size: Admob.AD_SIZE.SMART_BANNER, iosBannerId: this.iosBannerId, androidBannerId: this.androidBannerId, iosTestDeviceIds: ["4DC032A6-954E-4AE7-885F-8F32C14C5FAA"], margins: { // top: 50 bottom: 80 } }).then(function() { console.log("admob createBanner done"); }, function(error) { console.log("admob createBanner error: " + error); }); } public hideBanner() { Admob.hideBanner().then(function() { console.log("admob hideBanner done"); }, function(error) { console.log("admob hideBanner error: " + error); }); }
この createBanner() を呼び出すと広告が表示され、hideBanner() を呼び出すと消える。
bottom:
が広告が表示される位置になる。top:
と上からの座標を書く事もできる。
public createInterstitial() { admob.createInterstitial({ testing: true, iosInterstitialId: "ca-app-pub-XXXXXX/YYYYY2", // add your own androidInterstitialId: "ca-app-pub-AAAAAAAA/BBBBBB2", // add your own // Android automatically adds the connected device as test device with testing:true, iOS does not iosTestDeviceIds: ["ce97330130c9047ce0d4430d37d713b2"], keywords: ["keyword1", "keyword2"], // add keywords for ad targeting onAdClosed: function () { console.log("interstitial closed") } }).then( function() { console.log("admob createInterstitial done"); }, function(error) { console.log("admob createInterstitial error: " + error); } ); }
これを呼び出すと interstitial (区切りの良いところで表示される全面広告) が表示される。
Tips
スクリーンサイズを取得する
import { screen } from "tns-core-modules/platform/platform"; ... some_method() { console.log(`widthDIPs=${screen.mainScreen.widthDIPs}`); console.log(`widthPixels=${screen.mainScreen.widthPixels}`); console.log(`heightDIPs=${screen.mainScreen.heightDIPs}`); console.log(`heightPixels=${screen.mainScreen.heightPixels}`); console.log(`scale=${screen.mainScreen.scale}`); }
iconを使う
html <Image src="font://" class="fas t-36"> <Label text="" class="fas t-36"/> <Label [text]="text" class="fas t-36"/>
iconを program から変更するには、3行目のパターン。ただし、text は &#xXXXX; は使えないので、次のように記述する。
typescript text = String.fromCharCode(0xf5a0);
icon のコードは https://fontawesome.com/icons?d=gallery で探す。