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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

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

iOS

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

Xamarin

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

Q&A

解決済

2回答

4323閲覧

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

aokym

総合スコア7

C#

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

iOS

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

Xamarin

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

0グッド

0クリップ

投稿2017/02/04 12:56

編集2017/02/07 02:57

##リモートプッシュ通知用にdeviceTokenを取得したい
Xamarinで開発されたiOSアプリの改修をしています。

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

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

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

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

C#

1if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0)) 2{ 3 var pushSettings = UIUserNotificationSettings.GetSettingsForTypes( 4 UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound, 5 new NSSet()); 6 7 UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings); 8 UIApplication.SharedApplication.RegisterForRemoteNotifications(); 9} 10else { 11 UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound; 12 UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes); 13}

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

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

###手を入れたコード

C#

1if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0)) 2{ 3 UNUserNotificationCenter.Current.RequestAuthorization( 4 UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound, 5 (granted, error) => 6 { 7 if (granted) 8 { 9 UIApplication.SharedApplication.RegisterForRemoteNotifications(); 10 } 11 } 12 ); 13} 14else if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0)) 15{ 16 var pushSettings = UIUserNotificationSettings.GetSettingsForTypes( 17 UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound, 18 new NSSet()); 19 20 UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings); 21 UIApplication.SharedApplication.RegisterForRemoteNotifications(); 22} 23else { 24 UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound; 25 UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes); 26}

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

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

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

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

csharp

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

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

投稿2017/02/06 02:39

編集2017/02/06 02:46
iseebi

総合スコア96

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aokym

2017/02/07 02:51 編集

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

0

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

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

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

投稿2017/02/04 14:30

black_sleepman

総合スコア220

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aokym

2017/02/05 05:16 編集

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

2017/02/06 03: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らへんの書き方は推奨(保証)しなくなるらしいので、こちらを使うようにとの 記載がありました。
aokym

2017/02/07 02:52

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問