2016年2月28日日曜日

conent_available を true にすると foreground のときしか onMessageReceived() が呼ばれない

GcmListenerService では、特定の条件の場合 onMessageReceived() を呼ばずに自分で Notification を出すような処理になっています。

この条件が Google Play Services のバージョンによって異なり、7.8.0 から 8.4.0 に変更したときにはまったので調べた結果をまとめておきます。
(調べたのは 7.8.0 と 8.4.0 で、この間の他のバージョンは調べていません。)

7.8.0



7.8.0 では、送信する JSON に "notification" payload があり、その中の "icon" の値が null じゃない場合は onMessageReceived() が呼ばれずに GcmListenerService が Notification を出します。このときの Notification には "notification" payload で指定された "title" や "body" が使われます。"title" の値が空のときはアプリ名が利用されます。

notification payload の形式については https://developers.google.com/cloud-messaging/http-server-ref#notification-payload-support 参照

つまり
"notification" の "icon" == null → onMessageReceived()
"notification" の "icon" != null → GcmListenerService が Notification 発行


8.4.0



8.4.0 では条件が大きく変わります。
"content_available" が false (指定がない場合も false)かつ "notification" の "icon" == null の場合 onMessageReceived() が呼ばれます。そうでない場合、アプリが foreground にあれば onMessageReceived() が呼ばれ、background なら GcmListenerService が Notification を出します。

つまり
"content_available" == false && "notification" の "icon" == null → onMessageReceived()
"content_available" == true || "notification" の "icon" != null →
  アプリが foreground → onMessageReceived()
  アプリが background → GcmListenerService が Notification 発行

"content_available" を true にしていると、7.8.0 から 8.4.0 に変更したときに今まで background でも onMessageReceived() が呼ばれていたのに呼ばれなくなります。全然ドキュメントにも書いてないしはまりました。。。


7.8.0 のコード

GcmListenerService
  1. private void zzt(Bundle var1) {  
  2.     var1.remove("message_type");  
  3.     var1.remove("android.support.content.wakelockid");  
  4.     if(zza.zzu(var1)) {  
  5.         zza.zzay(this).zzv(var1); // "notification" のデータを使って Notification を発行している  
  6.     } else {  
  7.         String var2 = var1.getString("from");  
  8.         var1.remove("from");  
  9.         this.onMessageReceived(var2, var1);  
  10.     }  
  11. }  
zza
  1. static boolean zzu(Bundle var0) {  
  2.     return zzb(var0, "gcm.n.icon") != null;  
  3. }   
"gcm.n.icon" は "notification" payload の "icon" に対応している。


8.4.0 のコード

GcmListenerService
  1. private void zzq(Intent var1) {  
  2.     Bundle var2 = var1.getExtras();  
  3.     var2.remove("message_type");  
  4.     var2.remove("android.support.content.wakelockid");  
  5.     if(zzb.zzy(var2)) {  
  6.         if(!zzb.zzaI(this)) {  // 同じプロセスの Activity が foreground かチェック、foreground じゃない場合 if の中に入る  
  7.             zzb.zzc(thisthis.getClass()).zzA(var2); // "notification" のデータを使って Notification を発行している  
  8.             return;  
  9.         }  
  10.   
  11.         if(zzx(var1.getExtras())) {  
  12.             zza.zzh(this, var1);  
  13.         }  
  14.   
  15.         zzb.zzz(var2);  
  16.     }  
  17.   
  18.     String var3 = var2.getString("from");  
  19.     var2.remove("from");  
  20.     zzw(var2);  
  21.     this.onMessageReceived(var3, var2);  
  22. }  
zzb
  1. static boolean zzy(Bundle var0) {  
  2.     return "1".equals(zze(var0, "gcm.n.e")) || zze(var0, "gcm.n.icon") != null;  
  3. }  
"gcm.n.e" は "content_available" に対応している。 "gcm.n.icon" は "notification" payload の "icon" に対応している。

zzb
  1. static boolean zzaI(Context var0) {  
  2.     KeyguardManager var1 = (KeyguardManager)var0.getSystemService("keyguard");  
  3.     if(var1.inKeyguardRestrictedInputMode()) {  
  4.         return false;  
  5.     } else {  
  6.         int var2 = Process.myPid();  
  7.         ActivityManager var3 = (ActivityManager)var0.getSystemService("activity");  
  8.         List var4 = var3.getRunningAppProcesses();  
  9.         if(var4 != null) {  
  10.             Iterator var5 = var4.iterator();  
  11.   
  12.             while(var5.hasNext()) {  
  13.                 RunningAppProcessInfo var6 = (RunningAppProcessInfo)var5.next();  
  14.                 if(var6.pid == var2) {  
  15.                     return var6.importance == 100;  
  16.                 }  
  17.             }  
  18.         }  
  19.   
  20.         return false;  
  21.     }  
  22. }  



0 件のコメント:

コメントを投稿