Menampilkan spanduk pemberitahuan iOS stok saat aplikasi Anda terbuka dan di latar depan?

123

Ketika aplikasi Pesan iOS resmi Apple terbuka dan di latar depan, pesan baru dari kontak lain memicu stok, spanduk peringatan pemberitahuan iOS asli. Lihat gambar di bawah.

Apakah ini mungkin di aplikasi pihak ke-3 di App Store? Lokal dan / atau Pemberitahuan Push untuk aplikasi Anda saat aplikasi Anda terbuka dan di latar depan ?

Saat menguji aplikasi saya , pemberitahuan diterima tetapi tidak ada UI peringatan iOS yang ditampilkan .

Tetapi perilaku ini terlihat di aplikasi Pesan resmi Apple:

Pesan terbuka dan di latar depan.  Masih menunjukkan tanda pemberitahuan.

The Local dan Remote Pemberitahuan Panduan Pemrograman mengatakan:

Saat sistem operasi mengirimkan notifikasi lokal atau notifikasi jarak jauh dan aplikasi target tidak berjalan di latar depan , sistem operasi dapat menyajikan notifikasi kepada pengguna melalui peringatan , nomor lencana ikon, atau suara.

Jika aplikasi berjalan di latar depan saat notifikasi dikirimkan, delegasi aplikasi akan menerima notifikasi lokal atau jarak jauh.

Jadi ya, kami dapat menerima data notifikasi saat berada di latar depan. Tapi saya tidak melihat cara untuk menyajikan UI pemberitahuan pemberitahuan iOS asli .

-(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]
}

Apakah Message menggunakan API pribadi untuk menampilkan peringatan saat berada di latar depan?

Untuk tujuan pertanyaan ini, mohon jangan menyarankan pop-up alert "toast" pihak ketiga di github atau dll. Saya hanya tertarik jika ini dapat dilakukan dengan menggunakan stock, native iOS Lokal atau UI notifikasi Push Notification saat Anda aplikasi terbuka dan di latar depan .

pkamb
sumber

Jawaban:

152

iOS 10 menambahkan UNUserNotificationCenterDelegateprotokol untuk menangani notifikasi saat aplikasi Anda berada di latar depan.

The UNUserNotificationCenterDelegateProtokol mendefinisikan metode untuk menerima pemberitahuan dan untuk menangani tindakan. Saat aplikasi Anda berada di latar depan, notifikasi yang masuk dikirimkan ke objek delegasi Anda, bukan ditampilkan secara otomatis menggunakan antarmuka sistem.

Cepat:

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;

The UNNotificationPresentationOptions bendera memungkinkan Anda untuk menentukan UNNotificationPresentationOptionAlertuntuk menampilkan peringatan dengan menggunakan teks yang disediakan oleh pemberitahuan.

Ini adalah kuncinya karena memungkinkan Anda untuk menampilkan peringatan saat aplikasi Anda terbuka dan di latar depan , yang baru untuk iOS 10.


Kode sampel:

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)
    }
    
}
pkamb
sumber
4
Bisakah Anda memberikan contoh kode yang berfungsi di mana pemberitahuan latar depan yang masuk ditampilkan oleh sistem seolah-olah aplikasi di mana latar belakang?
azmeuk
1
@azmeuk Periksa jawaban saya ...
chengsam
8
Jangan lupa untuk menambahkan UNUserNotificationCenter.current().delegate = selfdalam application(_:willFinishLaunchingWithOptions:)atau application(_:didFinishLaunchingWithOptions:)metode
Deniss Fedotovs
3
Juga pastikan bahwa Anda tidak memiliki perangkat Anda dalam mode Jangan Ganggu jika tidak, pemberitahuan akan terlihat di Pusat Pemberitahuan, tetapi tidak akan disajikan di latar depan atas aplikasi Anda
Jadent
2
2 sen saya: jangan lewatkan: impor UserNotifications. !
ingconti
95

Untuk menampilkan pesan banner saat aplikasi berada di latar depan, gunakan metode berikut.

iOS 10+, Swift 3+ :

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.alert, .badge, .sound])
}
chengsam
sumber
1
Wow, di mana pun saya membaca orang mengatakan ini tidak mungkin. Saya sangat senang saya menemukan jawaban ini, ini berfungsi persis seperti yang saya harapkan! Saat aplikasi berjalan, pemberitahuan push sekarang ditampilkan persis seperti jika aplikasi berada di latar belakang. Terima kasih!
Torre Lasley
1
Kemana tujuan potongan ini? Di appDelegate, atau di tempat lain?
Yoav R.
@YoavR. AppDelegate
chengsam
Saya telah menggunakan kode yang sama. Tapi saya tidak tahu mengapa notifikasi tidak muncul saat aplikasi berada di latar depan.
Boominadha Prakash M
3
Chengsam Anda mungkin ingin memperbaiki ini: Ini tidak harus dimasukkan ke dalam file AppDelegate. Itu harus diletakkan untuk objek apa pun yang sesuai UNUserNotificationCenterDelegate. Karena itu, sebagian besar pengembang membuat AppDelegatepenyesuaian mereka UNUserNotificationCenterDelegate. @YoavR.
Madu
16

EDIT:

Peringatan latar depan sekarang dapat dilakukan di iOS 10! Silakan lihat jawaban ini .

Untuk iOS 9 dan yang lebih lama:

Tampaknya tidak mungkin untuk menampilkan peringatan pemberitahuan iOS stok saat aplikasi Anda terbuka dan di latar depan. Messages.app harus menggunakan API pribadi.

Sistem tidak menampilkan peringatan apa pun, memberi lencana ikon aplikasi, atau memutar suara apa pun saat aplikasi sudah paling depan. - Dokumen UILocalNotification

The UIApplicationDelegatemetode akan masih disebut, memungkinkan aplikasi Anda untuk merespon pemberitahuan lokal atau remote:

application:didReceiveLocalNotification:
application:didReceiveRemoteNotification:

Namun, UI spanduk pemberitahuan pemberitahuan bawaan iOS tidak akan ditampilkan seperti di Messages.app Apple, yang harus menggunakan API Pribadi.

Hal terbaik yang dapat Anda lakukan adalah menggulung spanduk peringatan Anda sendiri atau menggunakan kerangka kerja yang sudah ada:

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

Saya telah membuka radar untuk perilaku ini di sini: rdar://22313177

pkamb
sumber
3
Bagaimana whatsapp dan aplikasi terkenal lainnya melakukan itu?
Machado
@tardoandre punya screenshot? Saya berasumsi itu dengan meniru peringatan iOS saham dalam pandangan mereka sendiri.
pkamb
2
Anda harus menyertakan tautan untuk toastAlertFromGithubjika Anda menyarankan perpustakaan pihak ketiga ini untuk digunakan!
Ketan Parmar
14

Untuk menampilkan pemberitahuan saat Aplikasi terbuka, kita perlu menanganinya secara manual. Jadi yang saya lakukan di bawah ini adalah menangani notifikasi setelah diterima.

Tambahkan semua di bawah ini di AppDelegate.m

  1. Tangani panggilan untuk memberi tahu
  2. Buat tampilan, tambahkan AppIcon, pesan Notification dan tampilkan sebagai animasi
  3. Tambahkan Touch recogniser untuk menghapus jika disentuh atau dihapus dalam 5 detik dengan animasi.

Beri tahu saya jika ini adalah solusi yang baik. Bekerja dengan baik untuk saya tetapi saya tidak yakin apakah ini cara yang benar.

- (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) {


}];


}
Hafeez
sumber
3
Ini mungkin jawaban yang bagus untuk membuat peringatan Anda sendiri, tetapi tidak menampilkan Peringatan Stock iOS seperti yang ditunjukkan pada tangkapan layar.
pkamb
Hai, Terima kasih atas kata-kata baik Anda. Ya, tidak akan terlihat seperti itu (jika Anda berbicara tentang tampilan) karena yang ditunjukkan di atas pada gambar adalah notifikasi iOS dan yang melalui kode adalah custom. Kami mungkin bisa meniru tampilan dalam tampilan. Saya pikir WhatsApp memiliki tampilan yang rapi dengan latar belakang buram dll.
Hafeez
1
Seseorang memilih :(. Senang mendengar alasannya!?. Terima kasih.
Hafeez
2
Saya lakukan, karena kode dalam jawaban ini (bagus meskipun mungkin) tidak benar-benar menjawab pertanyaan yang diajukan: menunjukkan saham iOS roti spanduk di dalam aplikasi. Ada pertanyaan lain tentang SO di mana jawaban ini akan sangat bagus.
pkamb
1
Terima kasih pkamb untuk klarifikasi, masuk akal. Kurasa aku merindukan kata "saham".
Hafeez
10

Berikut adalah kode untuk menerima Pemberitahuan Push ketika aplikasi di latar depan atau di tahap terbuka, 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])
}

Jika Anda perlu mengakses userInfo dari kode penggunaan notifikasi: notification.request.content.userInfo

Metode userNotificationCenter(_:willPresent:withCompletionHandler:)ini hanya dipanggil jika Anda menambahkan ke payload atribut content-available:1. Muatan terakhir harus seperti ini:

{
     "aps":{
          "alert":"Testing.. (7)",
          "badge":1,"sound":"default"
     },
     "content-available":1
}
Kavin Kumar Arumugam
sumber
1
userNotificationCenter(_:willPresent:withCompletionHandler:)akan dipanggil saat aplikasi Anda berjalan di latar depan. Jadi TIDAK masalah dengan " konten-tersedia ", yang terkait dengan " pengambilan latar belakang ".
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);
}];

Saya dapat menampilkan pemberitahuan push saat aplikasi aktif untuk iOS 10.

  1. Pemberitahuan push dari server harus senyap .

  2. Saat menerima pemberitahuan jarak jauh dari server, Anda mengirim pemberitahuan lokal dan menyetel nilai untuk keyPath: shouldAlwaysAlertWhileAppIsForeground = True

Nguyen Loc
sumber
dalam 2 cepat - content.setValue("YES", forKeyPath: "shouldAlwaysAlertWhileAppIsForeground")benar? (dengan "Ya" dan tidak benar)
Yoav R.
Perhatian: Ini akan merusak aplikasi Anda di bawah iOS 12. Lihat diskusi di sini: stackoverflow.com/questions/41373321/…
Matt Bearson
5

Anda dapat menangani sendiri notifikasi tersebut dan menampilkan peringatan kustom. Aplikasi seperti Viber, Whatsapp, dan BisPhone menggunakan pendekatan ini.

Salah satu contoh lansiran ubahsuaian pihak ketiga adalah CRToast .

Coba jadwalkan pemberitahuan lokal saat aplikasi Anda berada di latar depan, dan Anda akan melihat bahwa tidak ada peringatan stok iOS yang ditampilkan:

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];
}
Mo Farhand
sumber
Terima kasih, tetapi hanya mencari jawaban menggunakan peringatan pemberitahuan stok iOS.
pkamb
1
ok tapi saya pikir Anda tidak bisa melakukannya, lihat juga Link ini: stackoverflow.com/questions/14872088/…
Mo Farhand
6
@matt Saya mencoba untuk menyimpan pertanyaan ini pada topik: menampilkan peringatan iOS stok di latar depan. Banyak pertanyaan "kerangka kerja peringatan roti panggang terbaik" lainnya. Jawaban dari "Tidak, Anda tidak dapat menampilkan lansiran iOS di latar depan" akan diterima dengan baik, dan saya akan menerima jawaban itu hingga hal ini dimungkinkan di versi iOS yang akan datang.
pkamb
4

Versi Swift 3

Ini menunjukkan peringatan saat aplikasi berada di latar depan.

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)")
    }
}

Implementasi ApplicationDelegate dari 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
}
Leslie Godwin
sumber
hanya untuk memastikan ... maksud Anda sejak iOS 10 Anda sekarang juga dapat menampilkan peringatan / spanduk / suara di latar depan seperti yang Anda lakukan di latar belakang?
Madu
Di mana saya bisa meletakkan bagian pengkodean di atas? di apakah acceptRemoteNotification?
pengguna1960169
@Leslie Godwin akan berfungsi untuk iOS 8.0 untuk menampilkan pemberitahuan di Latar Depan
Dilip Tiwari
2

Untuk menampilkan Pemberitahuan lokal, ini adalah opsi terbaik. perlu lebih sedikit kode untuk wright "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)
Mantosh Kumar
sumber
Ini BRYXBannerkerangka tampaknya tidak menggunakan saham iOS pemberitahuan banner.
pkamb
1

Jika target penerapan Anda> = iOS10, gunakan UNUserNotification seperti di bawah-

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
    {
        // Change this to your preferred presentation option
        completionHandler([.alert, .sound])
    }
Vishwas Singh
sumber