20210123のiOSに関する記事は4件です。

何回もこのコンピュータを信頼しますかと表示されて実機テストができない

バージョン

  • macOS Catalina v10.15.7
  • Xcode v12.3
  • iOS 14.3

現象

xcodeで実機テストをしようと思い、iphoneをmacに接続したら、
このコンピュータを信頼しますかという画面が表示されては消えを繰り返して、
接続ができない

解決策

Window > Devices and Simulators > Simulators
ここで不要なデバイスを開き、
Show as run destinationのチェックを外す

どう関係があるのかわかりませんが、このチェックをはずしたところ問題が解決しました

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

AVFoundation 音再生

音再生方法

まず AVFoundation をインポート

viewController.swift
import UIKit
import AVFoundation

class ViewController: UIViewController,AVAudioPlayerDelegate {

    var player :AVAudioPlayer!

まず、音ファイルをXcodeに追加。追加するのはここ!!
今回は 
umbrella と souziki が入っていますね。
スクリーンショット 2021-01-23 21.07.44.png

音声を呼び出す用の関数を定義!

viewController.swift
    public func prepareSound() {
        let soundFilePath = Bundle.main.path(forResource: "umbrella", ofType: "mp3")!
        let sound:URL = URL(fileURLWithPath: soundFilePath)
        do {
            player = try AVAudioPlayer(contentsOf: sound, fileTypeHint: nil)
            player?.delegate = self
        } catch {
            print("イエラー")
        }
        player?.delegate = self
        player?.prepareToPlay()
    }

viewDidLoad()に関数を記入

viewController.swift
    override func viewDidLoad() {
        super.viewDidLoad()

        prepareSound()

    }

あとは、ボタンなど、呼び出したいところで下記のオードを書けば

viewController.swift
    @IBAction func button(_ sender: Any) {

        if ((player?.isPlaying) != nil) {
            player?.stop()
            player?.currentTime = 0
        }
        player?.play()
    }

現在、選択私の違いによって出る音の変わる仕組みを製作中。

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

Firebaseの CloudMessaging での通知実装と Apple Developer Certificates に苦戦したメモ

基本的にはこちらの手順に従う方針だが、既にCertificateを作成していたり、本番用と開発用で違ったり、Bundle ID が違うと動かないなどがあり苦戦したのでメモ。
https://qiita.com/ausssxi/items/89305cdb3935d6f6f2b8

全体的に、iOSにおけるプッシュ通知は基本UserNotificationsをimportして使うが、そもそものプッシュ通知を送るバックエンド側のシステムが必要で、それがニフクラモバイルやFirebaseで実装されることが多いっぽい。なおFirebaseのCloud MessagingというのはFirebaseコンソールからユーザーにメルマガみたいにプッシュ通知を送れる仕組みのことっぽい。

主なつまずきポイント

シミュレータでは通知こないっぽい?

まずiOSにおける通知はアプリ起動中はこない模様。Singing & CapabilitiesPush Notificationsと合わせてBackgound Modesを追加しているので、アプリが表で起動してないときに通知を送る仕様なのだが、Xcodeで起動させるiPhoneシミュレータではそもそもバックグランドモードが使えないらしい。
スクリーンショット 2021-01-23 14.47.08.png

FirebaseのCloud Messagingで通知を行うためのCertificateも必要

通知で使うAPNs証明書(.p12ファイル)を作成するために Apple Push Services というCertificate(.cerファイル)を作成する必要がある。Certificate=証明書=.cerファイル=.p12ファイルであり、Firebaseなどの外部で証明書を使う際にはこの.12形式に変換してやらないといけないようだ。

最新のAPNsキー方式ではうまくいかなかった

Firebase公式が推奨しているAPNsキー(.p8ファイル)の方式では機能しなかった。もしかすると Bundle ID が一致してなかったときに試したからかもしれない。試していないがわかりやすそうなQiitaを見つけたので貼っておく。
https://qiita.com/MYamate_jp/items/994a31d5408bc09998bc

スクリーンショット 2021-01-23 14.36.50.png

Bundle ID が Firebase とアプリで同じでないといけない

同じプロジェクトでもBundle ID を変えてしまえばApp Store Connectでは別アプリとして認識されリリースできる。Firebaseも2つのアプリでデータを共用することができる。しかしFirebaseへのアプリ登録時のBundle ID と異なるアプリへは、Cloud Messaging を用いたプッシュ通知が送れないっぽい。
スクリーンショット 2021-01-23 14.37.23.png

実機テストではDevelopmentだが本番ではDistribution

初めに提示したQiitaは実機で通知テストするためにDevelopmentのCertificateを作成していたが、(Xcode11がiOS14に対応しておらず、Xcode12にあげるためにBigSurにあげるのは嫌だったので)本番環境で使うDistributionのCertificateを使って通知のテストをした。幸い、まだ通知機能を実装しているアプリはリリースされていないのでTestflightでインストールしたテスターにしか通知はいかない。

なお本番環境用のAPNsのCertificateはSandbox & Productionの方。
スクリーンショット 2021-01-23 12.16.11.png

Apple Developer Certificates

そもそもの知識

CSR、鍵、証明書、Provisioning Profile については以下の図解がとても分かりやすい。
https://qiita.com/fujisan3/items/d037e3c40a0acc46f618

超ざっくりしたあやふやな理解

・DevelopmentとDistributionで2つのCertificate Typeがある
・Developmentは実機テストで使い、DistributionはApp Storeへの配信に使う
・Provisioning Profileに書かれたMac・デバイス・App・機能の組み合わせでないとビルドが許可されていない

手元の実機iPhoneにアプリをインストールするのも、App Storeにアプリをリリースするのも、FirebaseのCloud Messagingで通知を送るのも、全部「わたしはAppleに認証されたMac(開発者),iPhoneですよー」という証明をしないといけない。

証明書やそれを生成するための鍵(CSR生成時に作られる?)はMacの中に保存するが、「どの証明書(TEAM)・App ID・デバイス・機能(Capabilities)で実行できるアプリなのか」というプロファイルを書いたProvisioning Profileというものをアプリに持たせ、それをApp Storeに申請することで、App Store Connect側は「あ、はいはい、確かに認証されたMac(TEAM)、App ID、機能の組み合わせねー」としてビルドとして認めてくれるようだ。

なおデバイスについては、あくまでDevelopmentのCertificateで実機テストするためのデバイスのことだと思われ、本番用のDistributionのCertificateを使ってリリース作業を行う場合は特に関係ないと思われる。ただ実機テストをする際に実機に Provisioning Profile がインストールされるそうである。

XcodeのCertificateが消えない問題

直接的には関係ないが、Certificateを作り直したりしていると遭遇。Keychainの証明書や鍵(認証局に証明書を要求するためのCSRと一緒に作られる?)を削除して、ProvisioningProfileを削除しても消えない。右クリックでDeleteしようとしてもダメ出し、Untitledとなっている証明書は存在せず、また日付から特定しようとしてもそれらしきものはない。
スクリーンショット 2021-01-23 14.28.21.png

Apple Development Certificate の「〇〇の Macbook Pro」と、それに対応する Provisioning Profileは UITest のアプリが勝手に生成するようなので削除しても復活するらしい。誰か助けて。

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

FIT SDKのMacStaticLibで大きなメッセージを書き込んだときにデコードに失敗する不具合を回避する

TL;DR

FitMesg.hFitMesg.mm を修正してビルドした libFitSdkCppiOS.a とヘッダーファイルを差し替える。
修正内容は記事の末尾。

不具合詳細

GARMIN FIT SDKはC言語/C++/Java/C#で提供されているが、同梱されているMacStaticLibを使用することでObjective-Cから使用することが出来、macOSやiOSのアプリから使用することができる。

しかし、このMacStaticLibにはバグがあり、メッセージのサイズが256Byte以上になるとヘッダーに書き込まれるデータ長とファイル末尾のCRCの値がおかしくなり、デコードできないFITファイルが生成されてしまう。

Objective-C Wrapper generate broken header when include long message - Discussion - FIT SDK - Garmin Forums

再現コード

FIT SDKに同梱されているサンプルプロジェクトにコードを追加したもの。
https://github.com/rseki-sonix/fit-ios-broken-header

device_infoメッセージのproduct_nameとdescriptorに長い文字列を追加するとデコード処理に失敗するようになる。

原因

Objective-CからC++ FIT SDKを使用するためのラッパークラス FitEncode はヘッダに書き込むデータ長を書き込んだメッセージ長から積算している。

このメッセージ長の型が FIT_UINT8 (UINT8のtypedef)になっており、256Byte以上の長さだとオーバーフローしてしまう。

https://github.com/rseki-sonix/fit-ios-broken-header/blob/master/usr/local/include/FitMesg.h#L25-L26

そのため、256Byte以上のメッセージが書き込まれるたびにヘッダーのデータ長が255Byte分短くなる。
また、ファイル末尾のCRCもそのデータ長をもとに計算されているためCRCもおかしくなってしまう。

生成済みのFITファイルを修復する

生成されたFITファイルはデータ長とCRCだけがおかしいため、適切なデータ長とCRCを書き込めばデコードすることができる。

ファイルサイズからヘッダ長(14Byte)と末尾CRCの長さ(2Byte)を引いた値を計算する。
ヘッダーの内容についてはFit Protocolを参照。

今回生成されたファイルは453Byteのためデータ長は

453 - 14 - 2 = 437 = 0x01B5
となる。
filesize.png
datasize.png
CRCは自分で計算してもよいが、FitCSVToolに-dオプションを追加すると計算した数値が表示されるためそれを用いる。
今回は 0x03A9 だった。
crc.png
書き換えるとFitCSVToolでデコードできるようになる。

MacStaticLibを修正する

GARMIN Forumsでは"your own risk"でFitMesgを修正してもいいかもとのこと。
単純にメッセージサイズの型をUINT16に変更することで正しいデータ長とCRCを持つFITファイルを生成できる。
以下の二箇所の変更が必要。

cpp/FitMesg.h
#include "fit_mesg_definition.hpp"

@interface FitMesg : NSObject
// - (FIT_UINT8) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg;
// - (FIT_UINT8) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg withDef:(const fit::MesgDefinition *)mesgDef;
- (FIT_UINT16) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg;
- (FIT_UINT16) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg withDef:(const fit::MesgDefinition *)mesgDef;
@end

#endif /* FIT_MESG_H */
cpp/FitMesg.mm
@implementation FitMesg

// - (FIT_UINT8) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg
- (FIT_UINT16) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg
{
    return [self Write:file forMesg:mesg withDef:FIT_NULL];
}

// - (FIT_UINT8) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg withDef:(const fit::MesgDefinition *)mesgDef
- (FIT_UINT16) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg withDef:(const fit::MesgDefinition *)mesgDef
{
    fit::MesgDefinition mesgDefOnNull;
    // FIT_UINT8 mesgSize = 1;
    FIT_UINT16 mesgSize = 1;
    FIT_UINT8 fieldSize = 0;
    FIT_UINT8 byte;

修正した静的ライブラリは以下の方法で行った。

FIT SDKのC++の静的ライブラリをビルドする - Qiita

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