web-dev-qa-db-ja.com

iOSアプリがバックグラウンドにあるときにアラートを表示する

iOSアプリがバックグラウンドにあるときにアラートビューを表示する(そしてロケーションを使用している)。

たとえば、ber Partner(Driver)appは、次の場合でもアラートを表示し、音を鳴らします。

  • 通知をオフにしました!
  • 私のiPhoneはサイレントモードです!

ローカル通知アプローチを認識していますが、ユーザーが[設定]で通知をオフ/変更すると機能しません。私は何か違うものを探しています。

enter image description here
上記の状態に到達するために実行されたアクション:

  • Uberパートナーアプリでオンラインになります(あなたがドライバーです!)
  • 設定でアプリの通知を無効にする
  • アプリをバックグラウンドに移動し、ライドリクエストを待ちます
  • しばらくすると、ライドリクエストがアラートビューとしてポップアップ表示され、バックグラウンドでサウンドが再生されます

もちろん、silentリモート通知は、ユーザーが[設定]で通知を無効にしている場合でも、didReceiveRemoteNotification: fetchCompletionHandler:APIを使用してアプリで利用できます。しかし、アラートがどのようにポップアップされるか、それが私が見つけようとしていることです。

21
K.K

Uberには特別な権限があるか、ローカル通知を使用せずにこの動作を実現できるプライベートAPIを使用していると思います。 Uberがパートナーアプリでこれをどのように実装したかはわかりませんが、ホーム画面でアラートがどのように機能するかについて少し話すことができます。

SpringBoardは、iPhoneのアプリケーションランチャーであるSpringBoardアプリケーション(SpringBoard.app)を管理するシングルトンクラスです。 SpringBoardは、SpringBoard全体のアラートシステムに参加していないため、標準のUIAlertView/UIAlertControllerクラスを使用しません。 iOS 5が導入されました SBAlertItem SpringBoardでUIAlertViewsを表示するために使用されます(バッテリー通知アラート、Simロック解除アラートなど)。 Appleはロックとホーム画面のアラートにSBAlertItemを使用します。私は、Uberがこの回答にSBAlertItemを使用していると仮定して作業します。

SBAlertItemには保護されたivarがありますUIAlertView *_alertSheet。これが通常のUIAlertViewとして機能すると仮定すると、ニーズに合わせてこのアラートのプロパティを変更できるはずです。また、saurikのCydia Substrateプロジェクト、具体的には MobileSafety.mm を読んで、いくつかのユースケースを確認します。また、SpringBoardでSBAlertItemを使用する例を示す noweibogoodsleep も見つかりました。

SBUserNotificationAlertSBAlertItemのサブクラスも見つかりました。これには、標準のSBAlertItemよりもニーズに合うアラートのカスタマイズを容易にする方法が多いようです。

プライベートAPIにフックすることは、おそらくこの質問をするときに期待していたことではないことを理解しています。 Uberがどのように機能するかわからないため、ランタイムデバイスとジェイルブレイクされたデバイスを使用した個人的な経験からのみ回答を提供できます。

10
JAL

バイナリの静的分析の結果、PKPushRegistry(VOIP)、文書化されていないNSNotificationCenter呼び出し、またはSBAlertItemを使用していないことが明らかになりました。

それを見つけるのに少し時間がかかりましたが、実際にはアラートにCFUserNotificationを使用しています。クラスは、Macの場合は documented ですが、iOSの場合はプライベートです。

私はこれを行うことによって使用法を見つけました:

nm -u ~/Downloads/Payload/UberDriver.app/UberDriver | grep CFUserNotification

出力は次のとおりです。

_CFUserNotificationCancel
_CFUserNotificationCreate
_CFUserNotificationCreateRunLoopSource
_kCFUserNotificationAlertHeaderKey
_kCFUserNotificationAlertMessageKey
_kCFUserNotificationAlertTopMostKey
_kCFUserNotificationAlternateButtonTitleKey
_kCFUserNotificationDefaultButtonTitleKey
_kCFUserNotificationSoundURLKey

PKPushRegistryまたはSBAlertItemをgrepすると、どちらも結果を返しません。

このファイル をプロジェクトにインポートすることでクラスを使用できます。

[〜#〜]更新[〜#〜]

「動作中」のコードがありますが、アラートを表示せずにすぐにコールバック関数(responseFlagsを kCFUserNotificationCancelResponse に設定)を呼び出します。

Uberアプリと同じキーと呼び出しを使用しているので(以下のコードを上記のリストと比較してください)、何か特別なものが必要です。探し続けます。

#import "CFUserNotification.h"

@interface AppDelegate ()
@property (nonatomic) CFRunLoopSourceRef runLoopSource;
@property (nonatomic) CFUserNotificationRef notification;
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    SInt32 error;
    NSDictionary *keys = @{(__bridge NSString*)kCFUserNotificationAlertHeaderKey: @"Hello",
                           (__bridge NSString*)kCFUserNotificationAlertMessageKey: @"World",
                           (__bridge NSString*)kCFUserNotificationAlertTopMostKey: @YES,
                           (__bridge NSString*)kCFUserNotificationDefaultButtonTitleKey: @"asdf",
                           (__bridge NSString*)kCFUserNotificationAlternateButtonTitleKey: @"asdf",
                           };

    self.notification = CFUserNotificationCreate(NULL, 10, kCFUserNotificationPlainAlertLevel, &error, (__bridge CFDictionaryRef)keys);
    self.runLoopSource = CFUserNotificationCreateRunLoopSource(NULL, self.notification, NotificationCallback, 0);
    CFRunLoopAddSource(CFRunLoopGetMain(), self.runLoopSource, kCFRunLoopCommonModes);

    return YES;
}

void NotificationCallback(CFUserNotificationRef userNotification, CFOptionFlags responseFlags) {
    NSLog(@"got response: %lu", responseFlags);
}
8
Casey

あなたの質問は、物事をより明確にする「Uberパートナー」アプリに関する最も重要な部分を見逃していました。 「UberPartner」アプリはEnterpriseアプリであり、Appstoreのガイドラインに限定されません。

他の回答が示唆するような特別な許可はありませんでした。

Sound\Notificationの設定に関係なく、SBAlertItemを使用してアラートビューを表示することは可能ですが、最終目標がアプリストアに到達することである場合、残念ながら、アプリはプライベートAPIの使用を拒否されます。

4
Segev