差分

提供: fukudat.net
ナビゲーションに移動検索に移動
21,404 バイト追加 、 2020年12月9日 (水) 01:41
NativeScript はkクロスプラットフォーム はクロスプラットフォーム (iOS と Android) のアプリケーションを構築するフレームワーク。
HTML, CSS, JavaScript を使用して OS native の API にアクセスする。[[Category:How-To]]
インストール方法を含めて、ドキュメントは 公式ドキュメントは https://docs.nativescript.org/ にある。
== [https://play.nativescript.org/ NativeScript Playground] ==
== CLI (コマンドラインインターフェイス) ==
=== インストール ===
Xcode に依存しているので、あらかじめ App Store から Xcode をインストールしておく。
 
cocoapods, xcodeproj に依存しているので、インストールする。
<pre>
$ sudo gem install cocoapods xcodeproj
</pre>
 
node.js に依存しているので、node.js をインストールする。
Mac の場合は、[[homebrew]] を使って、
ここでは、Angular と SideDrawer を選んでみた。
すると、カレントディレクトリに my-project というディレクトリができて、その中に開発環境が作られる。
 
[https://docs.nativescript.org/ui/overview この辺り]のドキュメントを読みながらアプリを作成する。
=== Preview ===
これで一応はテストができる。
 
=== Simulatorでのテスト ===
xcode のデバイスシミュレーターでテストする時は、
<pre>
$ tns run ios
</pre>
と叩く。
 
特定のデバイスで実行したいなら、
<pre>
$ instruments -s devices
</pre>
を実行すると、Simulator上の様々な種類のデバイスの device id のリストが表示されるので、
<pre>
$ tns run ios --device <device id>
</pre>
と叩く。
 
[[#Development provisioning profile|あとで]]説明する Developer provisioning profile を作り、そこにリアルデバイス (iPhone, iPad) の device id を登録しておくと、実機でのテストもできる。
同じ <code>instruments</code> コマンドで 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 に従う。
例えば、<code>com.fukudat.<application-name></code>のようなもの。
 
これを、<code>package.json</code> ファイルの "nativescript/id" の値に書き込む。
 
=== App name ===
アプリケーションの表示名を決める。アプリケーションアイコンのしたに表示される。
 
<code>App_Resources/iOS/Info.plist</code>ファイルの <code>CFBundleDisplayName</code> key の値として設定する。
 
=== App icons ===
標準の名前でよければ、<code>App_Resoures/iOS</code> のしたにある<code>icon.png</code>, <code>icon@2x.png</code>, <code>icon@3x.png</code>を書き換える。
ファイル名を変えたい時は、<code>App_Resources/iOS/Info.plist</code>を以下のように書き換える。
<pre>
...
<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>
...
</pre>
 
これをやってくれる便利なコマンドがあることが判明。まずは画像を images/icon.png に用意して、
<pre>
$ tns resources generate icons images/icon.png
Generating icons ...
Icons generation completed.
</pre>
すると以下のファイルが生成される。
* 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 ===
起動時に表示されるスクリーン。カッコよく作るとアプリの印象が良い。
<code>App_Resoures/iOS/Assets.xcassets/LaunchScreen.Center.imageset</code> のしたにある png ファイルをサイズをそのままに書き換える。
 
実はこれもコマンドで生成できる。
<pre>
$ tns resources generate splashes images/icon_transparent.png --background "#123456"
</pre>
ここで、<code>--background</code>の引数は背景色 (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 とマッチする文字列との組み合わせからなる。
例えば、<code>com.fukudat.*</code> を App ID に選ぶと、<code>com.fukudat.</code> で始まる全ての Bundle ID のアプリケーションとマッチする。
 
この App ID はあとで provisioning profiles で使用する。
 
=== Device ===
テストで使うデバイスは、https://developer.apple.com/account/resources/devices/list で登録しておく必要がある。
 
デバイスが接続されている Mac で、
<pre>
$ instruments -s devices
</pre>
と叩くと、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 はアプリがアップロードされて、承認申請に送られて、承認されたら更新する。
 
どちらの値も、<code>App_Resources/iOS/Info.plist</code> に書き込む。
* <code>CFBundleShortVersionString</code> key に Bundle Short Version String を格納し
* <code>CFBundleVersion</code> key に Bundle Version String を格納する。
 
xcode のビルドツールが apple id にアクセスする。2ファクタ認証が設定されている場合、application specific password を設定しておく必要がある。
https://appleid.apple.com/account/manage にアクセスして、tns 用のパスワードを生成する。<code>xxxx-xxxx-xxxx-xxxx</code> のようなパスワードが手に入る。
 
いよいよビルドする。
<pre>
$ tns publish ios --appleApplicationSpecificPassword xxxx-xxxx-xxxx-xxxx
</pre>
と叩く。
 
これでうまくいくはずなのだが、現在の tns のバージョン (6.5.0) だと、
<pre>
error: exportArchive: Provisioning profile "<distribution-provisioning-profile-name>" doesn't include signing certificate "Apple Distribution: <YOUR NAME> (<TEAM-ID>)".
</pre>
(profileにcertificateが含まれていない)というエラーが出て、アプリの提出に失敗してしまう。しかし確かに profile には certificate が含まれている。
 
いろいろ試したが、次のようにやったらうまくいった。
 
App_Resources/iOS/build.xcconfig に以下の2行を追加。
<pre>
PROVISIONING_PROFILE = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx;
PROVISIONING_PROFILE_SPECIFIER = <distribution-profile-name>;
</pre>
<pre>
$ tns publish ios --provision xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --appleApplicationSpecificPassword xxxx-xxxx-xxxx-xxxx
</pre>
ただし、<code>--provision</code> の引数に与えたのは distribution provisioning profile の UUIDで、ダウンロードした profile の中に埋まっている。
 
うまくいくと、
<pre>
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
</pre>
てなメッセージが出る。
 
https://appstoreconnect.apple.com/ に戻り、My App から提出準備中のアプリを開いて、提出したビルドが現れるのを待つ。しばらく(数分)時間がかかる。
 
あとは、必要な情報を埋めて、右上の提出ボタンを押したら完了。初回の審査には1-2週間かかるらしい。
 
入力を迷った項目:
* 暗号を使うか? = REST API を https で呼んでいるので、yes。ただし、https のみを使用にチェック。
* 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://&#xf5a0;" class="fas t-36">
<Label text="&#xf5a0;" 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 登録~]

案内メニュー