20200213のiOSに関する記事は6件です。

iOSのショートカットでなうぷれを作る

今回はAppleMusicアプリで再生中の曲情報をなうぷれとしてTwitterに投稿するショートカットを作成します。

デモ

サンプル

1581603408.jpg

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

iPad ProでPWAして全画面表示する~最終的に運用でカバー~

fs.jpg

おことわり

今回iPad Proにて全画面表示を行う必要があったため、PWAを試してみたが、結構時間がない中での実装だったうえに、iPadがレンタルだったため、細かい検証を行うことができなかった。スクショも取れていないので写真で失礼させていただく。
PWAはまだまだ機能として開発途中な感じがあり、イマイチ挙動が掴めきれなかったので、もしかしたら言葉のニュアンスの違いなど間違ったことを言っている部分があるかもしれません、そういったところは、指摘いただければできるだけ直します。よろしくお願いします。
本来なら記事にするのレベルにも達していない内容だと思いますが、数少ない同じ用途で悩んでいるエンジニアのヒントになればと思い、書くことにしました。なので優しくしてください!w
また、今回先人たちの記事を大量に参考にさせていただいたので、ここで感謝を述べておきたい。

製作背景

今回ある案件で、展示されたiPadからアプリを介して情報を入力する機能を作成することになった。エンドユーザーが使用するため、必要とされる機能は、

  • ネイティブアプリのように全画面表示できる
  • 関係のない機能に触らせないようする
  • ユーザーの操作でホーム画面に戻らないようにする

など。
swiftを学習する時間はなかったので、ブラウザで全画面表示すればいけるだろうと高をくくって実装を始めたけど、結構クセが強くてハマったので記録しておく。

[参考]https://qiita.com/tmtysk/items/2c5da83feec45b4ee36f
[参考]https://qiita.com/umamichi/items/0e2b4b1c578e7335ba20

結果

結論から言うと、自動で全画面表示にすることはできなかった。
起動時に画面上部に帯が一本出てしまう状態で、上にスライドすると消える。というところまでしかできなかったので、現場でスタッフさんに朝イチでアプリを起動したら、画面を上にスライドしてもらう。
という運用カバーになってしまった。

使用した機材

iPad Pro 12.9 インチモデル(第三世代)
iOS 13.2.2

実装方法

1.manifest.jsonを設置する

short_nameはブラウザのタイトルバーとかに出る名前。
nameはアプリ名っぽい。
iconsの192x192に設定した画像がアイコンになるけどこれは罠で、ここだけに書いても反映されない。
後述するタグも埋め込まないといけないらしい。

あと余談だが、このshort_nameに設定した名前を後で変更した場合 safariのキャッシュをクリアしても反映されない ここは最後までどうやって更新するのかわからなかった。
全画面表示にするには、"display"のバリューを"standalone"、もしくは"fullscreen"とすればよさそうだが、手元の環境ではどちらに設定しても挙動は変わらなかった。(キャッシュの影響かもしれない)

manifest.json
{
  "short_name": "TEST APP",
  "name": "TEST",
  "icons": [
    {
      "src": "./icon.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "./icon.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": "/start",
  "background_color": "#CDCDCD",
  "display": "standalone",
  "theme_color": "#000000"
}

[参考]https://developers.google.com/web/fundamentals/web-app-manifest

2.Service Workerを有効にする

下記のようなservice-worker.jsを設置する。

service-worker.js
self.addEventListener('install', function(e) {
  console.log('[ServiceWorker] Install');
});
self.addEventListener('activate', function(e) {
  console.log('[ServiceWorker] Activate');
});
self.addEventListener('fetch', function(event) {});

[参考]https://qiita.com/umamichi/items/0e2b4b1c578e7335ba20

3.headerにタグを入れる

index.html
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<link rel="apple-touch-icon" href="icon.png" sizes="192x192"/>
<link rel="manifest" href="manifest.json">
<script>
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register("js/service-worker.js").then(function() { console.log('Service Worker Registered'); });
   }
</script>

上の二つのタグに関しては、かつてこれらのタグを入れることで透明になったらしいが、iOS13からblack-translucentgが削除された?というような情報もある。
とにかく、手持ちのiPhone7(iOS11.4.1)では効いたが、iPad(iOS13.2.2)ではこれだけで透明にならなかった。
PWA化するとスライドしたときに消えるので、効いているような気もするが挙動がバグっぽい。。
真ん中のiconのリンクタグが、manifestのところで言っていたもの。これを埋め込まないとアイコンが反映されない。
あと、下の二つのタグで、manifest.jsonとservice-worker.jsを読み込んでいる。

4.ホーム画面に追加からアプリ化する

青で消してるのはキャッシュが消えなくてshort_nameが変更できなかったため。
これを行うと、ホーム画面にアプリっぽいものが作成される。
fs3.jpg

で、ホーム画面に作成されたアイコンから起動すると以下のような画面になる

fs2.jpeg

この上の白いバーの存在が謎。。。
これについては、何かタグが入っているのではないかと思い、document.body.clientHeightで出力してみたが、本来の高さが返ってきたのでおそらくsafari側で入れられている何かかと思われる。
この状態から一度上にスライドすれば以降このバーは消えるのだが、そもそもkioskとしての運用なので、スライド操作自体を無効化したい。

5.一度だけ上方向へのスライドを有効にする。

[参考]https://gist.github.com/violetyk/5343883

    function no_scroll(){
        document.addEventListener('touchmove', handleTouchMove, { passive: false });
    }
    function scroll(){
        document.removeEventListener('touchmove', handleTouchMove, { passive: false });
    }
    let start_pos = 0;
    $(window).scroll(function(e){
      var current_pos = $(this).scrollTop();
      if (current_pos > start_pos) {
        no_scroll();
      }else{
            // 
        }
      start_pos = current_pos;
    });

ここからが力業。アプリ起動後一度だけ上方向へのスクロールを許すようにする。
これで一応全画面表示ができるようになった。
スクロールの復帰関数も用意してあるのは、アプリを再起動すると上の謎のバーが再び出現するため、画面内に隠しボタンを設置し、そこを押すと再びスクロールできるように作ったため。
そしてこのスクロール、これもなかなかハマりポイントで、古い記事の方法とかだと動かなかったりする。
[参考]https://qiita.com/yukiTTT/items/773356c2483b96c9d4e0

アクセスガイドを設定してホーム画面に戻れないようにする

設定からアクセスガイドをオンにする。
ホームボタンがある機種はホームボタンを、ない機種はサイドの電源ボタンを三回押しすると起動する。
これで完全なフルスクリーンになる。

こちらの機能は、タッチ不可の領域を設定したりできるが、設定した範囲はグレーになるので、見栄えがあんまりよろしくない。

[参考]https://qiita.com/ousaan/items/5464f99bf15675ccc84b

他に試したことなど

フルスクリーンAPIを使う

フルスクリーンAPIというのがある。
こちらも試してみたが、自動で全画面にするっていうのが無理で、何かしらのユーザーの操作をトリガーにしないといけないっぽい。(セキュリティ的に?)
かつ、全画面にしても左上に大きなxボタンが出るので、ちょっと今回の用途には合わなかった。
fs4.jpg

[参考]https://qiita.com/annnews23/items/728a87a256cd0cf6e3a5
[参考]https://qiita.com/uzuki_aoba/items/ea7f35bc2833dd58b9ef

そもそもタブレットで全画面表示するのは難しい

PCの場合、chromeにkioskモードというのがある。
これを使えば全画面表示で最前面に表示されkioskとして使用できる。
(タッチデバイスの場合はこまごま他の設定が必要だが。。)
PCはキーボードというインターフェースがあるのでf11で一発で復帰できるが、
そもそもタブレットは物理的なインターフェースが少ない。
全画面表示で操作不能となるような事態を避けるため、メーカー側でそう簡単には完全な全画面にならないように設計していると思われる。
案件状況によっては、タッチ機能の付いていないモバイルディスプレイで全画面表示するように製作したほうがはるかに簡単なので、こだわりがなければこちらに切り替えることをお勧めする。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

iPadでもSwiftUIで遊べるドン!

こちらの記事で、XcodeのPlaygroundでSwiftUIが書ける旨が解説されていますが、iPadでも可能です。外出時に思いついたコードを試すなど、とても良さそうです。
https://qiita.com/shtnkgm/items/387132cd9633a59e7390

軽くサンプルのスクショ載せて解説します。忘れた時に参考できるような形です。

515A5131-FD09-46BC-A0C6-FB413BCB34DB.png

ポイント UIHostingViewControllerを使う

XcodeではPreviewProviderでプレビューを見る事ができますが、Playgroundにプレビューはありません。なので、UIKitの時にもPlaygroundでViewを検証するのに使っていたPlaygroundSupportのモジュールを利用します。 PlaygroundPage.current.liveViewにUIHostingViewControllerを割り当てる事でliveViewを表示できるようになります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

各OSのBluetoothの仕様

各OSのBluetoothの仕様

iOS

場所

25.5 Advertising Interval
The accessory should first use the recommended advertising interval of 20 ms for at least 30 seconds.
If it is not discovered within the initial 30 seconds, Apple recommends using one of the following longer
intervals to increase chances of discovery by the device:
● 152.5 ms
● 211.25 ms
● 318.75 ms
● 417.5 ms
● 546.25 ms
● 760 ms
● 852.5 ms
● 1022.5 ms
● 1285 ms

推奨される広告パターンと広告間隔は次のとおりです。
最初に、20ミリ秒間隔で少なくとも30秒間アドバタイズします
30秒後に検出されない場合は、152.5ミリ秒、211.25ミリ秒、318.75ミリ秒、417.5ミリ秒、546.25ミリ秒、760ミリ秒、852.5ミリ秒、1022.5ミリ秒、1285ミリ秒のいずれかの長い間隔に変更できます。
重要: これらの特定の間隔は、正確に使用される間隔です!これらの実際の間隔からのわずかな偏差でさえ、発見までの時間を劇的に増加させる可能性があります。

Android

The blog post “What to keep in mind when developing your BLE Android app” contains a section with advertising. According to the blog, the allowed advertising intervals are the following:
a. ADVERTISE_MODE_LOW_LATENCY – Advertising interval: 100 ms
b. ADVERTISE_MODE_BALANCED – Advertising interval: 250 ms
c. ADVERTISE_MODE_LOW_POWER – Advertising interval: 1000 ms

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

BleManager option

BleManageroption

BleManager

スキャンoptionでconnect成功率、速度向上できます

Android

まずAndroidじゃ!

  • scanningOptions - JSON - [Android only] after Android 5.0, user can control specific ble scan behaviors:

    • numberOfMatches - Number - corresponding to setNumOfMatches
    • matchMode - Number - corresponding to setMatchMode
    • scanMode - Number - corresponding to setScanMode
    • reportDelay - Number - corresponding to setReportDelay // 現在サポートされていない模様
  • scanningOptions - JSON - [Androidのみ] Android 5.0以降、ユーザーは特定のbleスキャン動作を制御できます。

    • numberOfMatches - Number - Bluetooth LEスキャンフィルターのハードウェア一致の一致数を設定する
    • matchMode - Number - Bluetooth LEスキャンフィルターの一致モードをハードウェア一致に設定する
    • scanMode - Number - Bluetooth LEスキャンのスキャンモードを設定します。

### 詳細

  • numberOfMatches

    • MATCH_NUM_MAX_ADVERTISEMENT
    • hwのリソースの現在の機能と可用性に依存します。
    • 定数値:3(0x00000003)
    • MATCH_NUM_FEW_ADVERTISEMENT
    • フィルターごとにいくつかの広告に一致します。hwのリソースの現在の機能と可用性に依存します
    • 定数値:2(0x00000002)
    • MATCH_NUM_ONE_ADVERTISEMENT
    • フィルターごとに1つの広告に一致
    • 定数値:1(0x00000001)
  • setMatchMode

    • MATCH_MODE_AGGRESSIVE
    • アグレッシブモードでは、信号強度が弱く、期間中に目撃/一致の数が少ない場合でも、hwは一致をより早く決定します。
    • 定数値:1(0x00000001)
    • MATCH_MODE_STICKY
    • スティッキーモードの場合、hwでレポートする前に、信号強度と目撃のより高いしきい値が必要です。
    • 定数値:2(0x00000002)

      • scanMode
      • SCAN_MODE_LOW_POWER
      • 低電力モードでBluetooth LEスキャンを実行します。これは最小の電力を消費するため、デフォルトのスキャンモードです。このモードは、スキャンアプリケーションがフォアグラウンドにない場合に適用されます。
      • 定数値:0(0x00000000)
      • SCAN_MODE_BALANCED
      • バランス電源モードでBluetooth LEスキャンを実行します。スキャン結果は、スキャン頻度と消費電力のバランスが取れたレートで返されます。
      • 定数値:1(0x00000001)
      • SCAN_MODE_LOW_LATENCY
      • 最高のデューティサイクルを使用してスキャンします。アプリケーションがフォアグラウンドで実行されている場合にのみ、このモードを使用することをお勧めします。
      • 定数値:2(0x00000002)
      • SCAN_MODE_OPPORTUNISTIC
      • 特別なBluetooth LEスキャンモード。このスキャンモードを使用するアプリケーションは、BLEスキャンを開始せずに他のスキャン結果を受動的にリッスンします。
      • 定数値:-1(0xffffffff)

iOS

まず参考記事

For example, when your app is relaunched by system, you can retrieve all the restoration identifiers for the central manager objects the system was preserving for your app, like this:
After you have the list of restoration identifiers, simply loop through it and reinstantiate the appropriate central manager objects.

システムがアプリのために保存していた中央マネージャーオブジェクトのすべての復元識別子を取得できます。
復元識別子のリストを取得したら、単純にループして、適切な中央マネージャーオブジェクトを再インスタンス化します。

効果

前のスキャンでconnectしたBLEに対してスキャンすっ飛ばしてconnectするようになるので劇的に早くなる(3秒)
見つけられなければ通常スキャンに切り替わる

使い方

  • xcodebackgroud processing on
  • infoにrestoreIdentifierKey任意のキー追加
  • retrieveServicesooption指定すればokよ

例 

if (!isAndroid) {
BleManager.start({ showAlert: false, restoreIdentifierKey: 'bitkey', forceLegacy: true });
}

気をつけないと行けないのがretrieveServicesooptionを指定してしまうとAndroidのスキャンが正常に動かないので
条件分岐などで避けてください!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AIに歌わすのは大変すぎる。

AIに歌を歌わせてみた。

最近はVocaloidやVtuber等良い声が出るAiがありますが、自作できないのか探求しています。

SpeakingOS.cpp
static constexpr auto DO = "ド";
static constexpr auto RE = "レ";
static constexpr auto MI = "ミ";
static constexpr auto FA = "ファ";
static constexpr auto SO = "ソ";
static constexpr auto RA = "ラ";
static constexpr auto SI = "シ";
int main(void){
    return NULL;
}

TITLE残業はなくならず

歌詞
残業はなくならず,国は捨てる
気持ち悪くなるだけ,悪くなってしまった
闇にいーる,疲れにやられてて,窓から見えるいつもの街灯を探した,わかってる
労働争議するわけでもなくて君と文句いうこともない
かつてと違うことは1つ,生きる勇気を失ってしまった
残業は,たまあってく おーわることなくー
かーいしゃの電気がほとんど消えてしっまった
残業はなくならず国は捨てる
たくさん過労が事実でも空しみは消えません
褒美だったと思っていた毎日も無くなっていた
知らなかった。あの地位になれば死なぬと思わなかったのに
育児とか 嫁とかのため何をすれば,いいのかわからなくなるなんてな
(いや)分かってる。もう昔の俺ではない 後ろめたい表現を俺の心が生み出した
最も大きい空しみさ
残業は 給料の証という
けれど(残業代が)実らぬならそう意味が無いサービス残業
定時で帰りたいよ 上司帰ったよ
1人ですすり泣く日々 残業に追われるだけ
誰も払わない(居酒屋の)勘定
払うどころか押し付けるから
いい加減に払いません?
このツケ返して貰いますって
(上司が怖いから)言えないよ
残業はなくならず国は捨てる
上司が謝っても,空しみは消えません
生きがいだった子がいても
ここにはいない
この会社を出なければ
会うこともできないのに
一人ですすり泣く日々残業に追われるだけ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む