10.4.1でビルドしたiOSアプリでプッシュ通知の処理を実行すると、「RequestPermission)メソッドを使用して、権限を要求する必要があります。」というエラーが発生します。

提供: Support
移動先: 案内検索

対象となるIDE製品

  • RAD Studio 10.4.1以降

対象となるiOSのバージョン

  • iOS 10以降

問題

モバイル チュートリアル:通知を使用する(iOS および Android)のドキュメントを参考にして、iOSアプリで動作する通知を実装しました。


  1. フォーム上にTNotificationCenterコンポーネントを配置
  2. 「プロジェクト」→「オプション」→「バージョン情報」からFMLocalNotificationPermissionを追加し、値をtrueと設定。
  3. iOS上でTNotificationCenter.PresentNotificationを実行すると、以下の図のようなエラーが発生し、通知の処理が実行できません。


Thumb03000191ujpn.png

原因

以前のバージョンで iOSの通知を利用する場合は、プロジェクトのバージョン情報で”FMLocalNotificationPermission”の値をtrueに設定する必要がありました。

FMLocalNotificationPermission”の値は、FMX.Platfomr.iOSユニットのTApplicationDelegate.CheckLocalNotificationPermissionメソッドでチェックし、iOS 8以上、かつtrueの場合はUIUserNotificationSettingsを実行してiOSのプッシュ通知認証を行っていました。


しかしiOS 10以降では、UIUserNotificationSettingsの利用は非推奨となっています。

10.4.1以降では、iOS 10以降で推奨されるUNUserNotificationCenterを利用するように変更されており、それに伴いましてiOSでプッシュ通知認証を行う手段も変更されました。


※10.4.1以降では、プロジェクトのバージョン情報で”FMLocalNotificationPermission”を追加しても無効になりました。


解決

10.4.1では、新たにTNotificationCenterコンポーネントにOnPermissionRequestResultイベントが追加されました。


OnPermissionRequestResultイベントは、RequestPermissionメソッドを実行し、通知を操作するためのアクセス許可を非同期的に要求した後、許可要求の結果を受信するためのイベントです。

RequestPermissionメソッドを実行すると、下図のように通知の認証ダイアログが表示されます。

Thumb03000192ujpn.png


つまり、このダイアログの許可/不許可の結果が、OnPermissionRequestResultイベントで取得できます。


そのため10.4.1以降でiOSの通知を利用するためには、RequestPermissionメソッドを呼び出す処理と、OnPermissionRequestResultイベントで通知の認証結果を判断する処理の実装が必要となります。


10.4.1で提供している以下のサンプルプログラムでは、

C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Mobile Snippets\Notifications\SendCancelNotification

実装例が示されていますが、現在のdocwikiでは詳しい解説が無いため、サポート情報として補足させていただきます。


以下は、iOSで通知を行うための簡単な実装手順です。


  1. 10.4.1で新規にマルチデバイスプロジェクトを作成
  2. フォーム上にTNotificationCenterとTButtonを一つずつ配置
  3. 通知許可フラグを実装する
    後で実装するOnPermissionRequestResultイベント内で通知の認証結果の判断を行うためのフラグを実装します。
    Delphiの場合:
    type
      TForm1 = class(TForm)
        NotificationCenter1: TNotificationCenter;
        Button1: TButton;
      private
        { private 宣言 }
        Notification_Permission_Flag: Boolean;
      public
        { public 宣言 }
      end;
    
    C++Builderの場合:
    class TForm1 : public TForm
    {
    __published:	// IDE で管理されるコンポーネント
    
    	TButton *Button1;
    	TNotificationCenter *NotificationCenter1;
    
    private:	// ユーザー宣言
    	bool Notification_Permission_Flag;
    
    public:		// ユーザー宣言
    	__fastcall TForm1(TComponent* Owner);
    };
    
  4. 通知許可を要求するための処理を実装する
    通知許可を要求する処理は、通知を実行する前であれば、どのタイミングでも構いません。ここでは、フォームが表示されるOnActivateイベントで実装します。フォームのOnActivateイベントで以下の処理を追加してください。
    Delphiの場合:
    procedure TForm1.FormActivate(Sender: TObject);
    begin
      if NotificationCenter1.AuthorizationStatus <> TAuthorizationStatus.Authorized
      then
      begin
        // 通知リクエスト
        NotificationCenter1.RequestPermission;
      end;
    end;
    
    C++Builderの場合:
    void __fastcall TForm1::FormActivate(TObject *Sender) {
    	if (NotificationCenter1->AuthorizationStatus() != TAuthorizationStatus::Authorized) {
    		// 通知リクエスト
    		NotificationCenter1->RequestPermission();
    	}
    }
    
    TAuthorizationStatusには、NotDetermined, Restricted, Denied, Authorizedの4種類があります。ここでは、Authorized(認証)されていないときに、通知許可を要求(RequestPermission)を実行します。
  5. 通知の許可要求の結果を受信するためのイベントを実装する
    TNotificationCenterのOnPermissionRequestResultイベントで、以下の処理を追加してください。
    Delphiの場合:
    procedure TForm1.NotificationCenter1PermissionRequestResult(Sender: TObject;
      const AIsGranted: Boolean);
    begin
      if AIsGranted then
        Notification_Permission_Flag := true
      else
        Notification_Permission_Flag := false;
    end;
    
    C++Builderの場合:
    void __fastcall TForm1::NotificationCenter1PermissionRequestResult(TObject *Sender, const bool AIsGranted) {
    	if (AIsGranted) {
    		Notification_Permission_Flag = true;
    	}
    	else {
    		Notification_Permission_Flag = false;
    	}
    }
    
    AIsGrantedの値は、通知ダイアログの結果が渡されます。Trueの場合は許可、Falseの場合は拒否
  6. 通知処理を実装する
    TButtonのOnClickイベントで、以下の処理を追加してください。
    Delphiの場合:
    procedure TForm1.Button1Click(Sender: TObject);
    var
      MyNotification: TNotification;
    begin
      if Notification_Permission_Flag = true then
      begin
        // TNotification のインスタンスを作成する
        MyNotification := NotificationCenter1.CreateNotification;
        try
          // 即座にメッセージを送る
          MyNotification.FireDate := Now;
          // メッセージを設定する
          MyNotification.AlertBody := 'iOSのローカル通知テスト';
          NotificationCenter1.PresentNotification(MyNotification);
    
        finally
          MyNotification.DisposeOf;
        end;
      end
      else
      begin
        ShowMessage('通知は許可されていません。');
      end;
    end;
    
    C++Builderの場合:
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      if (Notification_Permission_Flag)
      {
    	// TNotification のインスタンスを作成する
    	TNotification *MyNotification = NotificationCenter1->CreateNotification();
    	try {
           // 即座にメッセージを送る
    	  MyNotification->FireDate = Now();
    	  // メッセージを設定する
    	  MyNotification->AlertBody = L"iOSのローカル通知テスト";
    	  NotificationCenter1->PresentNotification(MyNotification);
    
    	}__finally{
    	  MyNotification->DisposeOf();
    	}
      }else{
        ShowMessage(L"通知は許可されていません");
      }
    }
    
  7. ターゲットプラットホームを"iOSデバイス 64ビット"に切り替えてビルドし、iOSデバイスへ配置する
    下図は、iOSデバイスでの実行例です。
    Thumb03000193ujpn.png

関連情報

C++Builder/Delphiで、iOS 14 SDK(Xcode 12)をインポートして利用する場合は、以下の注意が必要です。