質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • C#

    7116questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • iOS

    3998questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

  • Xamarin

    499questions

    Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。

iOS10でデバイストークンが取得できない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,127

aokym

score 1

リモートプッシュ通知用にdeviceTokenを取得したい

Xamarinで開発されたiOSアプリの改修をしています。

サーバサイドの担当者から、「iOS 10端末のデバイストークンが送られてこない」という報告があり調査したところ、送る以前に取得できていないようでした。

新仕様(UserNotificationFramework)への移行で解消するかと思いましたが、正常に動く状態にできていません。

書き方が悪いのか、そもそものアプローチが間違っているのか、お知恵を拝借できればと思います。

元のコードがこんな感じです

if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
{
    var pushSettings = UIUserNotificationSettings.GetSettingsForTypes(
                       UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound,
                       new NSSet());

    UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings);
    UIApplication.SharedApplication.RegisterForRemoteNotifications();
}
else {
    UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
    UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
}

Xcode8(Beta2)とiOS10ではremote push通知用のdeviceTokenが取得できず失敗する時のチェック
iOS10とiOS9にプッシュ通知を送るための最低限の処理

↑このあたりを参考にして手を加えてみました

手を入れたコード

if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
    UNUserNotificationCenter.Current.RequestAuthorization(
        UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound,
        (granted, error) =>
        {
            if (granted)
            {
                UIApplication.SharedApplication.RegisterForRemoteNotifications();
            }
        }
    );
}
else if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
{
    var pushSettings = UIUserNotificationSettings.GetSettingsForTypes(
                       UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound,
                       new NSSet());

    UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings);
    UIApplication.SharedApplication.RegisterForRemoteNotifications();
}
else {
    UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
    UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
}


ver.10以上向けの処理部分のみ追加です

出力されるエラーメッセージ

Warning: Unhandled exception: UIKit.UIKitThreadAccessException: UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread.
Unhandled managed exception:
UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread. (UIKit.UIKitThreadAccessException)

UIApplication.SharedApplication.RegisterForRemoteNotifications以外の方法がないか調べてみたのですが、見つけることができませんでした。

使用ツール

  • XamarinStudio 6.1.5.0
  • Xcode 8.2.1

追記

色々試しまして、事態はまだ解決しておりませんが、問題がここではなさそうだったので一旦クローズとさせていただきます。
アドバイスくださったお二方ありがとうございました。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

black_sleepman さんが書かれているとおり、メインスレッドで呼んでいないのが問題なのであれば、メインスレッドに移行して呼ぶことで解決できると思います。

NSObject.InvokeOnMainThread を使うとどうでしょうか。
例えば下記のような形です。

UIApplication.SharedApplication.InvokeOnMainThread(() => 
    UIApplication.SharedApplication.RegisterForRemoteNotifications());

※この部分がメインスレッドで実行され、処理が完了するまで待機されます。時間のかかる処理をしないように注意してください。
※逆に、非同期にする場合は NSObject.BeginInvokeOnMainThreadですが、非同期に呼び出されるため、処理の順番が変わってしまいます。適宜含める処理の内容を調整する必要があります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/07 11:51 編集

    ご回答ありがとうございます
    エラーは解消しました

    キャンセル

+2

UIKit関連の関数は、メインスレッドでしか呼べません。

なので、エラーを見る限りでは、その関数がサブスレッドで呼ばれていることが原因だと思います。

起動時などに取得するのが一般的だと思われます(ex. ViewDidLoadなど)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/05 14:13 編集

    回答ありがとうございます。
    エラーが出ているのはこの記述で、
    ----
    if (granted)
    {
    UIApplication.SharedApplication.RegisterForRemoteNotifications();
    }
    ----
    同一の記述がある、else if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0)) を通った先ではエラーが発生していないことを確認しています。
    処理の場所を大きく変えることができないので、別の対処方法があればご教示いただきたいです。

    キャンセル

  • 2017/02/06 12:33

    そうですね。よくよく考えたらデバイストークンの取得とかはAppDelegateでしてますもんね。

    エラーが出ている箇所が記載されていましたが、if文の前でエラーが発生しているのでしょうか。
    もしくは、if文の中の処理でエラーが出ているのでしょうか。

    [Xamarin iOS10 Device Token](https://developer.xamarin.com/guides/ios/platform_features/introduction-to-ios10/user-notifications/enhanced-user-notifications/)

    ここにXamarin iOS10でのUser Interface周りのサンプル、リファレンスが載っています。
    XamarinではiOS9らへんの書き方は推奨(保証)しなくなるらしいので、こちらを使うようにとの
    記載がありました。

    キャンセル

  • 2017/02/07 11:52

    ありがとうございます
    参考に致します

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    7116questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • iOS

    3998questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

  • Xamarin

    499questions

    Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。