2015-07-02 10 views
14

Tôi hiện đang làm việc để triển khai thông báo GCM vào ứng dụng của mình.GcmListenerService.onMessageReceived() không được gọi là

Sự cố tôi gặp phải là phương pháp onMessageReceived() từ triển khai GcmListenerService của tôi không được gọi. Tôi nhận được dữ liệu từ máy chủ GCM tốt, vì nó tự động tạo thông báo (Tôi muốn thay thế thông báo này bằng thông báo của riêng tôi bằng phương thức onMessageReceived()) nhưng sau đó không có cuộc gọi nhật ký nào được in trong nhật ký.

JSON được gửi từ máy chủ đến máy chủ GCM

{ 
    "notification" : { 
     "title" : "Title", 
     "text" : "Message", 
     "icon" : "@drawable\/ic_notification", 
     "click_action" : "OPEN_MAIN_ACTIVITY" 
    }, 
    "registration_ids":[ 
     "xxxx", "xxxx", "xxxx", "etc" 
    ] 
} 

AndroidManifest.xml (GCM chỉ là một phần)

<!-- GCM START --> 
    <receiver 
     android:name="com.google.android.gms.gcm.GcmReceiver" 
     android:exported="true" 
     android:permission="com.google.android.c2dm.permission.SEND" > 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
      <category android:name="com.my.package" /> 
     </intent-filter> 
    </receiver> 

    <service 
     android:name=".Services.ListenerService" 
     android:exported="false" > 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
     </intent-filter> 
    </service> 

    <service 
     android:name=".Services.IDListenerService" 
     android:exported="false"> 
     <intent-filter> 
      <action android:name="com.google.android.gms.iid.InstanceID"/> 
     </intent-filter> 
    </service> 
    <!-- GCM END --> 

GcmListenerService (chỉ cần một bản in nhanh chóng để xem nếu nó gọi là tất cả)

public class ListenerService extends GcmListenerService { 

    private static final String TAG = "MyGcmListenerService"; 

    @Override 
    public void onMessageReceived(String from, Bundle data) { 
     String message = data.getString("title"); 
     Log.d(TAG, "From: " + from); 
     Log.d(TAG, "Message: " + message); 
    } 
} 

Không chắc chắn nếu phương thức yêu cầu mã thông báo có liên quan, nhưng tôi có thể đăng nó nếu cần.

Nếu phần nào của câu hỏi không rõ ràng, hãy cho tôi biết, tôi không phải là giải thích tốt nhất.

+0

Bạn đã đăng ký khách hàng của mình chưa? – Gordak

+0

Tôi nhận được mã thông báo và thậm chí là thông báo (tôi nghĩ GCM tự động tạo chúng hoặc cái gì đó), nếu đó là ý của bạn? – Dan

+0

Vâng, nếu bạn đã thiết lập ứng dụng của mình theo https://developers.google.com/cloud-messaging/android/client, bạn sẽ ổn. Đừng quên gửi mã thông báo gcm của bạn đến ứng dụng máy chủ của bạn (Tôi không thấy mã đăng ký tại đây). – Gordak

Trả lời

12

Như đã giải thích trong this Github vấn đề mà chính là vấn đề của bạn:

Từ https://developers.google.com/cloud-messaging/server#notifications_and_data_messages "GCM sẽ hiển thị một phần thông báo thay mặt cho ứng dụng của khách hàng Khi dữ liệu tùy chọn được cung cấp, nó sẽ được gửi đến ứng dụng khách sau khi người dùng nhấp vào thông báo và mở ứng dụng máy khách [...] Trên Android, tải trọng dữ liệu có thể được lấy trong Intent được sử dụng để khởi động hoạt động của bạn. . "

Vì vậy, dữ liệu được thông qua vào mục đích sử dụng để khởi động hoạt động, sau khi người dùng chạm vào thông báo này có nghĩa là bạn cần phải làm như sau:

  • Thêm click_action đến khóa thông báo bạn gửi từ máy chủ: ví dụ

    send_queue.append({'to': REGISTRATION_ID, 
           'message_id': random_id(), 
           "notification" : { 
            "body" : "Hello from Server! What is going on? Seems to work!!!", 
            "title" : "Hello from Server!", 
            "icon" : "@drawable/ic_school_white_48dp", 
            "sound": "default", 
            "color": "#03A9F4", 
            "click_action": "OPEN_MAIN_ACTIVITY" 
           }, 
           'data': { 'message': "Hello" }}) 
    

Xem tài liệu tham khảo để thông báo tải trọng tại địa chỉ: https://developers.google.com/cloud-messaging/server-ref#notification-payload-support

  • Trong AndroidManifest.xml thêm một bộ lọc ý định hoạt động bạn muốn được mở ra khi người dùng nhấp vào thông báo, với cùng tên hành động bạn đã sử dụng trên khóa "click_action" ở phía máy chủ, ví dụ:

    <activity 
        android:name=".ui.MainActivity" 
        android:label="@string/title_activity_main" > 
        <intent-filter> 
         <action android:name="OPEN_MAIN_ACTIVITY" /> 
         <category android:name="android.intent.category.DEFAULT" /> 
        </intent-filter> 
    </activity> 
    
  • Lấy dữ liệu từ mục đích trên onCreate của bạn() phương pháp hoặc trên onNewIntent() nếu bạn đã thiết lập các launchMode để singleTop cho hoạt động bạn muốn khởi động khi thông báo được nhấn vào, ví dụ như:

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
    
        Intent intent = getIntent(); 
    
        if (intent.hasExtra(Constants.KEY_MESSAGE_TXT)) { 
         String message = intent.getStringExtra(Constants.KEY_MESSAGE_TXT); 
         Log.d(TAG, message); 
        } 
    } 
    

tôi đã thử nghiệm này và có thể xác nhận rằng nó hoạt động. (sử dụng kết nối XMPP)

+0

Cố định vấn đề của tôi, tôi đã gặp vấn đề Github trước đó, nhưng không đọc nó rõ ràng một cách rõ ràng, cảm ơn vì đã làm rõ. Có cách nào để cập nhật thông báo phía máy khách không? Như trong không bị spam bởi 4 thông báo giống hệt nhau, nhưng chỉ là một? Sortof như thế này: http://imgur.com/a/DlJV0 – Dan

+2

@Dan Nếu bạn sử dụng phím thông báo, bạn có thể đặt khóa "thẻ" cho mỗi thông báo giống như thông báo trước và thông báo mới với cùng một thẻ sẽ thay thế thẻ trước đó trong trung tâm thông báo. Xem mô tả về khóa "thẻ" [tại đây] (https://developers.google.com/cloud-messaging/server-ref#notification-payload-support). Ngoài ra, hãy xem ["collapse_key"] (https://developers.google.com/cloud-messaging/server-ref#table1) và delay_while_idle, rất hữu ích khi cho GCM biết điều gì xảy ra trong các trường hợp khi thông báo không thể giao ngay và bạn thử lại. – bitek

+1

Nếu bạn không sử dụng phím thông báo, nhưng phím "dữ liệu", bạn cần tự mình loại trừ bằng cách theo dõi các thông báo được hiển thị trước đó. – bitek

3

Để nhận thư trong onMessageReceived, bạn cần phải xác định trường "dữ liệu" cấp cao nhất trong đối tượng thư của bạn. Trường thông báo được xử lý tự động và tạo thông báo, onMessageReceived không được chuyển bất kỳ dữ liệu nào trong trường thông báo.

Cập nhật đối tượng thông điệp của bạn để bao gồm một trường dữ liệu và onMessageReceived nên được gọi là:

 
{ 
    "notification" : { 
     "title" : "Title", 
     "text" : "Message", 
     "icon" : "@drawable\/ic_notification", 
     "click_action" : "OPEN_MAIN_ACTIVITY" 
    }, 
    "data": { 
     "some_key": "some_value" 
    }, 
    "registration_ids":[ 
     "xxxx", "xxxx", "xxxx", "etc" 
    ] 
} 
+2

Tôi sẽ cố gắng khi tôi về nhà tối nay. Có cách nào để làm cho trường thông báo không tự động tạo thông báo trên Android để tôi có thể sử dụng triển khai của riêng mình không? Tốt hơn là không xóa toàn bộ trường thông báo vì tôi sử dụng nó trong iOS. – Dan

+0

Tôi không thể nghĩ ra cách tốt để làm điều này. Bạn có thể thử rời khỏi lĩnh vực biểu tượng kể từ khi được yêu cầu trên Android nhưng không phải trên iOS. Vì vậy, tôi cho rằng nó sẽ bị bỏ qua trên Android nhưng bạn vẫn sẽ nhận được phần dữ liệu trong onMessageReceived. –

+1

Xóa hoàn toàn khối "thông báo" đã thực hiện thủ thuật và thực hiện cuộc gọi điện thoại onMessageReceived. Đó không phải là cách tôi muốn nhưng tôi sẽ tìm cách giải quyết nó. Bạn có biết liệu có thể thu gọn nhiều thông báo thành một để người dùng không bị spam với thông báo không? Xem http://imgur.com/a/DlJV0 để biết ví dụ hình ảnh (sắp xếp) – Dan

4

GcmListenerService.onMessageReceived() sẽ không được gọi nếu thông báo hạ lưu (json) chứa thông báo.

+2

Để xây dựng điểm @ Zephyr, có [hai loại tải trọng trong một tin nhắn GCM] (https://developers.google.com/cloud-messaging/concept-options): Thông báo Thông báo và Thông báo Dữ liệu. Các thông báo thông báo không gọi phương thức 'onMessageReceived' nếu ứng dụng không hoạt động. Chúng chỉ khiến thông báo được hiển thị trong khay thông báo. Tin nhắn dữ liệu sẽ khiến 'onMessageReceived' được gọi là mọi lúc, bất kể trạng thái của ứng dụng. Xem chi tiết [tại đây] (http://stackoverflow.com/a/35368530/936761) – Shiprack

0

onMessageReceived chỉ được gọi là dịch vụ mát-xa đẩy "chỉ dữ liệu".

Các vấn đề liên quan