- 投稿日:2019-04-17T19:01:55+09:00
CLIでローカルビルドをUnityCloudBuildにアップ
※この記事を書いてる途中(2019/4/17)に ふとググったら去年10月公式に…
それはさておき、2017年12月15日に
Unity Cloud Buildがローカル環境で作ったビルド成果物をアップロードできるようになった
という記事を見かけました。
しかし、WebからじゃなくCLIからアップロードしたいと思い、
きっと誰かが良い記事書いてくれるのでは…と思ってましたが
びっくりするくらい簡単なDeployGate1があるせいか、
はたまた そもそも興味持たれないのか 待てど暮らせど見つからず2
CloudBuildのページあたりを見ていましたらAPIドキュメント発見CloudBuild API Document (v1.0.0時点)
https://build-api.cloud.unity3d.com/よし作ってみるか!
…なるほど、まったくわからん
とまでは行きませんでしたが
ChromeDeveloperで挙動やログを追いかけて なんとか出来ました 3
どれだけの方が利用するかわかりませんが、とりあえず公開前提
- 私の環境: MacOSX10.14.4(iMac4K)
- 成果物は apk / ipa のみしかアップロードチェックしていません
- unity DashBoard にて アプリ名登録まで済んでいるものとします
- bashシェルスクリプトで順番に説明
- json解析にjqを使用
- 置換にgsedを使用
- curl等、色々間違ってたらすいません…
- ですので最低限のみ記載
以下スクショの文字列は例ですので DashBoard眺めてメモってください。
PROJECT_ID(ここではTest)と UPID(ここでは3dc…)をメモ
Testの下の ORG_ID(ここではdeveloper…)をメモ
成果物ファイル名は アスキーコード 0x20〜0x40 辺りを使ってましたら
%20〜%40 に変換してください(URLEncode?)初期設定
API_KEY= #DashBoard - プロジェクト - Develop - Settings - Cloud Build - APIキーに書いてある PROJECT_ID= #DashBoard - プロジェクト名 ORG_ID= #DashBoard - プロジェクト名の下に書いてある UP_ID= #DashBoard - プロジェクト - プロジェクト名の横に書いてあるUPID FILE_NAME= #成果物ファイル名 xxxx.ipa 等をURLEncode EXT= #成果物の拡張子(つまりapkかipa) FILE_SIZE= #成果物のファイルサイズ `wc -c < 成果物ファイル名` とか if [ "${EXT}" = "apk" ]; then PLATFORM=android TYPE_NAME=".APK file" TYPE_NAMEe=".APK%20file" elif [ "${EXT}" = "ipa" ]; then PLATFORM=ios TYPE_NAME=".IPA file" TYPE_NAMEe=".IPA%20file" else exit 1 fi BUILD_API_DOMAIN="https://build-api.cloud.unity3d.com/api/v1" ARTIFACT_API_DOMAIN="https://build-artifact-api.cloud.unity3d.com/api/v1" BUILD_TARGET_ID="_local" LOG=`mktemp --tmpdir=./` function endJob { echo $1 rm ${LOG} }ビルドエリア生成して ビルド番号取得
curl -X POST -H "Content-Type: application/json" -H "Authorization: Basic ${API_KEY}" --data-binary "{\"platform\": \"${PLATFORM}\", \"label\": \"${COMMENT}\"}" ${BUILD_API_DOMAIN}/orgs/${ORG_ID}/projects/${PROJECT_ID}/buildtargets/${BUILD_TARGET_ID}/builds -o ${LOG} -s BUILD_NO=`cat ${LOG} | jq .[0].build` STAT=`cat ${LOG} | jq .[0].buildStatus` if [ "${STAT}" != "\"success\"" ]; then endJob "BuildArea - Error: ${STAT}" exit 1 fiアーティファクト生成
curl -X POST -H "Content-Type: application/json" -H "Authorization: Basic ${API_KEY}" --data-binary "{\"name\":\"${TYPE_NAME}\",\"primary\":true,\"public\":false,\"files\":[{\"filename\":\"${FILE_NAME}\",\"size\":${FILE_SIZE}}]}" ${ARTIFACT_API_DOMAIN}/projects/${UP_ID}/buildtargets/${BUILD_TARGET_ID}/builds/${BUILD_NO}/artifacts -o ${LOG} -s STAT=`cat ${LOG}` if [ "${STAT}" != "Created" ]; then endJob "Generate Artifact - Error: ${STAT}" exit 1 fiアップロード
hc=$( curl -d "" -X POST -H "Upload-Length: ${FILE_SIZE}" -H 'Tus-Resumable: 1.0.0' -H 'Content-Type: application/offset+octet-stream' -H "Authorization: Basic ${API_KEY}" ${ARTIFACT_API_DOMAIN}/projects/${UP_ID}/buildtargets/${BUILD_TARGET_ID}/builds/${BUILD_NO}/artifacts/${TYPE_NAMEe}/upload/${FILE_NAME} -o ${LOG} -w '%{http_code}\n' -s ) if [ $hc != 201 ]; then STAT=`cat ${LOG}` endJob "Upload Post - Error: $hc\n${STAT}" exit 1 fi hc=$( curl -X PATCH -H 'Upload-Offset: 0' -H "Content-Length: ${FILE_SIZE}" -H 'Tus-Resumable: 1.0.0' -H 'Content-Type: application/offset+octet-stream' -H "Authorization: Basic ${API_KEY}" --data-binary @"${1}" ${ARTIFACT_API_DOMAIN}/projects/${UP_ID}/buildtargets/${BUILD_TARGET_ID}/builds/${BUILD_NO}/artifacts/${TYPE_NAMEe}/upload/${FILE_NAME} -o ${LOG} -w '%{http_code}\n' -s) if [ $hc != 204 ]; then STAT=`cat ${LOG}` endJob "Upload Patch - Error: $hc\n${STAT}" exit 1 fiシェアリンク作成
# GET:既に生成済みのShareID取得、POST:ShareID生成、DELETE:ShareID削除 curl -d "" -X POST -H "Content-Type: application/json" -H "Authorization: Basic ${API_KEY}" ${BUILD_API_DOMAIN}/orgs/${ORG_ID}/projects/${PROJECT_ID}/buildtargets/${BUILD_TARGET_ID}/builds/${BUILD_NO}/share -o ${LOG} -s STAT=`cat ${LOG} | jq .shareid | gsed 's/"//g'` if [ "${STAT}" == "null" ]; then cat ${LOG} endJob "ShareLink - failed" exit 1 fi SHARE_URL="https://developer.cloud.unity3d.com/share/${STAT}" #ここらへんで SHARE_URL をチャット等に送る endJob "success"出来上がったSHARE_URLをチャットやメール等に流せばOKかと。
Android・iOSからダウンロード・インストール・実行出来ました。みんな幸せにな〜れ
規約違反とかありましたら記事消します…。
- 投稿日:2019-04-17T18:29:02+09:00
[Android] ConstraintLayoutでwrap_contentしつつ領域からはみ出さないようにする
実現したいレイアウト
特に何の変哲もないレイアウトだが、これをConstraintLayoutで作るのに手こずった話。
素直なConstraintLayout実装
とりあえず上記のレイアウトを素直に作ると以下のようになる。
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="70dp" xmlns:app="http://schemas.android.com/apk/res-auto" android:background="#FFDDDD"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" android:text="販売価格" android:textSize="25dp" /> <TextView android:id="@+id/price" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toRightOf="@id/title" android:layout_marginLeft="10dp" android:lines="1" android:autoSizeTextType="uniform" android:text="2,800" android:textSize="40dp" /> <TextView android:id="@+id/yen" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@+id/price" app:layout_constraintBaseline_toBaselineOf="@+id/price" android:gravity="bottom" android:text="円" android:textSize="20dp" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintRight_toRightOf="parent" android:text="購入する" android:textSize="25dp" /> </androidx.constraintlayout.widget.ConstraintLayout>問題点
しかし、このレイアウトには問題があり、価格が大きくなるとボタンと価格が重なってしまう。
※分かりやすくするためボタンは半透明化
解決方法
- 値段の
layout_constrainedWidth
をtrue
にする- 円の右端を購入するの左端につける
- 値段の右端を円の左端に付ける
<TextView android:id="@+id/price" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toRightOf="@id/title" app:layout_constraintRight_toLeftOf="@+id/yen" android:layout_marginLeft="10dp" android:lines="1" android:autoSizeTextType="uniform" android:text="2,811" app:layout_constrainedWidth="true" android:textSize="40dp" /> <TextView android:id="@+id/yen" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@+id/price" app:layout_constraintRight_toLeftOf="@+id/button" app:layout_constraintBaseline_toBaselineOf="@+id/price" android:gravity="bottom" android:text="円" android:textSize="20dp" />
layout_constrainedWidth
をtrue
にすることで wrap_contentの中身が大きくても、Constraintをはみ出さないよう幅を制限できる。
また、layout_constrainedWidth
を有効にするために、左右両端にConstraintをつける必要がある。これで価格がはみ出ることはなくなった。
位置調整
しかし、上の方法ではまだ問題があり、価格が短い場合は価格と円が左寄せにならなくなってしまう。
これを調整するために以下の対応が必要になる。
layout_constraintHorizontal_chainStyle="packed"
を指定して価格と円をくっつけるlayout_constraintHorizontal_bias="0"
を指定して左端によせる
layout_constraintHorizontal_chainStyle
は双方向にConstraintで結ばれたView同士をくっつけるか、分散させるかを指定することができる。
これをpacked
にすることで価格と円がくっつくが、標準では中央寄せになってしまうので、位置を左寄せにするためlayout_constraintHorizontal_bias
を0に設定する。以下が最終的なレイアウトファイル。
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="70dp" xmlns:app="http://schemas.android.com/apk/res-auto" android:background="#FFDDDD"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" android:text="販売価格" android:textSize="25dp" /> <TextView android:id="@+id/price" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toRightOf="@id/title" app:layout_constraintRight_toLeftOf="@+id/yen" android:layout_marginLeft="10dp" android:lines="1" android:autoSizeTextType="uniform" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintHorizontal_bias="0" android:text="300" app:layout_constrainedWidth="true" android:textSize="40dp" /> <TextView android:id="@+id/yen" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@+id/price" app:layout_constraintRight_toLeftOf="@+id/button" app:layout_constraintBaseline_toBaselineOf="@+id/price" android:gravity="bottom" android:text="円" android:textSize="20dp" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintRight_toRightOf="parent" android:text="購入する" android:textSize="25dp" /> </androidx.constraintlayout.widget.ConstraintLayout>
- 投稿日:2019-04-17T11:27:49+09:00
Android build時にapkにcommitHashを埋め込んでアプリ上で確認する
自分用メモ
/app/build.gradle
//commit hash 取得 def getCommitHasH() { def process = "git rev-parse --short HEAD".execute() process.waitFor() (process.exitValue() == 0) ? process.text.trim() : "" } android { defaultConfig { // BuildConfig へ埋め込み buildConfigField("String", "COMMIT_HASH", "\"" + getCommitHasH() + "\"") } }kotlinで表示制御する場合
HogeActivity.kt//debugビルドなら表示する if(BuildConfig.DEBUG){ commitHashText.text = BuildConfig.COMMIT_HASH commitHashText.visibility = View.VISIBLE }else{ commitHashText.visibility = View.GONE }layoutxmlで表示制御する場合
<!-- import BuildConfig --> <data> <import type="com.hoge.BuildConfig"/> </data> <!-- Data binding --> <TextView tools:text="@{BuildConfig.COMMIT_HASH}" android:visibility="@{BuildConfig.DEBUG ? View.VISIBLE : View.GONE}" />ref
- https://gist.github.com/kappa-lab/fd8650dfcc2f780055255fa982e82473
- https://qiita.com/kawachi/items/d97c448b013c37f2f198
- 投稿日:2019-04-17T07:30:08+09:00
Kotlin Serialization事始め
はじめに
僕が神と崇めているJake Wharton氏(@JakeWharton)のGitHubを眺めていたら、 Kotlin Serialization なるものを使っていることが分かりました。神が使っているものだから、きっと我々下々の民に素晴らしい恩恵を与えるものに違いない
そう思い使い方を調べてみました。
Kotlin Serializationとは
Kotlin serialization consists of a compiler plugin, which automatically produces visitor code for classes, and runtime library, which uses generated code to serialize objects without reflection.
公式リポジトリの説明によると、『Kotlin Serializationはクラスのビジターコードを自動的に生成するコンパイラプラグインと、生成されたコードを使用してリフレクションなしでオブジェクトをシリアル化するランタイムライブラリで構成されている』そうです。はぁ
さらに、Kotlin Serializationは以下の機能を備えているそうです。
@Serializable
及び標準コレクションとしてマークされているKotlinクラスをサポート- JSON、CBOR及びProtobuf形式をサポート
- 同様のコードがJVM/JS/Nativeで機能するマルチプラットフォーム
要するに、Web APIなどのレスポンスをサービスで利用できる形式のオブジェクトに変換する、パーサのようなものかなと。JSONのパーサだと、GsonやMoshiなどが有名ですね。また、これらのパーサと比べて、リフレクションを使用していないため、動作が早いんだとか。ほほう。
導入
コンパイラプラグインをプロジェクトルートに追加します。
build.gradlebuildscript { ext.kotlin_version = '1.3.30' dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" } }なお、Kotlinのバージョンは
1.3.30
以上が必要とのことです。続いて、モジュールに依存関係とプラグインに関する追記をします。build.gradleapply plugin: 'kotlinx-serialization' repositories { maven { url "https://kotlin.bintray.com/kotlinx" } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.11.0' }全ての追記が終わったら
Sync Project
を実行し、エラーが出ていなければOKです。使い方
以下のようなJSON形式の場合
repo.json{ "name": "dagger", "description": "A fast dependency injector for Android and Java. http://google.github.io/dagger", "language": "Java", "html_url": "https://github.com/google/dagger", "watchers_count": 563, "stargazers_count": 13294, "forks_count": 2672, "owner": { "login": "google", "avatar_url": "https://avatars1.githubusercontent.com/u/1342004?v=4" } }こんなモデルを作ります。
Repo.kt@Serializable data class Repo( val name: String, val description: String? = null, val language: String? = null, @SerialName("html_url") val url: String, @SerialName("watchers_count") val watchers: Int, @SerialName("stargazers_count") val stars: Int, @SerialName("forks_count") val forks: Int, val owner: Owner )Owner.kt@Serializable data class Owner( val login: String, @SerialName("avatar_url") val avatar: String )
@Serializable
アノテーションを付けたKotlinクラスがシリアライズの対象になります。@SerialName
アノテーションはJSONのキー名と違ったパラメータを紐づける場合に使います。その他のアノテーションは公式のドキュメントを参考にしてください。Gson/Moshiからの移行
Retrofit+GsonあるいはRetrofit+Moshiなどで、すでにAPIを叩く処理を実装している場合、Kotlin Serializationへの移行はできないのではないか?安心してください。神は我々を見捨てませんでした
Kotlin Serialization Converter
Retorfit向けにコンバータを用意してくれていたのです。このコンバータをGsonやMoshi同様に
Api.ktval contentType = MediaType.get("application/json") val retrofit = Retrofit.Builder() .baseUrl("https://example.com/") .addConverterFactory(Json.asConverterFactory(contentType)) .build()とすれば、Kotlin Serializationが使えます。今後正式にRetrofitのプロジェクトに採用されるかもしれません。
まとめ
JSON以外にもパースできる形式があったり、独自のシリアライズを定義することもできるのですが、今回はひとまず概要のみで割愛させていただきました。導入に関しては、使用可能なKotlinバージョンの縛りはあるものの、GsonやMoshi同様にアノテーションで簡潔に書くことができました。導入コストも比較的低いのではないでしょうか。また、先述した動作速度の向上に関しても気になるところではあるので、時間がある時に他のパーサと比較してみたいと思います。今回はこのへんで。
参考文献
- Kotlin Serialization: https://github.com/Kotlin/kotlinx.serialization
- 投稿日:2019-04-17T01:52:22+09:00
Xamarin 最近どうよ?
「ネイティブアプリ開発者は絶滅危惧種なのか?」への感想文 - ナカザンドットネット
や
への反応で、「最近 Xamarin 生きてんの?」という声がちらほら聞こえたので書いてみました。
もともとの 「ネイティブアプリ開発者は絶滅危惧種なのか?」 という問いには、「緩やかにそうなっていくでしょうね」 という冒頭の記事を書かれた @Nkzn さんとほぼ同じアンサー1 なので、この話題を Xamarin と絡めたらというネタで書きます。
マイクロソフトなのになんで React 使ってんの?Xamarin は?
Office も Teams も Skype も、全て Web アプリも含めての rewrite 構想だったのでしょうね。
Webを含めるという戦略も当然だし、Xamarin は Webアプリはカバーしない ので、至極当然の選択です、以上です。近年のマイクロソフト
ここ数年のマイクロソフトは、軸足を完全に Azure、つまりサーバーサイドに移していて、クライアントサイドのプラットフォーム(Windows)で覇権を取ることはあきらめたように見えます。
フロントエンド技術への注力で目立つものは、
- TypeScript 2
- Xamarin
- HoloLens
くらいで、いわゆる「Windows向けアプリケーション」を開発するための、
- WPF(Windows Platform Foundation)
- UWP(Universal Windows Platform)
といった領域の新機能はあまり目立ちません。
クロスプラットフォームな .NET 開発/実行環境である .NET Core
一方でマイクロソフトは、サーバーサイドというか、 Windows 以外のプラットフォームで .NET 資産を使えるようにする ことに注力し続けていて、それが .NET Core です。
.NET Core は 本当にクロスプラットフォーム で、 Linux や mac で同じバイナリが動作します。
AWS の Lambda も .NET Core をサポートしているし、Dockerコンテナ も普通に用意されています。「は?オレ今まで .NET 使ってないから関係ねーし」と言われればそれまでですが、この先ずっと同じ言語を使って働いていくとも限らないですし、選択肢が増えるのは良いことです。
マイクロソフト自身が「脱Windows」している
個人的にもっと象徴的だなあと思ったのが SQL Server on Linux です。
MS の RDBサーバーである SQL Server は当然 Windows OS 専用でしたが、それすら Linux 版を作ってしまいました。
このように、マイクロソフト自身が Windows を捨てる準備を着々としているように感じられます。
Xamarin は最近どうなのよ?
さて、ネイティブアプリ開発が PWA に喰われ、クロスプラットフォームなネイティブアプリ開発は Flutter に押されと、オワコン説もささやかれる Xamarin ですが、Xamarin の最近の動向を書いてみます。
そもそもブランドとしての Xamarin とは、
- Android や iOS の API を .NET 向けにラップした Xamarin Native(Xamarin.Android や Xamarin.iOS)
- ↑を利用した、Android/iOS/etc共通のUI/アプリケーションフレームワークである Xamarin.Forms 3
に大別されます。
Xamarin Native は縁の下の力持ちというか、Android,iOSそれぞれのSDKのバージョンアップに追従して粛々とバージョンアップをし続けていて、それだけでとても価値があります。逆に言えば、ここでは皆が驚くような新機能は今後も出てこないでしょう。
Xamarin.Forms が、Flutter や ReactNative と直接の競合関係になる箇所です。
Flutter の「Materialで美麗なアプリを爆速で」とか、ReactNativeの「WebもAndroidもiOSも」に比べると弱いですが、機能追加はしています。最近だと、
- FlexLayout - FlexBox みたいなやつ、というかそれ
- Xamarin.Forms Visual - Flutter よろしく Android/iOS で Material な見た目を実現できるやつ
Xamarin.Forms Visual は実現方法は違えど、対Flutterとしては効果が期待できそうな雰囲気を感じます(目的はそれかは知らない)。
↑ Visual Challenge Conquered! | Xamarin Blog より
今後私は Xamarin と、あるいはネイティブアプリとどう向き合って行くのか?(持論)
Xamarin に関しては、徐々にシェアは減っていくのでしょうが、ぽんぽこ風に言えば「それでもどっこい生きている」でしょうか。意外としぶといんですよ、.NET が死ななければ Xamarin も死なないし。
私自身は、「PWAファースト」な考えをしています。
最近は Glide という Spreadsheet から PWA が自動生成できる サービスに注目していて、そう言えばこれは Xamarin からスピンアウトした人達が作っているサービスでした。スピンアウトした彼らは、ネイティブアプリからPWA移行の急先鋒と言えるのかも知れないですが、この Glide に注目している理由を、冒頭の @Nkzn さんのブログから引用します。
BtoBでお客さんが「アプリが欲しい」と言った場合に、実はそれは素朴なWebアプリでいい要件だったり、少し込み入ってもPWAの範囲でなんとかなるものは、意外と多いのではないでしょうか(肌感覚です)。
こういう肌感覚を私も持っていて、Glide ってまさにこういうニーズにぶっ刺さるんじゃないかな、と感じるからです。
Salesforce みたいなツールを導入するコストは無い、業務は EXCEL で回っているみたいな中小企業さん向けのソリューションですね。
Glide がそのまま使えるケースは限られるでしょうが、開発の参考にする価値は大いにあるなあと。PWA の次の選択肢として検討するのが「ガワネイティブ」ですね。
DroidKaigi 2019 の私の発表 で、「再考!ガワネイティブ」という章を設けました。これの意図するところは、
- プレゼンテーション層は PWA(というか Web)
- デバイス連携はネイティブ
とすることで、現状 Web では苦手な機能を部分的にネイティブにやらせることで、いいとこ取りが簡単にできるじゃん?というものです。
で、このデバイス連携箇所をネイティブで作る際、Xamarin(Xamarin Native)が活躍します。
例えば 「カメラで画像を撮影して Android の TensorFlow Lite や iOS の CoreML で解析してその結果を返す」 という一連の処理をそれぞれ実装して、抽象化されたAPIを定義し、それを JavaScript と連携させて PWA から呼び出す、ということは、現状もっとも作りやすいのは Xamarin と .NET です。
Flutter や ReactNative や Cordova などはどうしてもネイティブとのブリッジが面倒です。その面倒さは API をラップしている Xamarin Native にはほぼありません(何度言っているのだろうこのセリフ)。
ただ、Kotlin Multiplatform がもっと進化したら置き換えられる可能性はあります、期待しています。おわりに
まとめると、
- モバイルネイティブアプリ開発者は徐々に絶滅危惧種になっていくと思う
- Xamarin はそれでもどっこい生きている(く)
- 10年後のことは誰にもわからない
モバイル "ネイティブ" アプリ開発案件の数は減っていくと思っていて、その中のクロスプラットフォームアプリ開発ツールと領域でも Flutter や RN、Kotlin MPP とパイを取り合う構図なので、Xamarin へのニーズも徐々に減っていくと思います(クロスプラットフォームはモバイルに限った話ではない、という話ならそれは Xamarin ではなく ".NET" ですし)。
一方で .NET の利用シーンは増えている(Azure, ゲーム(Unity), HoloLens など)ので、「周りがほとんど .NET だった時にモバイルアプリが必要になったら Xamarin」という選択にはなると思います。JavaScript はほぼどこでも使えるようになっているし、Kotlin もそうなりつつあります。Dart はまだ未知数という感じでしょうか。
Android Dev Phone 1 を $400 で買って、自分で書いたアプリケーションがその端末で動いたとき、めちゃくちゃ感動したし、なんだかものすごい未来が来る予感がして、実際(概ね)そうなったわけですが、その10年前と同じ感動と予感が得られる「何か」をずっと探していて、そのために、スマホアプリに限らずいろいろなテクノロジーに手を出しています。たぶんこれからもそうして生きていくと思います、それが楽しいです。
- 投稿日:2019-04-17T00:40:58+09:00
Glideで個人間で使う旅行計画PWAアプリをつくってみた
はじめに
ネイティブアプリデベロッパーからしたら驚愕のWebサービスが出てきました。
当方もネイティブアプリ開発をしていますが、15分足らずでPWAアプリが作れるのは脅威的だと思います。本記事では、ざっくり作り方、Glideでできることできないことを明確にしていきたいと思います。
(記事執筆時 2019/04/17 時点)作成したアプリになります。ご査収ください。
スポット一覧
スケジュール一覧
GWにタイ旅行に行くので、知り合いとスポットを管理できたら便利だなぁと思い作成しました。
アプリ前提
- データ作成は、本アプリからユーザが行う(PC使えない場合も踏まえて)
- 少人数での利用(2-3人)
GlideでのPWAアプリ作り方
ぶっちゃけある程度はポチポチしてるだけで作れるので説明はあまりいらないかと思いますが、一応つけときます。
- Glide に登録し「New App」
![]()
- Google Spreadsheetでデータの作成
![]()
- Glideでデータを選択
![]()
- Glide画面の
Navigation
,Screen
,Settings
で入力項目や表示項目を設定していく![]()
めちゃくちゃ簡単っ!!
Glideでの操作
ドメインを登録するには課金しないとみたいです
http://help.glideapps.com/faq/setting-a-custom-domain-for-your-appGlideでできなかったこと、注意すること
正直ここまで簡単にアプリが作れるので、文句はないのですが、これができればなぁという一覧です。まあアップデートでなんとでもなると思うので今後も期待ですね。
写真はURLの直アドレスのみ
- SpreadSheet上の画像保存のデータを参照してもアプリ上には反映されない
- とりあえず画像はGoogle Drive保存か、Evernoteとかに保存して参照してねということらしいです
アプリ上から画像の保存は不可
- 手入力で画像アドレスをはっつけるのはめんどい!と思い、ないかなと期待しましたが、残念ながらできない様子
データ入力項目はテキストのみのため、日付項目などは選択できない
- (今のところ)データの入力項目はNote、テキスト、Switchのみです。
Spreadsheetの計算式は利用できない?
- データ追加はシートに計算式がある箇所はスルーされて、新しい行に追加される
- ARRAYFORMURAで解決するかも
Navigation(アプリメニュー項目)を増やすと表示項目などの設定が初期化される(バグ?)
- 途中まで作成してあとからメニューを増やそうとしたら表示項目などが初期化されてしまい、また最初からになりました。(簡単だからいいけど、さすがにめんどくさい。。。)
Setting(入力項目や表示項目)のエクスポートができない
- 入力項目や表示項目のエクスポートはできず、同様にアプリをコピーとかもできないようです。
さいごに
無料かつ短時間でノンプラグラミングでここまでのアプリができてしまうGlide。個人、企業で利用しない手はないですね!
個人的にはもっと細かく設定できたり、設定をエクスポートできたらなぁという思いがありますが、今後有料化したりして機能が増えていけばなぁと思う次第です。