GeoFenceとCoreMotionを組み合わせたバックグラウンド常駐監視の一案
仕事へのパッションが抑えられません。
ジオフェンシングとモーションセンサーを使って
バックグラウンドやロック状態でも何かをしたいときの一案。
ジオフェンシングって知ってますか?
ではEnjoy ジオフェンシングとモーションセンサー!
やりたいこと
ある領域内にいるうちは定期的に何かしたい。
何かのトリガーでバックグラウンドでアプリを起動させても動くのって10秒ほど。
がんばって延長させても最長10分弱。
そうじゃなくて定期的に何かしたい。
やることの要約
- 指定領域内に入ったらモーションセンサー開始
- モーションセンサーで歩くたびに何かする
- 指定領域内は継続
- バックグラウンドでもロック時も動作開始、継続
- 指定領域から出たらモーションセンサー停止
前提
- Xcode6.3.1
- 検証機はiPhone6plus iOS8.3。
- AppStoreに申請したことはない。
- SwiftじゃないよObjective-Cです。
「・・・」のところは本筋から外れるので間引いています。
気になる方はサンプルコードからどうぞ。
サンプルコード
実装のまえに
プロテイ、、プロジェクトの設定をします。
位置情報「常に使用」を有効にします。
* Info.plistにNSLocationAlwaysUsageDescription
を追加
バックグラウンドで動かす設定をします。
* TARGETS
- Capabilities
- Background Modes
をON
* Location updates
にチェックをつける
やっと実装
まずはインポート。
余談ですがframeworkに追加しなくてよくなったのね。
framework追加なしでエラーになりません。
#import <CoreLocation/CoreLocation.h> #import <CoreMotion/CoreMotion.h>
CLLocationManager初期化と監視領域の指定。
CLLocationCoordinate2DMake
で指定した緯度軽度を中心に、
CLLocationDistance
で指定した領域を監視します。
//CLLocationManager初期化 self.locationManager = [[CLLocationManager alloc] init]; ・・・ self.locationManager.delegate = self; //Region初期化 CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(37.324540, -122.041241);//アメリカ(クパチーノ) CLLocationDistance radiusOnMeter = 100.0;//範囲指定 self.geoRegion = [[CLCircularRegion alloc] initWithCenter:coordinate radius:radiusOnMeter identifier:@"jp.roadto.ROADTO-Geo"]; //位置情報の許可状況に合わせて動作開始 if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { // iOS8 switch ([CLLocationManager authorizationStatus]) { case kCLAuthorizationStatusNotDetermined: NSLog(@"位置情報の許可が未設定なのでユーザに確認する"); [self.locationManager requestAlwaysAuthorization]; break; case kCLAuthorizationStatusAuthorizedAlways: NSLog(@"「常に許可」されている"); break; ・・・ } } else { // iOS7以下 [self.locationManager startUpdatingLocation]; }
続きましてCLLocationManagerDelegateメソッドたち
requestStateForRegion
で監視が始まったときとか
requestAlwaysAuthorization
の位置情報使用確認後とかに通知されます。
領域内に入ったときにモーションセンサーをONにし、
領域外になったときにモーションセンサーをOFFにします。
説明はコメントにて。
#pragma mark - CLLocationManagerDelegate // CLLocationManager初期化時または // アプリの位置情報の許可状態ステータスが変更されたときに通知される -(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { switch (status) { case kCLAuthorizationStatusNotDetermined: break; case kCLAuthorizationStatusAuthorizedAlways: NSLog(@"「常に許可」"); // 領域監視スタート [self.locationManager startMonitoringForRegion:self.geoRegion]; break; ・・・ } } //領域監視がスタートしたときに通知 - (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region { //現在の領域状態を確認。 //「- locationManager:didDetermineState:forRegion:」が呼ばれます。 [self.locationManager requestStateForRegion:region]; } //領域内に入ったときに通知 - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { NSLog(@"領域内になったよ"); //モーションセンサー 開始 内容は次の章で説明。 [self startMotionActivity]; } //領域の状態について通知。状態が変わるたびに呼び出される。 - (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region { switch (state) { case CLRegionStateInside: NSLog(@"領域内"); //モーションセンサー 開始 内容は次の章で説明。 [self startMotionActivity]; break; ・・・ } } //領域から出たことを通知 - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { NSLog(@"領域外になったよ"); //モーションセンサー 停止 [self stopMotionActivity]; }
あとはモーションセンサー
CMMotionActivityManager
を使ってモーションを取ります。
今回は歩いているか否かを使っていますが、他にもいろんな状態をとれます。
「//do something」でしたい何かの処理を書きます。
#pragma mark - モーションセンサー //モーションセンサー 初期化 - (CMMotionActivityManager *)getActivityManager { if (!self.motionActivityManager) { self.motionActivityManager = [[CMMotionActivityManager alloc] init]; } return self.motionActivityManager; } //モーションセンサー 開始 - (void)startMotionActivity { NSLog(@"モーションセンサー 開始"); //iOS7,8ともに必要 [self.locationManager startUpdatingLocation]; //←キモ。iOS7,8ともに必要です。 if([CMMotionActivityManager isActivityAvailable]){ NSOperationQueue *queue = [NSOperationQueue mainQueue]; CMMotionActivityManager *motionActivityManager = [self getActivityManager]; [motionActivityManager startActivityUpdatesToQueue:queue withHandler:^(CMMotionActivity *motionActivity){ //do something NSString *log = [NSString stringWithFormat:@"motion %@", motionActivity.walking ? @"そうだね。プロテインだね。" : @"んーんーんー。"]; NSLog(log); ・・・ }]; } } //モーションセンサー 停止 - (void)stopMotionActivity { NSLog(@"モーションセンサー 停止"); CMMotionActivityManager *motionActivityManagerUpdate = [self getActivityManager]; [motionActivityManagerUpdate stopActivityUpdates]; }
テストに出ます
「←キモ」のところ。
startMotionActivity内で「-locationManager startUpdatingLocation」を呼んでいます。
これ自体は位置情報の更新監視をスタートさせるものですが
なぜかこれを書くとモーションセンサーもバックグラウンドで動いてくれます。
バックグラウンドでもロック状態でも起動するし、
フォアグラウンドで起動して、バックグラウンドやロック状態になっても動き続けます。
尚、「M7」モーションセンサーはiPhone5sから搭載なので、
iPhone5以前は使えません。
結果
サンプルコードを起動させます。
サンプルコードでは画面に出力させています。
歩いているかどうかを判定しています。
歩いてると出てますね。「そうだね。プロテインだね。」
バックグラウンドでも動いていますね。「そうだね。プロテインだね。」
以上です。
エヴィバディパッション!
そうだね。プロテインだね。
— ひとのみち (@hitonomichi) 2015, 5月 29
Road to Passbookの作成
Passbookを作ってみる機会があって色々調べたので残しておきましょう。
ではEnjoy Passboooooooooook!
前提
素材を集める
証明書を作成
「キーチェーンアクセス」ー「証明書アシスタント」ー「認証局に証明書を要求」
「CertificateSigningRequest.certSigningRequest」ができました。
あとで使います。
Pass Type IDsを作成
デブセンでPass Type IDsを作成します。
証明書(さっき作った.certSigningRequest)を使用します。
できたらDownloadします。
ダブルクリックでキーチェーンに保管します。
テンプレートをゲットだぜ
Passbookのテンプレートを取得します。
ここから。Passbook Support Materials
「Passbook Materials」てリンクからダウンロード。
落ちてきたpassbook_materials.dmgを開く。
必要なやつだけ別に置いてみたら分かりやすいんじゃね?
任意の場所にフォルダを作成。今回は「PassSample」とします。
「PassSample」にサンプルjsonファイルと必要素材のどれかを置きます。
今回は「Generic.raw」を使用します。
signpassのプロジェクトをXcodeでビルドし作成されたsignpassを「PassSample」フォルダに移動に置きます。
こんな感じ。
Passbookの中に具を詰めます
pass.jsonを編集します。
まず、必要な情報があるのでキーチェーンアクセスから証明書を見てみます。
作成して保存した証明書を右クリックから「情報を見る」で開きます。
詳細な情報を開くと、あったあった。
これらをpass.jsonに設定します。
- passTypeIdentifierにPass Type IDを指定
例)"pass.com.example.PassbookSample" - teamIdentifierに部署を指定。10桁の英数字文字列です。
- organizationNameに組織を指定。
その他必要な項目を設定します。
ここを参考に。
Pass Design and Creation
オーブンに入れて出来上がりを待ちます
ターミナル起動。
「PassSample」ディレクトリに移動。
実行。
./signpass -p Generic.raw
Generic.pkpassができました!
ダブルクリックでプレビューできます。
作成手順は以上です!
アレンジで自分だけのPassbookを。
去年のWWDCで現地のディベロッパーは名刺をPassbookで持ってるって耳にしたので、
試しにひとのみちPassbook名刺をつくりました。
ひとのみちPassbook名刺
iPhoneだとPassbookアプリに入るよ。
え?いらない?ですよね。いらない人は燃えるゴミの日にだすか、かたつむりにあげてください。
別腹
余談ですが。
PassbookはiBeaconに反応してロック画面に表示しますが、
表示対象のPassbook複数あったらどうなるか。
たぶん並んで表示されるんやろーなーと思ってたら、、なんと!
思ってた通り並んで表示されました。
ちなみに、passTypeIdentifierが違えば別モノとして表示、
passTypeIdentifierが同じでserialNumberが違うと同じpassTypeIdentifierのうちどれか一つが表示されました。
食後に
PassbookはiBeaconや緯度経度に連動するし、
AppleWatchにも搭載されるし、
あんまり流行っていないけど、使い道はあると思ってるんですけどね。
自動更新とかサーバ絡んだことはまたそのうち研究します。
iBeaconとPassbookのサンプルを作ったよ。
iBeaconとPassbookのサンプル作りました。 サンプルコードとか技術的な話はないです。ないんです。
ビーコンとは最近流行ってるIoTの切り込み隊長で、 電波を発信してモバイル端末に訴えかける仕組みです。
小売店や映画館とか、割と事例が出てきてます。
小売店や飲食店でもホームページみたいに必須になるかも。このスマフォの普及に加えてウェアラブルの普及が来たらこちらからの訴えかけに最適。
/企業の導入で注目が高まる「Beacon」って何? http://t.co/tJSpCIk5ub @HuffPostJapanさんから
— ひとのみち (@hitonomichi) 2015, 1月 8
Apple WatchとiBeaconは相性良さげ。
大手が導入して世間の生活に入り込めたら普及するのに。
/米国スーパー、Apple Watch向けにiBeaconを活用した初のプロモーション http://t.co/rsFGvlNu2T @iPhoneMania_jpさんから
— ひとのみち (@hitonomichi) 2015, 1月 12
iBeaconで映画館でのプロモーションやって。同じ目的のグループに対して能動的なアピールは効果的やわ。
/新体験!?映画館や映画フェスでのiBeaconを使った最新事例 | オムニチャネルラボ(Omni-Channel Lab.) http://t.co/T5nHeoQoDG
— ひとのみち (@hitonomichi) 2015, 1月 22
カードのプロモ目的の、街フェスタ×ビーコン事例。お客さんからの有用さはいかに。
/国内初、大手クレジットカードの iBeaconを活用したO2Oサービスに「ACCESS(TM) Beacon Framework」が採用 http://t.co/C7F3xdpLJ6
— ひとのみち (@hitonomichi) 2015, 2月 25
はい。 こんな感じです。
作ったサンプルですが、下の写真の黒い四角いのがビーコンです。 一個1000円で電池で動きます。
空想上の街イベントアプリを作りました。
食とバンド、アートが街のいろんなところで楽しませてくれます。
例えば、ハンバーガーショップに近づくとアプリがビーコンに反応します。 ピロンとアラートが表示されますねー。
この例ではクーポン¥300,000OFFをゲットです。
店側からしたら、なかなかアピールする手段がない中、 こちらから訴えかける一つの仕組みとして有効ですね。
あと、Passbookも一度iPhoneに取り込めばビーコンに反応して、 ロック画面に出てきます。
こちらも合わせてアピールの道具になりそうですね。
入力欄付きUIAlertControllerサンプル
iOS8から登場したアラートコントローラー「UIAlertController」のメモ。
パスワード入力欄付き。
前提
selfはViewControllerね。
ソース
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"タイトル" message:@"メッセージ" preferredStyle:UIAlertControllerStyleAlert]; //入力欄(UITextField)付きを設定 [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) { //入力欄に薄くでるアレ textField.placeholder = @"パスワードを入力"; //マスク(*表示) textField.secureTextEntry = YES; }]; //キャンセルボタンと処理 UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"キャンセル" style:UIAlertActionStyleCancel handler:nil]; [alert addAction:actionCancel]; //OKボタンと処理 UIAlertAction *actionOK = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { //OKタップ時の処理 //alert.textFieldsにUITextFieldが入っている UITextField *textField = alert.textFields.firstObject; if ([textField.text isEqualToString:@"0000"]) { NSLog(@"パスワードOK"); } }]; [alert addAction:actionOK]; //表示 [self presentViewController:alert animated:YES completion:nil];
アクションボタンのスタイルはUIAlertActionStyleで指定。
2014年に通った道と2015年の道しるべ。
関西・大阪在住のフリーランスアプリ開発者です。
新年明けたということで(1月中なのでセーフ)去年の総括をします。
(まじめに。)
トピック
- 2014年に通った道
- 2015年の道しるべ
2014年に通った道
半フリーランス半会社員な感じでした。
生活リズムは、昼は仕事に出て夜と土日は自宅でという感じ。
ではいってみましょう♪
順不同です。
WWDC2014に参加
- Road to WWDC2014「準備するよ」 - ROADTO みちログ
- Road to WWDC2014「行くよ」 - ROADTO みちログ
- Road to WWDC2014「レジストレーション」 - ROADTO みちログ
- Road to WWDC2014「Keynote」 - ROADTO みちログ
- Road to WWDC2014「the Bash」 - ROADTO みちログ
- Road to WWDC2014「帰ってきたからまとめたよ」 - ROADTO みちログ
アメリカ本土初上陸でした。世界は思ってたより狭くて近かったです。
得たものをよく聞かれるけど半年たって今考えると大きく3つ。
- 最新キーワードにアンテナ張るようになった。
- 日本人ディペロッパーとの出会い&再会で単純に嬉しいしそこからのインプットが増えた。
- 上2つの相乗効果で意識の向上で視野も広くなった。
2015も行きたいと。私ははい。思ってます。
壁は抽選と家庭内稟議・・。
アプリスペシャリストな会社に常駐
これまでSIerへの常駐が多かった私ですが初めて知り合いのアプリ開発会社*1に常駐しました。
いろいろカルチャーショックを受けましたね。
知識やノウハウもさることながら、スピード。
意思決定のスピード、求められる開発スピード、スピードに関してが最も大きなインパクトが有りました。
逆にスピードなしではアプリの世界では生きて行けないのかも。
身にしみる思いでした。
ここではあの有名な○○の○○アプリやみんな知ってる○○の○○アプリを○○させて頂きました。*2
そういえば久しぶりにJavaもやりましたね。
WebシステムのiPadアプリ移植
Enterprise案件。
既存のWebシステムをiPadで使うためのアプリに移植。
JaveScriptをフックしてゴニョゴニョとか。
AlarmWeatherリリース
久しぶりのROADTOブランドのアプリ。
目覚ましと天気予報とツイッター投稿を速攻でするオレ得アプリ!
OpenWeatherMapのAPIを使ってます。
某機関の某診断アプリ その1
受託案件。
内容は内緒。
ViewからPDF作るのに苦戦。
某機関の某診断アプリ その2
受託案件。
内容は内緒。
営業さん用 社内ファイル専用ビューアアプリ
Enterprise案件。
外部に出したくないファイルを安全に見るためのiPadアプリ。
営業が持って回る社内PDF・動画・画像の専用ビューアアプリです。
DBとファイルの暗号化とか。
アメホリバルアプリリリース
共同開発のStoreアプリ。
大阪ミナミのアメ村/堀江のイベント、「アメホリバル®」の公式アプリです。
@tinpayさんと一緒につくりました。
ミナミの発展に寄与できれば幸いですね。
今年もバージョンアップする予定です。
ポコポコポコ〜
アメホリバルについてはこちら。
そして@tinpayさんの記事。
くまプレの開発支援
@EijiShibutani さんの「【本格RPG】くまのプレイといにしえの大戦記」の開発支援をしました。
DBでのデータ管理とサーバ側、サーバ接続部分を支援。
MBaasを使って初めて構築。
Promiseの概念もちょっと勉強できました。
ゲームの世界も面白そうです。
感想。
我ながら昼夜問わず働きました。
過去最高の労働時間でした。
それが良いか悪いかは別にして。。
ただ、
だんだん自分の思い描く仕事内容や仕事環境に近づきつつあるなと。
以前はまりかけていた負のスパイラル*3からは抜け出せつつあるはず。
そして、たまたまかもしれないけど需要があってよかったね!(ほっ)とも思います。
2015年の道しるべ
今年はこんなことを考えています。
受託案件中心にしたい。
常駐で拘束時間が多かったので、今年はライフワークバランスを考えるために受託案件を多くしたいです。
受託案件が楽というわけでは決してないです。
責任を持って自分を律して時間を有効に使う意味を含んでいます。
コワーキングとかも試してみてもいいかと。
iPhone+何か
iPhone/iPadの中で閉じる世界から飛び出して、
例えばiBeacon、BLE、ウェアラブルなやつなんかをやりたいです。
もう少しAppStoreとかかわりたい。
基本ツール系で。
ゲームの開発支援とかもいいかな。
ROADTOブランドのStoreアプリも作りたい。
ま、ここは優先度は低めです。
おわりに
何事もバランスなので、土台作りしながら先鋭的なところもやっていきたいと思っています。
がんばる!という次元ではなく、ちゃーんと戦略的に。
これ以上、海パンとゴーグルできゃべつ畑の真ん中にいたら凍えるのでこのへんで。
どうぞ皆様、今年もよろしくお願いいたします。
Write the code. Change the world.
— ひとのみち (@hitonomichi) 2015年1月22日
iPhoneのスクリーンをgifに。
iPhoneのスクリーンをgifにしたいほどの昼下がりってありますよね。
手順メモ。
自己責任で。
前提
- MacはYosemite。
- FFmpegをインストールしておく。
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
$ brew install ffmpeg
手順
$ ffmpeg -i input.mov output.gif
サイズ指定となんだか遅かったのでオプション付けていい感じに。
$ ffmpeg -i input.mov -s 375x667 -an -r 15 -pix_fmt rgb24 -f gif output.gif
できあがり
サイズやfpsもオプションで変えれるみたい。