cordova8 で plugin addエラー 最低限のpackage.jsonが必要
cordova7まではpluginのpackage.jsonなしでもプラグインの追加を行えた。cordova8からはpackage.jsonの中も見てるようで最低限のpackage.jsonが必要になったぽい。
package.json
{ "name": "my_plugin", "version": "0.0.1", "description": "" }
試したらnameとversionとdescriptionだけあればokだった。メンテされてないプラグインはどうすればいいのだろう。いちおうエラー内容もメモしておく
package.jsonなしの場合
$ ionic cordova plugin add /path/to/cordova-plugin-my-plugin/ > cordova plugin add /path/to/cordova-plugin-my-plugin/ --save (node:20136) UnhandledPromiseRejectionWarning: CordovaError: Invalid Plugin! /path/to/cordova-plugin-my-plugin needs a valid package.json at /Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/cordova-lib/src/plugman/fetch.js:92:41 at _fulfilled (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/q/q.js:787:54) at self.promiseDispatch.done (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/q/q.js:816:30) at Promise.promise.promiseDispatch (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/q/q.js:749:13) at /Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/q/q.js:509:49 at flush (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/q/q.js:108:17) at _combinedTickCallback (internal/process/next_tick.js:131:7) at process._tickCallback (internal/process/next_tick.js:180:9) at Function.Module.runMain (module.js:695:11) at startup (bootstrap_node.js:191:16) (node:20136) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejec\ tion id: 1) (node:20136) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
package.jsonに不備の場合
$ ionic cordova plugin add /path/to/cordova-plugin-my-plugin/ > cordova plugin add /path/to/cordova-plugin-my-plugin/ --save (node:20157) UnhandledPromiseRejectionWarning: CordovaError: Error: npm: Command failed with exit code 1 Error output: npm ERR! code EINVALIDTYPE npm ERR! typeerror Error: Argument #2: Expected string but got null npm ERR! typeerror at exports.findRequirement (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/npm/lib/install/deps.js:721:3) npm ERR! typeerror at findChild (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/npm/lib/install/deps.js:109:17) npm ERR! typeerror at computeMetadata (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/npm/lib/install/deps.js:119:9) npm ERR! typeerror at Installer.normalizeCurrentTree (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/npm/lib/install.js:408:3) npm ERR! typeerror at Array.<anonymous> (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/npm/node_modules/slide/lib/bind-actor.js:15:8) npm ERR! typeerror at LOOP (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/npm/node_modules/slide/lib/chain.js:15:14) npm ERR! typeerror at /Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/npm/node_modules/slide/lib/chain.js:18:7 npm ERR! typeerror at iferr (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/npm/lib/install.js:362:5) npm ERR! typeerror at a (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/npm/node_modules/iferr/iferr.js:3:64) npm ERR! typeerror at cb (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/npm/node_modules/slide/lib/async-map.js:47:24) npm ERR! typeerror at /Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/npm/node_modules/call-limit/call-limit.js:22:12 npm ERR! typeerror at _combinedTickCallback (internal/process/next_tick.js:131:7) npm ERR! typeerror at process._tickCallback (internal/process/next_tick.js:180:9) npm ERR! typeerror This is an error with npm itself. Please report this error at: npm ERR! typeerror <https://npm.community> npm ERR! A complete log of this run can be found in: npm ERR! /Users/hogehoge/.npm/_logs/2018-08-16T06_30_08_468Z-debug.log at /Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/cordova-lib/src/plugman/fetch.js:112:45 at _rejected (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/q/q.js:864:24) at /Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/q/q.js:890:30 at Promise.when (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/q/q.js:1142:31) at Promise.promise.promiseDispatch (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/q/q.js:808:41) at /Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/q/q.js:624:44 at runSingle (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/q/q.js:137:13) at flush (/Users/hogehoge/.nodebrew/node/v8.11.3/lib/node_modules/cordova/node_modules/q/q.js:125:13) at _combinedTickCallback (internal/process/next_tick.js:131:7) at process._tickCallback (internal/process/next_tick.js:180:9) (node:20157) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejec\ tion id: 1) (node:20157) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
以上です
【ionic3】iOSでvideoインライン再生
ionic3でvideoタグのインライン再生しようとしたら上手くいかなかったのでそのときのメモ
HTMLはこんな感じ
<video muted="true" preload="auto" webkit-playsinline playsinline controls src="assets/imgs/sample.mp4"> </video>
調べてみると wkwebview の設定で allowsInlineMediaPlayback という設定があった。
CDVWKWebViewEngine.m を見てると allowsInlineMediaPlayback を設定している箇所もあった。
config.xml
<preference name="AllowInlineMediaPlayback" value="true" />
これだけでした。以上です
【Ionic3(Angular)】Componentを作成してHTMLを分割する方法まとめておく
はじめに
今回やりたかったことは以下のようなコードの「リスト」の部分が複雑になったので別ファイルに分けたいということでした。AngularのComponentを作成すれば実現できるようでIonicコマンドでComponentを作成できるのでこちらの使い方をメモしておく。
<ion-content> <!-- タイトル --> <div>Title</div> <!-- リスト --> <ion-list> <ion-item>Item1</ion-item> <ion-item>Item2</ion-item> ・・・ </ion-list> </ion-content>
やりたいことは以下
・ファイルを分割したい
・ionicのコンポーネントを使いたい
・呼びだし側と呼ばれる側とで値を共有したい
実装
Componentを作成
$ ionic g component mylist
src/componentsディレクトリが作成されてひな形が作成される
components.module.ts
import { NgModule } from '@angular/core'; import { MyListComponent } from './my-list/my-list'; @NgModule({ declarations: [MyListComponent], imports: [], exports: [MyListComponent] }) export class ComponentsModule {}
さらに src/components/my-list ディレクトリも作成されて html、scss、tsファイルのひな形が作成される。これをアプリから呼びだすことができるようにapp/app.module.tsに以下を追記
app.module.ts
・・・ import { ComponentsModule } from '../components/components.module' // ★追記 ・・・ @NgModule({ ・・・ imports: [ BrowserModule, IonicModule.forRoot(MyApp), ComponentsModule, // ★追記 ] })
これで追加したmy-listコンポーネントを以下の形でよびだせるようになる。
<ion-content> <!-- タイトル --> <div>Title</div> <!-- リスト --> <my-list></my-list> </ion-content>
Ionicコンポーネントを呼びだせるようにする
続いてmy-listコンポーネント実装していく。ionicのコンポーネント(ion-list)を使いたいのでcomponents.module.tsにIonicModuleを追記
・・・ import { IonicModule } from 'ionic-angular' // ★追記 ・・・ @NgModule({ declarations: [MyListComponent], imports: [IonicModule], exports: [MyListComponent] })
components/my-list/my-list.html
<ion-list> <ion-item>Item1</ion-item> <ion-item>Item2</ion-item> ・・・ </ion-list>
呼び出し側と呼ばれる側とで値を共有する
値の共有の例として以下を実装する
・ion-listに表示する値をコンポーネントに渡す
・ion-listでクリックされた行を親に渡す
AngularのngIf、ngForを使えるようにする
追加したComponentでAngularのngIfやngForを使いたい場合はこれらも使えるようにBrowserModuleを追加する必要がある。
components/components.module.ts
import { BrowserModule } from '@angular/platform-browser'; ・・・ @NgModule({ ・・・ imports: [BrowserModule, IonicModule], ・・・ })
コンポーネントに値を渡す(コンポーネントが値を受け取る)
受け取る側
components/my-list/my-list.ts
import { Component, Input } from '@angular/core'; ・・・ export class MyListComponent { @Input() items: any }
component/my-list/my-list.html
<ion-list> <ion-item *ngFor="let item of items">{{ item.name }}</ion-item> </ion-list>
渡す側
xxx.ts
export class Hoge { items: any = [ { id: 1, name: "Item1"}, { id: 2, name: "Item2"}, ・・・ ] }
html
<ion-content> <!-- タイトル --> <div>Title</div> <!-- リスト --> <my-list [items]="items"></my-list> </ion-content>
コンポーネントから値を受け取る
渡す側
components/my-list/my-list.ts
import { Component, Output } from '@angular/core'; ・・・ export class MyListComponent { @Output() selected = new EventEmitter<number>() ・・・ select = (id: number) => { this.selected.emit(id) } }
component/my-list/my-list.html
<ion-list> <ion-item *ngFor="let item of items" (click)="select(item.id)">{{ item.name }}</ion-item> </ion-list>
受け取る側
xxx.ts
export class Hoge { select = (id) => { console.log(id) } }
html
<ion-content> <!-- タイトル --> <div>Title</div> <!-- リスト --> <my-list (selected)="select($event)"></my-list> </ion-content>
ずらずら書いたけど以上です。
Ionic3とAngularのバージョン確認
IonicはCLIとフレームワークとでそれぞれバージョン違うし。Angularはバージョンどんどん上がってる印象なので。自分がそれぞれどのバージョン使ってるかわからなくなってきた。
CLIのバージョン
$ ionic -v 3.20.0
FWのバージョンはpackage.jsonを見るとわかる
{ ・・・ "dependencies": { "@angular/animations": "5.2.11", "@angular/common": "5.2.11", "@angular/compiler": "5.2.11", "@angular/compiler-cli": "5.2.11", "@angular/core": "5.2.11", "@angular/forms": "5.2.11", "@angular/http": "5.2.11", "@angular/platform-browser": "5.2.11", "@angular/platform-browser-dynamic": "5.2.11", ・・・ "ionic-angular": "3.9.2", ・・・ }, ・・・ }
Angularが5.2.11で、Ionicが3.9.2だった。以上です
CircleCI2、Fastaneでの2段階認証が設定されたアップルIDでのアプリアップロードを諦めた話
fastlaneのドキュメントに2段階認証のことものってた
https://docs.fastlane.tools/best-practices/continuous-integration/
環境変数 FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD に2段階認証の場合はAPPパスワードを発行してセットするように書いてあったのだがやってみてもうまくいかず。。
deliverでiTtunesConnectにアップロードしようとするところで、こんなエラーで落ちる。ソース追う気力もないけど2段階認証のところでなんかやろうとして落ちてる感じだ。
/Library/Ruby/Gems/2.0.0/gems/highline-1.7.10/lib/highline/question.rb:413:in `remove_whitespace': [!] undefined method `strip' for nil:NilClass (NoMethodError) from /Library/Ruby/Gems/2.0.0/gems/highline-1.7.10/lib/highline.rb:873:in `get_line' from /Library/Ruby/Gems/2.0.0/gems/highline-1.7.10/lib/highline.rb:891:in `get_response' from /Library/Ruby/Gems/2.0.0/gems/highline-1.7.10/lib/highline.rb:264:in `ask' from /Library/Ruby/Gems/2.0.0/gems/highline-1.7.10/lib/highline.rb:365:in `choose' from /Library/Ruby/Gems/2.0.0/gems/fastlane-2.61.0/spaceship/lib/spaceship/two_step_client.rb:35:in `handle_two_step' from /Library/Ruby/Gems/2.0.0/gems/fastlane-2.61.0/spaceship/lib/spaceship/client.rb:473:in `send_shared_login_request' from /Library/Ruby/Gems/2.0.0/gems/fastlane-2.61.0/spaceship/lib/spaceship/tunes/tunes_client.rb:111:in `send_login_request' (省略) from /usr/local/bin/fastlane:23:in `load' from /usr/local/bin/fastlane:23:in `<main>'
ドキュメントの冒頭に以下の記述があった
The easiest way to get fastlane running on a CI system is to create a separate Apple ID that doesn't have 2-factor auth enabled, with a long, randomly generated password. Additionally make sure the newly created Apple account has limited\ access to only the apps and resources it needs.
「2段階認証を無効にしたApple IDを別途作成して、必要な権限を与えて使ってください」とのことでした。説明見てるとできそうだけど、時間かけてもあまり意味もないと思うので今回は諦めました。以上です
ionic(cordova) CircleCI2とFastlaneでiOSアプリをデプロイゲートにアップロードする手順まとめ
はじめに
今回やりたかったことは
・ionicで開発したiOSアプリをCircleCI2上でAdHoc版ビルド
・ビルドしたアプリをデプロイゲートへアップロード
・Fastlane Matchは使わず手元にある証明書とプロビジョニングプロファイルで行う
ビルドとアップロードはFastlaneというツールを使う
必要なもの
・証明書
キーチェーンアクセスから書き出す「iPhone Distribution:xxxxxxxxxxx(xxxxxx)」いつものp12ファイル。
・プロビジョニングプロファイル
・デプロイゲートのAPIキーとアカウント名
流れ
CircleCI上で証明書等を予め登録しておく
・証明書とプロビジョニングプロファイルをCircleCI上に暗号化して登録(環境変数を利用)
・デプロイゲートのアカウントとAPIキーもCircleCI上に登録(環境変数を利用)
https://circleci.com/gh/[githubアカウント]/[リポジトリ名]/edit#env-vars
↑ここから登録できる
以下を用意
・.circleci/config.yml
・fastlane/Fastfile
イメージとしては普段macでおこなっている作業をCircleCI上のmacで行うだけ。
・cordova、ionic と依存するnode_modulesのインストール
・予め登録した証明書とプロビジョニングプロファイルを復号化してマシンにインストール
・インストールした証明書等を使ってアプリをビルド
・予め登録したデプロイゲートの情報を使って、デプロイゲートへアップロード
ハマったこと
証明書とプロビジョニングプロファイルを正しく指定してるのにSigning Errorが消えない
エラー
Code Signing Error: Signing for "circleci_demo" requires a development team. Select a development team in the project editor. Code Signing Error: Code signing is required for product type 'Application' in SDK 'iOS 11.2'
xcodeでいうところの「Automatically manage signing」がONになっている状態だとエラーになってしまっていた。
ONが奨励されてる?のかわからないけど今回はこれをOFFにすることで解決した。
後述するFastlane の disable_automatic_code_signing メソッドを使うとOFFになる。
cordova-iosが生成するxcodeの project.pbxproj ファイルの形式が不完全
エラー
Seems to be a very old project file format - please open your project file in a more recent version of Xcode
TargetAttributes属性がないとFastlaneがこのエラーで終了してしまう。
Cordovaで生成した直後のプロジェクトだとこの属性がないらしい(最新のcordova-iosでは改善してるかも)
で、platforms/ios/circleci_demo.xcodeproj/project.pbxproj もgitで管理してビルドする前にこのファイルを使うことで解決することにした。
アーカイブに成功してエクスポートでエラー
エラー
Exit status: 70 No provisioning profile provided Make sure to pass a valid provisioning for each required target Check out the docs on how to fix this: https://github.com/fastlane/fastlane/tree/master/gym#export-options
よくわかってないのだが、xcodebuildでのアーカイブで出力されるplistをエクスポートの際に使用するようなのだが、それが正しくないらしい。スタックオーバーフローとか見てると、xcode上でエクスポートする際に作られるExportOptions.plistを使うと良いらしい。これもGitで管理するようにしてFastfileで指定することで解決した。gymのexport_optionsで指定可能でした。
実装
証明書とプロビジョニングプロファイルをCircleCI2に登録
$ base64 -i xxxxx.p12 | pbcopy $ base64 -i xxxxx. mobileprovision | pbcopy
こちらのページに細かく書かれている(というかまんま)
http://developabout0309.blogspot.com/2018/05/circleci20fastlanefabric_1.html
今回は以下の変数名で登録した
CERTIFICATES : pm12ファイル
PROVISIONING_PROFILES : プロビジョニングプロファイル
DEPLOYGATE_USER : デプロイゲートのアカウント
DEPLOYGATE_API_KEY : デプロイゲートのAPIキー
.circleci/config.yml
version: 2 jobs: build: macos: xcode: "9.2.0" shell: /bin/bash --login working_directory: ~/workspace steps: - checkout - run: name: install ionic command: | # Ionicインストール npm install -g cordova@6.5.0 npm install -g ionic@2.2.3 npm install # 最新のcordova-iosでプロジェクト作成 ionic platform rm ios ionic platform add ios@4.5.4 ionic prepare - run: name: build and upload deploygate command: | # stagingブランチの場合、デプロイゲートへアップロード if [ "${CIRCLE_BRANCH}" == "staging" ]; then # 証明書をデコード base64 -D -o circleci_demo.p12 <<< $CERTIFICATES # プロビジョニングプロファイルのインストール mkdir -pv ~/Library/MobileDevice/Provisioning\ Profiles/ base64 -D -o ~/Library/MobileDevice/Provisioning\ Profiles/CircleCI_Adhoc.mobileprovision <<< $PROVISIONING_PROFILES # xcodeprojファイルをチェックアウト git checkout platforms/ios/circleci_demo.xcodeproj/project.pbxproj # AdHocビルド fastlane ios build # デプロイゲートへアップロード fastlane ios upload_deploygate # masterブランチの場合、AppStoreへアップロード elif [ "${CIRCLE_BRANCH}" == "master" ]; then fi
fastlane/Fastfile
platform :ios do desc "Build for iOS" lane :build do if is_ci? setup_circle_ci import_certificate( keychain_name: ENV["MATCH_KEYCHAIN_NAME"], keychain_password: ENV["MATCH_KEYCHAIN_PASSWORD"], certificate_path: 'circleci_demo.p12', certificate_password: '' ) end update_app_identifier( xcodeproj: "platforms/ios/circleci_demo.xcodeproj", plist_path: "circleci_demo/circleci_demo-Info.plist", app_identifier: 'ciecleci.test' ) disable_automatic_code_signing( path: "platforms/ios/circleci_demo.xcodeproj" ) gym( scheme: 'circleci_demo', workspace: 'platforms/ios/circleci_demo.xcworkspace', configuration: 'Debug', export_method: "ad-hoc", clean: true, verbose: true, output_directory: "build", output_name: "circleci_demo", xcargs: "OTHER_SWIFT_FLAGS='$(inherited) -DSTGING' PROVISIONING_PROFILE_SPECIFIER='CircleCI Adhoc' CODE_SIGN_IDENTITY='iPhone Distribution'", export_xcargs: "-allowProvisioningUpdates", export_options: "fastlane/ExportOptions.plist" ) end desc "Upload To Deploygate" lane :upload_deploygate do deploygate( api_token: ENV["DEPLOYGATE_API_KEY"], user: ENV["DEPLOYGATE_USER"], ipa: "build/circleci_demo.ipa" ) sh "rm -rf ../build" end end
こんなもんかな。以上です。