แสดงแบนเนอร์แจ้งเตือน iOS เมื่อแอปของคุณเปิดอยู่และอยู่เบื้องหน้า?


123

เมื่อแอป iOS Messages อย่างเป็นทางการของ Apple เปิดอยู่และอยู่เบื้องหน้าข้อความใหม่จากผู้ติดต่อรายอื่นจะทริกเกอร์สต็อกแบนเนอร์แจ้งเตือนดั้งเดิมของ iOS ดูภาพด้านล่าง

เป็นไปได้ไหมในแอพของบุคคลที่สามบน App Store การแจ้งเตือนในพื้นที่และ / หรือแบบพุชสำหรับแอปของคุณในขณะที่แอปของคุณเปิดอยู่และอยู่เบื้องหน้า ?

เมื่อทำการทดสอบapp ของฉัน , จะได้รับการแจ้งเตือน แต่ไม่มีการแจ้งเตือน iOS ของ UI ที่จะแสดง

แต่พฤติกรรมนี้มีให้เห็นในแอป Messages อย่างเป็นทางการของ Apple:

ข้อความเปิดอยู่และอยู่เบื้องหน้า  ยังคงแสดงการแจ้งเตือนการแจ้งเตือน

ท้องถิ่นและระยะไกลการเขียนโปรแกรมแจ้งคู่มือบอกว่า:

เมื่อระบบปฏิบัติการส่งการแจ้งเตือนในพื้นที่หรือการแจ้งเตือนระยะไกลและแอปเป้าหมายไม่ทำงานอยู่เบื้องหน้าก็สามารถนำเสนอการแจ้งเตือนแก่ผู้ใช้ผ่านการแจ้งเตือนหมายเลขป้ายไอคอนหรือเสียง

หากแอปกำลังทำงานอยู่เบื้องหน้าเมื่อมีการแจ้งเตือนผู้ร่วมประชุมแอปจะได้รับการแจ้งเตือนในพื้นที่หรือระยะไกล

ใช่เราสามารถรับข้อมูลการแจ้งเตือนในขณะที่อยู่เบื้องหน้าได้ แต่ผมไม่เห็นวิธีการที่จะนำเสนอพื้นเมือง iOS แจ้งเตือน UI

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 
{
    // I know we still receive the notification `userInfo` payload in the foreground.
    // This question is about displaying the stock iOS notification alert UI.

    // Yes, one *could* use a 3rd party toast alert framework. 
    [self use3rdPartyToastAlertFrameworkFromGithub]
}

จากนั้น Messages ใช้ API ส่วนตัวเพื่อแสดงการแจ้งเตือนขณะอยู่เบื้องหน้าหรือไม่

สำหรับจุดประสงค์ของคำถามนี้โปรดอย่าแนะนำการแจ้งเตือนป๊อปอัพ "toast" ของบุคคลที่สามบน github หรืออื่น ๆ ฉันสนใจเฉพาะในกรณีที่สามารถทำได้โดยใช้สต็อก, iOS Local ดั้งเดิมหรือ UI การแจ้งเตือนแบบพุชในขณะที่คุณ แอปพลิเคเปิดและในเบื้องหน้า

คำตอบ:


152

iOS 10เพิ่มUNUserNotificationCenterDelegateโปรโตคอลสำหรับจัดการการแจ้งเตือนในขณะที่แอปของคุณอยู่เบื้องหน้า

UNUserNotificationCenterDelegateโปรโตคอลกำหนดวิธีการในการรับการแจ้งเตือนและสำหรับการดำเนินการจัดการ เมื่อแอปของคุณอยู่เบื้องหน้าการแจ้งเตือนที่มาถึงจะถูกส่งไปยังออบเจ็กต์ผู้ร่วมประชุมของคุณแทนที่จะแสดงโดยอัตโนมัติโดยใช้อินเทอร์เฟซระบบ

สวิฟท์:

optional func userNotificationCenter(_ center: UNUserNotificationCenter, 
                     willPresent notification: UNNotification, 
      withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void)

Objective-C:

- (void)userNotificationCenter:(UNUserNotificationCenter *)center 
       willPresentNotification:(UNNotification *)notification 
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler;

UNNotificationPresentationOptionsธงอนุญาตให้คุณระบุUNNotificationPresentationOptionAlertเพื่อแสดงการแจ้งเตือนการใช้ข้อความที่ได้รับจากการแจ้งเตือน

นี่เป็นกุญแจสำคัญที่ช่วยให้คุณสามารถแสดงการแจ้งเตือนในขณะที่แอปของคุณเปิดอยู่และอยู่เบื้องหน้าซึ่งเป็นสิ่งใหม่สำหรับ iOS 10


โค้ดตัวอย่าง:

class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // Set UNUserNotificationCenterDelegate
        UNUserNotificationCenter.current().delegate = self
        
        return true
    }
    
}

// Conform to UNUserNotificationCenterDelegate
extension AppDelegate: UNUserNotificationCenterDelegate {
    
    func userNotificationCenter(_ center: UNUserNotificationCenter,
           willPresent notification: UNNotification,
           withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
    {
        completionHandler(.alert)
    }
    
}

4
คุณสามารถให้ตัวอย่างโค้ดที่ใช้งานได้ซึ่งระบบจะแสดงการแจ้งเตือนเบื้องหน้าที่เข้ามาเหมือนกับว่าแอปพลิเคชันที่อยู่เบื้องหลัง
azmeuk

1
@azmeuk Check my answer ...
chengsam

8
อย่าลืมที่จะเพิ่มUNUserNotificationCenter.current().delegate = selfใน application(_:willFinishLaunchingWithOptions:)หรือapplication(_:didFinishLaunchingWithOptions:)วิธีการ
Deniss Fedotovs

3
ตรวจสอบให้แน่ใจว่าคุณไม่มีอุปกรณ์ของคุณในโหมดห้ามรบกวนมิฉะนั้นการแจ้งเตือนจะปรากฏในศูนย์การแจ้งเตือน แต่จะไม่ปรากฏในเบื้องหน้าเหนือแอปพลิเคชันของคุณ
Jadent

2
2 เซ็นต์ของฉัน: อย่าพลาด: นำเข้า UserNotifications !
ingconti

95

สำหรับการแสดงข้อความแบนเนอร์ในขณะที่แอปอยู่เบื้องหน้าให้ใช้วิธีต่อไปนี้

iOS 10+, Swift 3+ :

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.alert, .badge, .sound])
}

1
ว้าวทุกที่ที่อ่านมีคนบอกว่าเป็นไปไม่ได้ ฉันดีใจมากที่พบคำตอบนี้มันได้ผลตามที่ฉันคาดไว้! เมื่อแอปทำงานอยู่ตอนนี้การแจ้งเตือนแบบพุชจะแสดงเหมือนกับที่แอปทำงานอยู่เบื้องหลัง ขอบคุณ!
Torre Lasley

1
ตัวอย่างข้อมูลนี้ไปที่ใด ใน appDelegate หรือที่อื่น?
Yoav R

@YoavR AppDelegate
chengsam

ฉันได้ใช้รหัสเดียวกัน แต่ฉันไม่รู้ว่าทำไมการแจ้งเตือนไม่แสดงเมื่อแอปอยู่เบื้องหน้า
Boominadha Prakash M

3
Chengsam คุณอาจต้องการแก้ไขสิ่งนี้: ไม่จำเป็นต้องใส่ในไฟล์AppDelegate. UNUserNotificationCenterDelegateมันจะต้องมีการวางวัตถุสิ่งที่สอดคล้องกับ มีที่กล่าวว่านักพัฒนาส่วนใหญ่ของพวกเขาให้เป็นไปตามAppDelegate UNUserNotificationCenterDelegate@YoavR
น้ำผึ้ง

16

แก้ไข:

การแจ้งเตือนเบื้องหน้าเป็นไปได้แล้วใน iOS 10! โปรดดูคำตอบนี้

สำหรับ iOS 9 และต่ำกว่า:

ดูเหมือนว่าจะเป็นไปไม่ได้ที่จะแสดงการแจ้งเตือนการแจ้งเตือนของ iOS เมื่อแอปของคุณเปิดอยู่และอยู่เบื้องหน้า Messages.app ต้องใช้ API ส่วนตัว

ระบบจะไม่แสดงการแจ้งเตือนติดป้ายไอคอนของแอปหรือเล่นเสียงใด ๆ เมื่อแอปอยู่ด้านหน้าสุดแล้ว - เอกสาร UILocalNotification

UIApplicationDelegateวิธีการจะยังคงถูกเรียกว่าช่วยให้แอปของคุณเพื่อตอบสนองต่อการแจ้งเตือนท้องถิ่นหรือระยะไกล:

application:didReceiveLocalNotification:
application:didReceiveRemoteNotification:

อย่างไรก็ตาม UI แบนเนอร์แจ้งเตือนการแจ้งเตือนของ iOS แบบสต็อกดั้งเดิมจะไม่แสดงเหมือนใน Messages.app ของ Apple ซึ่งต้องใช้ Private API

สิ่งที่ดีที่สุดที่คุณทำได้คือม้วนแบนเนอร์แจ้งเตือนของคุณเองหรือใช้กรอบที่มีอยู่:

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 
{    
    // Use a 3rd party toast alert framework to display a banner 
    [self toastAlertFromGithub]
}

ฉันได้เปิดเรดาร์สำหรับพฤติกรรมนี้ที่นี่: rdar://22313177


3
whatsapp และแอพชื่อดังอื่น ๆ ทำอย่างไร?
Machado

@tardoandre มีภาพหน้าจอไหม ฉันคิดว่าเป็นการเลียนแบบการแจ้งเตือน iOS หุ้นในมุมมองของพวกเขาเอง
pkamb

2
คุณควรใส่ลิงก์สำหรับtoastAlertFromGithubหากคุณกำลังแนะนำไลบรารีของบุคคลที่สามนี้ให้ใช้!
Ketan Parmar

14

หากต้องการแสดงการแจ้งเตือนในขณะที่แอปเปิดอยู่เราจำเป็นต้องจัดการด้วยตนเอง สิ่งที่ฉันกำลังทำด้านล่างคือจัดการการแจ้งเตือนเมื่อได้รับ

เพิ่มทั้งหมดด้านล่างใน AppDelegate.m

  1. จัดการโทรแจ้ง
  2. สร้างมุมมองเพิ่ม AppIcon ข้อความแจ้งเตือนและแสดงเป็นภาพเคลื่อนไหว
  3. เพิ่มตัวจดจำระบบสัมผัสเพื่อลบหากแตะหรือนำออกใน 5 วินาทีพร้อมภาพเคลื่อนไหว

แจ้งให้เราทราบหากนี่เป็นวิธีแก้ปัญหาที่ใช้ได้ ทำงานได้ดีสำหรับฉัน แต่ฉันไม่แน่ใจว่านี่เป็นวิธีที่ถูกต้องหรือไม่

- (void)application:(UIApplication *)applicationdidReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {


NSString *notifMessage = [[userInfo objectForKey:@"aps"] objectForKey:@"alert"];

//Define notifView as UIView in the header file
[_notifView removeFromSuperview]; //If already existing

_notifView = [[UIView alloc] initWithFrame:CGRectMake(0, -70, self.window.frame.size.width, 80)];
[_notifView setBackgroundColor:[UIColor blackColor]];

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10,15,30,30)];
imageView.image = [UIImage imageNamed:@"AppLogo.png"];

UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 15, self.window.frame.size.width - 100 , 30)];
myLabel.font = [UIFont fontWithName:@"Helvetica" size:10.0];
myLabel.text = notifMessage;

[myLabel setTextColor:[UIColor whiteColor]];
[myLabel setNumberOfLines:0];

[_notifView setAlpha:0.95];

//The Icon
[_notifView addSubview:imageView];

//The Text
[_notifView addSubview:myLabel];

//The View
[self.window addSubview:_notifView];

UITapGestureRecognizer *tapToDismissNotif = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                    action:@selector(dismissNotifFromScreen)];
tapToDismissNotif.numberOfTapsRequired = 1;
tapToDismissNotif.numberOfTouchesRequired = 1;

[_notifView addGestureRecognizer:tapToDismissNotif];


[UIView animateWithDuration:1.0 delay:.1 usingSpringWithDamping:0.5 initialSpringVelocity:0.1 options:UIViewAnimationOptionCurveEaseIn animations:^{

    [_notifView setFrame:CGRectMake(0, 0, self.window.frame.size.width, 60)];

} completion:^(BOOL finished) {


}];


//Remove from top view after 5 seconds
[self performSelector:@selector(dismissNotifFromScreen) withObject:nil afterDelay:5.0];


return;


}

//If the user touches the view or to remove from view after 5 seconds
- (void)dismissNotifFromScreen{

[UIView animateWithDuration:1.0 delay:.1 usingSpringWithDamping:0.5 initialSpringVelocity:0.1 options:UIViewAnimationOptionCurveEaseIn animations:^{

    [_notifView setFrame:CGRectMake(0, -70, self.window.frame.size.width, 60)];

} completion:^(BOOL finished) {


}];


}

3
นี่อาจเป็นคำตอบที่ดีสำหรับการสร้างการแจ้งเตือนของคุณเอง แต่จะไม่แสดงการแจ้งเตือนStock iOS ตามที่แสดงในภาพหน้าจอ
pkamb

สวัสดีขอบคุณสำหรับคำพูดของคุณ ใช่มันจะไม่เป็นแบบนั้น (ถ้าคุณกำลังพูดถึงลักษณะที่ปรากฏ) เนื่องจากที่แสดงด้านบนในภาพคือการแจ้งเตือนของ iOS และการแจ้งเตือนผ่านรหัสเป็นแบบกำหนดเอง เราสามารถจำลองรูปลักษณ์ในมุมมองได้ ฉันคิดว่า WhatsApp มีรูปลักษณ์ที่ดูเรียบร้อยพร้อมพื้นหลังเบลอ ฯลฯ
Hafeez

1
มีคนโหวตลง :( จะได้ยินทำไม!? ขอบคุณ
Hafeez

2
ฉันไม่ได้เป็นรหัสในคำตอบนี้ (ดีแม้ว่ามันอาจจะ) ไม่ได้โดดตอบคำถามที่ถาม: แสดงหุ้น iOS ของขนมปังแบนเนอร์ภายใน app มีคำถามอื่น ๆ เกี่ยวกับ SO ซึ่งคำตอบนี้จะดีมาก
pkamb

1
ขอบคุณ pkamb สำหรับการชี้แจงมีเหตุผล ฉันพลาดคำว่า "หุ้น" ที่ฉันเดา
Hafeez

10

นี่คือรหัสสำหรับรับการแจ้งเตือนแบบพุชเมื่อแอปอยู่เบื้องหน้าหรือในพื้นที่เปิด iOS 10 และ Swift 2.3

@available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void)
{
     completionHandler([UNNotificationPresentationOptions.Alert,UNNotificationPresentationOptions.Sound,UNNotificationPresentationOptions.Badge])
}

หากคุณต้องการเข้าถึง userInfo ของรหัสการแจ้งเตือนให้ใช้: notification.request.content.userInfo

วิธีการที่เรียกว่าถ้าคุณเพิ่มน้ำหนักบรรทุกแอตทริบิวต์userNotificationCenter(_:willPresent:withCompletionHandler:) content-available:1น้ำหนักบรรทุกขั้นสุดท้ายควรเป็นดังนี้:

{
     "aps":{
          "alert":"Testing.. (7)",
          "badge":1,"sound":"default"
     },
     "content-available":1
}

1
userNotificationCenter(_:willPresent:withCompletionHandler:)จะถูกเรียกเมื่อแอปของคุณทำงานอยู่เบื้องหน้า ดังนั้นจึงไม่สำคัญกับ " เนื้อหาที่มี " ซึ่งเกี่ยวข้องกับ "การดึงข้อมูลพื้นหลัง "
DawnSong

9
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.body = body;
content.userInfo = userInfo;
content.sound = [UNNotificationSound defaultSound];
[content setValue:@(YES) forKeyPath:@"shouldAlwaysAlertWhileAppIsForeground"];

UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"Notif" content:content trigger:nil];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
    DLog(@"Error:%@", error);
}];

ฉันสามารถแสดงการแจ้งเตือนแบบพุชเมื่อแอปเปิดใช้งานสำหรับiOS 10

  1. การแจ้งเตือนผลักดันจากเซิร์ฟเวอร์ควรจะเงียบ

  2. เมื่อได้รับการแจ้งเตือนระยะไกลจากเซิร์ฟเวอร์คุณจะส่งการแจ้งเตือนภายในเครื่องและตั้งค่าสำหรับkeyPath: shouldAlwaysAlertWhileAppIsForeground = True


ใน swift 2 - มันคือcontent.setValue("YES", forKeyPath: "shouldAlwaysAlertWhileAppIsForeground")ใช่มั้ย? (มี "ใช่" และไม่เป็นความจริง)
Yoav R.

ข้อควรระวัง: แอปของคุณจะขัดข้องใน iOS 12 ดูการสนทนาที่นี่: stackoverflow.com/questions/41373321/…
Matt Bearson

5

คุณสามารถจัดการการแจ้งเตือนด้วยตัวเองและแสดงการแจ้งเตือนที่กำหนดเอง แอปเช่น Viber, Whatsapp และ BisPhone ใช้แนวทางนี้

ตัวอย่างหนึ่งของการแจ้งเตือนที่กำหนดเองของบุคคลที่ 3 เป็นCRToast

ลองตั้งเวลาการแจ้งเตือนในเครื่องในขณะที่แอปของคุณอยู่เบื้องหน้าและคุณจะเห็นว่าไม่มีการแจ้งเตือน iOS ในสต็อก:

if (application.applicationState == UIApplicationStateActive ) {
     UILocalNotification *localNotification = [[UILocalNotification alloc] init];
    localNotification.userInfo = userInfo;
    localNotification.soundName = UILocalNotificationDefaultSoundName;
    localNotification.alertBody = message;
    localNotification.fireDate = [NSDate date];
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}

ขอบคุณ แต่เพียงแค่มองหาคำตอบโดยใช้การแจ้งเตือนการแจ้งเตือนหุ้น iOS
pkamb

1
โอเค แต่ฉันคิดว่าคุณทำไม่ได้ลองดูที่ลิงค์นี้: stackoverflow.com/questions/14872088/…
Mo Farhand

6
@matt ฉันพยายามที่จะเก็บคำถามนี้ไว้ในหัวข้อนี้: แสดงการแจ้งเตือนสต็อค iOS ในเบื้องหน้า คำถาม "กรอบการแจ้งเตือนขนมปังที่ดีที่สุด" อื่น ๆ อีกมากมาย คำตอบของ "ไม่คุณไม่สามารถแสดงการแจ้งเตือน iOS ในเบื้องหน้า" เป็นสิ่งที่ยอมรับได้อย่างสมบูรณ์และฉันจะยอมรับคำตอบนั้นจนกว่าจะเป็นไปได้ใน iOS เวอร์ชันอนาคต
pkamb

4

เวอร์ชัน Swift 3

แสดงการแจ้งเตือนเมื่อแอปพลิเคชันอยู่เบื้องหน้า

if #available(iOS 10.0, *)
{
    // need to setup the global notification delegate somewhere when your app starts
    //
    UNUserNotificationCenter.current().delegate = applicationDelegate

    // to show a message
    //
    let content = UNMutableNotificationContent()
    content.body = "MESSAGE"

    let request = UNNotificationRequest(identifier: "fred", content: content, trigger: nil)
    UNUserNotificationCenter.current().add(request)
    {
       error in // called when message has been sent

       debugPrint("Error: \(error)")
    }
}

การนำ ApplicationDelegate ไปใช้งาน UNUserNotificationCenterDelegate

@available(iOS 10.0, *)
public func userNotificationCenter(_ center : UNUserNotificationCenter, willPresent notification : UNNotification, withCompletionHandler completionHandler : @escaping (UNNotificationPresentationOptions) -> Void)
{
    completionHandler([.alert]) // only-always show the alert
}

เพื่อให้แน่ใจว่า ... คุณหมายถึงตั้งแต่ iOS 10 ตอนนี้คุณสามารถแสดงการแจ้งเตือน / แบนเนอร์ / เสียงในเบื้องหน้าได้เช่นเดียวกับที่คุณทำในพื้นหลัง?
น้ำผึ้ง

ฉันจะใส่ส่วนการเข้ารหัสข้างต้นได้ที่ไหน ในไม่ได้รับการแจ้งเตือนระยะไกล?
user1960169

@Leslie Godwin จะใช้งานได้กับ ios 8.0 สำหรับการแสดงการแจ้งเตือนใน Foreground
Dilip Tiwari

2

หากต้องการแสดงการแจ้งเตือนในพื้นที่นี่เป็นตัวเลือกที่ดีที่สุด ต้องการโค้ดน้อยลงเพื่อเขียน "BRYXBanner" https://cocoapods.org/pods/BRYXBanner

let banner = Banner(title: "title", subtitle: "subtitle", image: UIImage(named: "addContact"), backgroundColor: UIColor(red:137.0/255.0, green:172.0/255.0, blue:2.0/255.0, alpha:1.000))
    banner.dismissesOnTap = true
    banner.show(duration: 1.0)

BRYXBannerดูเหมือนว่าเฟรมเวิร์กนี้จะไม่ใช้แบนเนอร์แจ้งเตือนหุ้น iOS
pkamb

1

หากเป้าหมายการปรับใช้ของคุณ> = iOS10 ให้ใช้ UNUserNotification ดังต่อไปนี้ -

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
    {
        // Change this to your preferred presentation option
        completionHandler([.alert, .sound])
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.