ROADTO みちログ

ひとのみちのブログ。大阪でiOSアプリの道を歩くフリーランス。

ホテルのリモコンアプリの実装担当しました。

作ったというか実装担当したアプリが世に出たので紹介したいと思います。

そしてMacFan2018年7月号に掲載されたのでご紹介です。 巻頭カラー見開き4ページにわたってドドンと掲載されています。 ディレクションの株式会社rootの西村さん、システム担当の株式会社フィードテイラー大石さんがバッチリ載ってます! f:id:hitonomichi:20180531203015j:plain f:id:hitonomichi:20180601144421p:plain f:id:hitonomichi:20180601144425p:plain f:id:hitonomichi:20180601144431p:plain f:id:hitonomichi:20180601144432p:plain

先日オープンしたTHE MILLENNIALS(ザミレニアルズ)渋谷というホテルがあります。

カプセルホテルなんですけど少し変わっていて、スマートポットと呼ばれる個室になっていて快適です。 チェックイン時にiPod touchを渡されます。それが部屋のリモコンになります。 そのiPod touchで照明やベッドやプロジェクターやファンを操作することができます。

でですね、私はリモコンアプリのiOSアプリの実装をお手伝いしました。 今回は仕様追加からの参画だったんですけども、フィードテイラーの大石さんに声をかけていただいて、実装や導入を体験させていただきました。

THE MILLENNIALSはですね、実は京都にもあって、京都が先にオープンしたんです。 京都では導入に2、3日かかっていたものを、渋谷では1日ほどに激短縮することができました。

QRコードを読み込むことによって初期設定を全てやってしまうっていう方法をとりました。 その、QRコード読み込んで初期設定するところを主に担当しました。記事中の「QRコードで初期設定」の箇所です。

無線ならではの難しいところがあって、普通のアプリ案件と違ってソフトとハードが関わると、一体どっちの問題なのかわからないってことがよくあります。よくというか、絶対ハマります。 今回もなかなかどうして一筋縄ではいかなかったんですけれども、関係者で力を合わせて乗り切った感じです ホテルのオープンに携わることができて、貴重な体験だったなと思っています。

ディレクションの段取り、ネットワークの設定、仕組み化、進め方など、プロフェッショナルなプロジェクトで勉強になりました。 上質に触れることは大事ですね。

エンタープライズのアプリを一般ユーザーが使ってる例ってあまりないと思うので、そのあたりを含めご興味あればMacFan2018年7月号をお手に取っていただければと思います。

CognitoIDを取得する方法

AWS Cognito の CognitoIDと呼ばれるモノを取得する方法を備忘録。
頑張ったけど使わなくなったのでここで供養。

CognitoのUserPoolのsubの値を取得する

    var pool: AWSCognitoIdentityUserPool?
    var credentialsProvider: AWSCognitoCredentialsProvider?

    func login() {

        let email = "メールアドレスの値"
        let password = "パスワードの値"

        // ユーザープールを取得する
        pool = AWSCognitoIdentityUserPool(forKey: "AWS USERPOOLのキー")
        // 認証する
        let user: AWSCognitoIdentityUser = pool!.getUser(email)
        user.getSession(email, password: password, validationData: nil).continueWith(block: {task in
            if task.error != nil {
                dLog("ログイン失敗:" + task.error.debugDescription)
            } else {
                dLog("ログイン成功")
                
                user.getDetails().continueWith(block: { (task: AWSTask) -> Any? in
                    if let response = task.result, let userAttributes = response.userAttributes {
                        
                        var cognitoId: String?
                        for userAttribute in userAttributes {
                            if userAttribute.name == "sub" {
                                cognitoId = userAttribute.value
                            }
                        }
                        
                        if let cognitoId = cognitoId {
                            
                            dLog("Cognito id: \(cognitoId)")
                            
                        } else {
                            dLog("ログイン失敗: Cognito id: nil")
                        }
                        
                    } else {
                        dLog("ログイン失敗: Cognito id: nil")
                    }
                    return nil
                })                
            }
            return nil
        })

Cognitoのフェデレーティッドアイデンティティアイデンティティ IDの値を取得する

    var pool: AWSCognitoIdentityUserPool?
    var credentialsProvider: AWSCognitoCredentialsProvider?

    func login() {

        let email = "メールアドレスの値"
        let password = "パスワードの値"

        // ユーザープールを取得する
        pool = AWSCognitoIdentityUserPool(forKey: "AWS USERPOOLのキー")
        // 認証する
        let user: AWSCognitoIdentityUser = pool!.getUser(email)
        user.getSession(email, password: password, validationData: nil).continueWith(block: {task in
            if task.error != nil {
                dLog("ログイン失敗:" + task.error.debugDescription)
            } else {
                dLog("ログイン成功")                
                
                // ユーザープールをプロバイダーに設定する
                self.credentialsProvider = AWSCognitoCredentialsProvider(regionType: .APNortheast1,
                                                                        identityPoolId: "AWS IDENTITY_POOLのID",
                                                                        unauthRoleArn: "AWS UNAUTH_ROLE_ARN",
                                                                        authRoleArn: "AWS AUTH_ROLE_ARN",
                                                                        identityProviderManager: self.pool)
                
                let configuration = AWSServiceConfiguration(region: .APNortheast1,
                                                            credentialsProvider: self.credentialsProvider)
                AWSServiceManager.default().defaultServiceConfiguration = configuration
                
                // IdentityIdを取得する
                self.credentialsProvider?.getIdentityId().continueWith { (task: AWSTask) -> AnyObject? in
                    if (task.error != nil) {
                        
                        dLog("error on login=\(task.error.debugDescription)")
                        
                    } else {
                        if let cognitoId = self.credentialsProvider?.identityId {
                            
                            dLog("Cognito id: \(cognitoId)")
                            
                        } else {
                            dLog("ログイン失敗: Cognito id: nil")
                        }
                    }
                    
                    return nil
                }
            }
            return nil
        })

ログアウトも必要ですね

let pool = AWSCognitoIdentityUserPool(forKey: "AWS USERPOOLのキー")
let user: AWSCognitoIdentityUser = pool.currentUser()!
user.signOut()
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: .APNortheast1,
                                                             identityPoolId: "AWS IDENTITY_POOLのID",
                                                             unauthRoleArn: "AWS UNAUTH_ROLE_ARN",
                                                             authRoleArn: "AWS AUTH_ROLE_ARN",
                                                             identityProviderManager: pool)
credentialsProvider.invalidateCachedTemporaryCredentials()
credentialsProvider.clearCredentials()
credentialsProvider.clearKeychain()
pool.clearLastKnownUser()

ハマった点

ここの値が異なっててハマったので次はハマらないぞ。

認証プロバイダー 
 |- Cognitoタブ 
  |-- ユーザープール ID
  |-- アプリクライアント ID

お名前.comのドメインのWebサーバーはAWS、メールサーバーはロリポップに設定する

お名前.comで取得したドメイン。 WebサーバーはAWSのS3でホスティング、メールサーバーはロリポップにしたかった時に苦労したのでメモ。

前提

  • お名前.comでドメイン取得済み。仮にexample.jpとする。
  • ロリポップ契約済み
  • AWSのアカウントがありRute53のHosted Zone作成済み

お名前.comのネームサーバー変更

ログインし、「ネームサーバー変更」へ。
ネームサーバー情報にRute53のNSの値を入力し保存。 f:id:hitonomichi:20170617133734p:plain

待つの。

変更が反映されるまでしばし待つ。
待ってる間にRute53にメールサーバーの設定をする。

AWSにログインしRute53へ

ロリポップのメールサーバーを確認しよう。 ターミナルを立ち上げて、打つ!

$ nslookup -type=mx xxxx.greater.jp ←ロリポップのドメイン

Non-authoritative answer:
xxxxx.xxxxx.jp  mail exchanger = 10 mx01.lolipop.jp.

mx01.lolipop.jp.ロリポップのメールサーバのよう。

じゃあこれをRute53に追加。
f:id:hitonomichi:20170617133720p:plain

お名前.comのネームサーバー変更が終わってるか確認

ターミナルを立ち上げて、打つ!

$ nslookup -type=ns example.jp ←独自ドメイン

指定したNSに変わっていたらOK。 変わっていない場合は時間をおいてトライ!

メール送信して届いていれば完了! 知ってたらなんてことないんだろうけど知らないと全くわからんですねインフラは。

株式会社グッドタイミングを立ち上げました。

f:id:hitonomichi:20170313100250j:plain
会社を立ち上げました。という話です。

株式会社グッドタイミング誕生

今年はじめから会社を作ろうと動いておりまして、先日登記申請が完了したので「株式会社グッドタイミング」が誕生しました。
設立日は2017年3月3日です。

これまではアプリ受託の個人事業主でやって来た訳ですが、所謂「法人成り」とは違いまして、個人事業主のROADTOは存続しつつ、新しく別事業をする会社を作ったということになります。
アプリ受託開発はROADTO、インターネットサービスの運営はグッドタイミング、という事です。

なにやるの

グッドタイミングのインターネットサービスの内容ですが、「空き時間のシェアサービス」です。
高齢化、副業推奨、自動化の波といった、この日本のこの時代にこそ需要がある、価値あるサービスにするのが目標です。

しかし肝心のサービスそのものは、まだありません。
これから作ります。これから作ります。

何もしてないのかよと突っ込まれた場合用に用意してる弁解ですが、
準備は進めていて、各方面にお願いして不可欠な専門家にはすでに協力を頂いております。

まずユーザーに刺さる素敵なデザインが不可欠。デザインはデザイナーSさん。
そしてWebページがないと始まらない。Web開発はOさん。
モバイルの時代なのでアプリが欲しい。アプリ開発は@hitonomichiさん。
土台となる会計・税務面からのアドバイス。会計士Mさん。
盾となる法律面。サービスの法的なチェックは弁護士Kさん。

その他、事前に話を聞いて頂いた皆様にも後押しを頂いております。
ありがとうございます。泣いてます。花粉ひどいですよね今年。

箱があると何か入れたくなる

図太く大胆に、やれる事はすべてやる気持ちでやっていきます。

とはいえ、まだ箱ができただけでからっぽ。
これから作っていく段階なので偉そうな事は何も言えませんが、逐次お伝えしていけたらと思います。
中身をこれから詰めて価値をつけて参る所存でございますので、どうか温かい目でみて、記事を見かけたらイイねして、顔を見かけたらウィンクしてやってください。

おお、よっしゃ頑張れよという方で、もし応援してくれるという方がいらっしゃればこちらを見て頂けると喜び庭駆け回ります。
どちらかお好きな方へどうぞ。

ハマゾン www.amazon.co.jp

始まったところで何もないのですが、頑張ります。
よろしくお願いいたします。

Swift3でなんども調べてるちょっとしたこと

Swift3でなんども調べてるちょっとしたことを書きます。

非同期実行

DispatchQueue.global().async {
    // 非同期処理
    DispatchQueue.main.async {
        // メインスレッド処理
    }
}

フリーランスアプリ開発者が2016年10月〜12月に通った道

f:id:hitonomichi:20160104004403p:plain
関西・大阪在住、フリーランスアプリ開発者の私@hitonomichi2016年10月〜12月の活動まとめです。
前回の活動まとめから3ヶ月経ったので自分自身での振り返りがてら、
3ヶ月間の総括をします。

お仕事のお問い合わせはこちらからお願いいたします。
f:id:hitonomichi:20160410090308p:plainROADTO Webページ

トピック

2016年10月〜12月に通った道

  1. シフト管理サービス
  2. 受付アプリ
  3. BLE連携アプリ
  4. アメホリバルアプリ
  5. 音声SNSアプリ
  6. クーポン配信アプリ

それではいってみましょう(σ・∀・)σ
順不同です。

シフト管理サービス

WebとAppStore向けアプリの共同開発案件。
不定期シフト管理サービスです。
人を不定期に不特定の場所へ派遣する業務の連絡を効率化します。

アプリはAppStoreにリリース。
Webも本番リリース済み。

Web担当のエンジニアと一緒に開発しました。
私はiOSの開発と、その他開発に関わるディレクションをしました。

アプリだけではないWeb画面を絡めた案件であっても、チームを組んで対応できるという自信になりました。
一人ではないということで程よい強制力が働くのも良かったです。

受付アプリ

AppStore向けアプリの受託案件。

QRコードで病院の受付をするアプリ。
ちょこっと改善。 QRコード読み取るのも簡単になりましたね。

BLE連携アプリ

AppStore向けアプリの受託案件。

BLEガジェット同士を連動したり、
BLEガジェットとスマホならではの機能を連動したりします。
赤外線リモコンとつないでおうちハックのようなことができます。

リアルと繋がっているので、楽しい仕事仕事です。
通信が見えにくいのでテストが大変ですが・・。

アメホリバルアプリ

f:id:hitonomichi:20161003110709p:plain
共同開発のAppStoreアプリ。@tinpayさんと一緒につくってます。

毎年秋に開催される、大阪ミナミのアメ村/堀江のイベント、「アメホリバル®」の公式アプリです。

今年も去年に引き続きiBeacon機能を搭載。

hitonomichi.hatenablog.com

音声SNSアプリ

AppStore向けアプリの受託案件。

要件から設計してUIの提案まで。
mBaaSで作る予定です。

クーポン配信アプリ

AppStore向けアプリの受託案件。

デザイン重視の案件で、デザイナーから提供されるUIを忠実に再現することが求められます。 これまで培ってきたUI作成技術をフル活用して挑みます!

こちらもリアル世界とネットが繋がる仕組みなので楽しいです。

総括

サービスの開発がひと段落しました。
自分的には、新しいことにチャレンジして、得るものがたくさんありました。

半分受託は相変わらず。
個人的に面白い仕事を頂けてるので、いつもながら大変ありがたいです。

2017年1月〜3月への道しるべ

これからについて。

サービスの立ち上げ

新しい展開を考えていて、企画して進めていきたいと考えています。
実行してこその価値なので、信念持って進めていきます。

引き続き受託

半分は受託をする見込みです。
ありがたいことに、年始から数ヶ月はお話がすでにあります。
あとiPhone+何かの仕事もやりたい。

おわりに

周りのベンチャーが、やれ東京に事務所を作ったやら、数千万調達したやら、IPOする企業に参画やら、景気のいい話が聞こえて来て羨ましいです。
羨ましいですが、そんな気持ちはほどほどにしておいて、自分は自分として進めていくしかありません。
スピード感とリスクのバランスを取って頑張ります。

チームで開発した実績もできたことですし、チーム開発のノウハウも溜まったので、また次回はよりよくできるはず。
デザイン、Web、AndroidiOS、まるっとチームでお請けするので、そんな案件もご相談頂けたらと思います。

2016年も終わりに近づいて来ました。また今年も成長できたと感じています。
辛いことも嬉しいことも色々ありましたが、概ね楽しんで仕事できたので結構なことですね。
皆様今年はありがとうございました。どうぞ来年もよろしくお願いいたします。

お仕事のお問い合わせはこちらからお願いします。
f:id:hitonomichi:20160410090308p:plainROADTO Webページ

過去の道

アメホリバルアプリを2016年バージョンにアップデート!

アメホリバルアプリを2016年バージョンにアップデート!
f:id:hitonomichi:20161003110709p:plain
もうこれを書いているのが12月なので終わってだいぶ経ってますが、書きます。

もう冬になっちゃいましたね。。

アメホリバルとは。 アメホリバルは毎年10月に大阪のアメ村・堀江エリアで開催されるバルイベントです。
今年2016年は10/21〜30でした。
104店舗が参加されました。
前売チケットだと3,000円/5枚つづり!お得!
アメホリバル公式ページはこちら。

amehoribar.com

アメホリバルアプリをアップデートしました!

アメホリバルの公式アプリを毎年作らせてもらってるんですが、昨年に引き続き(昨年はこちら)、アメホリバルアプリをアップデートです。

アメホリバル - 関西最大級のバルイベント

アメホリバル - 関西最大級のバルイベント

  • Risa Umeda
  • フード/ドリンク
  • 無料

f:id:hitonomichi:20161213230056j:plain

  • バージョンアップ
    • 起動アニメーション
    • 2016年用にショップデータを更新
    • Parse.comからFirebaseに乗せ換え
    • iBeacon表示変更

もう3年目ともなると作業の分担や進め方が固まってきました。
そして、もう気軽に追加できる機能はなくなってきたかも。

Parse.comが終了ってことでFirebaseに乗せ換え。(´・ω・`)
乗せ換えの部分は@tinpayさんが頑張ってくれました。さすがです。

メンバー

アプリは昨年に引き続き@tinpayさん共同制作でした。
今年は私が多忙で@tinpayさんに頼ってしまいました。
素敵デザインはまた提供いただきました。

iBeacon連携機能

iBeacon(アイビーコン)っていういわゆる発信機を参加店に置いてもらい、近くのお店をお知らせする機能。
去年から導入開始して、導入店舗数は68/104店舗。
今回、私もバルに参加しましたが、行ったお店は5店舗中4店舗がiBeaconを置いていました。
嬉しい。嬉しい! お店のアピールが少しでも増えたのなら幸いです。

店舗の方と少し話しましたが、「ああビーコンね」みたいな感じで存在は知ってもらってるようでした。
導入数が増えるとそれを使ってできることがあるはずで、何か面白い企画を考えたいです。
f:id:hitonomichi:20161213230042p:plain

今年も参加しました。

私ももちろんアメホリバルに参加しました。
一度に何件もはしごするのも楽しいし、普段入れないようなお店にもお試し感覚で入れるのが嬉しい!
次の店どうする?みたいな会話も楽しかったです。

来年バージョンは?

来年はVRで店の中を体験できるようにして、ApplePayを搭載して支払いもできるようにします。 ごめん、それは無理。うそ。ふー、セーフセーフ。あぶない。

また来年もいくぞアメホリバルー!

f:id:hitonomichi:20161213230051j:plain

自己紹介
メガネは売っていません
高浜 一道(たかはま かずみち)
大阪でiOSアプリの道を歩くフリーランス。
iPad・iPhoneとサーバを連携した、JSONやDBといったキーワードが出てくるツール系が多めです。
お仕事のご依頼やご連絡はこちらから。
お仕事ください!
Web : ROADTO
ML : k-takahama(a)roadto.jp

個人的なアカウントはこちら。
Tw : @hitonomichi
Fb : kazumichi.takahama