在android中未收到推送通知

Posted

技术标签:

【中文标题】在android中未收到推送通知【英文标题】:Push Notification not Received in android 【发布时间】:2014-02-27 11:59:14 【问题描述】:

我是推送通知的新手,我正在尝试向已注册到 GCM 服务的特定设备发送推送通知。我根据this example 实现了我的应用程序 并在我的程序中进行了相应的修改。但是,我无法在设备上接收推送通知。

这是我的代码:

package com.markattendence.activites;

import static com.markattendence.activites.CommonUtilities.DISPLAY_MESSAGE_ACTION;
import static com.markattendence.activites.CommonUtilities.EXTRA_MESSAGE;
import static com.markattendence.activites.CommonUtilities.SENDER_ID;

import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gcm.GCMRegistrar;
import com.markattendence.activites.MainActivity.YourAsyncTaskLogin;
import com.markattendence.markattendence.R;

public class NotificationActivity extends Activity 
// label to display gcm messages
TextView lblMessage;

// Asyntask
AsyncTask<Void, Void, Void> mRegisterTask;

// Alert dialog manager
AlertDialogManager alert = new AlertDialogManager();

// Connection detector
ConnectionDetector cd;

private String userFName;

private String latitude;

private String longitude;
private static String KEY_SUCCESS = "success";
private static String KEY_ERROR = "error";
private static String KEY_ERROR_MSG = "error_msg";
private static String KEY_UID = "uid";
private static String KEY_FNAME = "fname";
private static String KEY_EMAIL = "email";
private static String KEY_LNAME = "lname";

UserFunctions userFunction;
private JSONObject json;

public static String name;
public static String email;

SharedPreferences prefs;
public static final String MyPREFERENCES = "MyPrefs";

@Override
public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_notification);

    cd = new ConnectionDetector(getApplicationContext());
    prefs = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);

    if (prefs.contains("message")) 
        lblMessage.setText(prefs.getString("message", ""));

    

    // Check if Internet present
    if (!cd.isConnectingToInternet()) 
        // Internet Connection is not present
        alert.showAlertDialog(NotificationActivity.this,
                "Internet Connection Error",
                "Please connect to working Internet connection", false);
        // stop executing code by return
        return;
    

    // Getting name, email from intent
    Intent i = getIntent();

    name = i.getStringExtra("uFName");
    userFName = i.getStringExtra("uFName");
    email = i.getStringExtra("email");
    latitude = i.getStringExtra("latitude");
    longitude = i.getStringExtra("longitude");

    // Make sure the device has the proper dependencies.
    GCMRegistrar.checkDevice(this);

    // Make sure the manifest was properly set - comment out this line
    // while developing the app, then uncomment it when it's ready.
    GCMRegistrar.checkManifest(this);

    lblMessage = (TextView) findViewById(R.id.lblMessage);

    registerReceiver(mHandleMessageReceiver, new IntentFilter(
            DISPLAY_MESSAGE_ACTION));

    // Get GCM registration id
    final String regId = GCMRegistrar.getRegistrationId(this);

    // Check if regid already presents
    if (regId.equals("")) 
        // Registration is not present, register now with GCM
        GCMRegistrar.register(this, SENDER_ID);
     else 
        // Device is already registered on GCM
        if (GCMRegistrar.isRegisteredOnServer(this)) 
            // Skips registration.
            Toast.makeText(getApplicationContext(),
                    "Already registered with GCM", Toast.LENGTH_LONG)
                    .show();
         else 
            // Try to register again, but not in the UI thread.
            // It's also necessary to cancel the thread onDestroy(),
            // hence the use of AsyncTask instead of a raw thread.
            final Context context = this;
            mRegisterTask = new AsyncTask<Void, Void, Void>() 

                @Override
                protected Void doInBackground(Void... params) 
                    // Register on our server
                    // On server creates a new user
                    ServerUtilities.register(context, name, email, regId);
                    return null;
                

                @Override
                protected void onPostExecute(Void result) 
                    mRegisterTask = null;
                

            ;
            mRegisterTask.execute(null, null, null);
        
    
    if(name != null)
    userFunction = new UserFunctions();
    new YourAsyncTaskLogin().execute();
    


/**
 * Receiving push messages
 * */
private final WakefulBroadcastReceiver mHandleMessageReceiver = new WakefulBroadcastReceiver() 
    @Override
    public void onReceive(Context context, Intent intent) 
        ComponentName comp = new ComponentName(context.getPackageName(),
                GCMIntentService.class.getName());
        // Start the service, keeping the device awake while it is launching.
        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);

        String newMessage = intent.getExtras().getString(EXTRA_MESSAGE);
        // Waking up mobile if it is sleeping
        WakeLocker.acquire(getApplicationContext());

        /**
         * Take appropriate action on this message depending upon your app
         * requirement For now i am just displaying it on the screen
         * */

        // Showing received message
        lblMessage.append(newMessage + "\n");
        Toast.makeText(getApplicationContext(),
                "New Message: asd" + newMessage, Toast.LENGTH_LONG).show();

        prefs = context.getSharedPreferences(MyPREFERENCES,
                Context.MODE_PRIVATE);
        Editor editor = prefs.edit();
        editor.putString("message", lblMessage.getText().toString());
        editor.commit();
        // Releasing wake lock
        WakeLocker.release();
    
;

@Override
protected void onDestroy() 
    if (mRegisterTask != null) 
        mRegisterTask.cancel(true);
    
    try 
        unregisterReceiver(mHandleMessageReceiver);
        GCMRegistrar.onDestroy(this);
     catch (Exception e) 
        Log.e("UnRegister Receiver Error", "> " + e.getMessage());
    
    super.onDestroy();


class YourAsyncTaskLogin extends AsyncTask<Void, Void, Void> 

    private ProgressDialog _ProgressDialog;
    private String userId;

    @Override
    protected void onPreExecute() 
        // show your dialog here

        _ProgressDialog = ProgressDialog.show(NotificationActivity.this,
                "", "Loading", true);

    

    @Override
    protected Void doInBackground(Void... params) 

        try 

            json = userFunction.sendMessage(userFName,
                    " has marked attendence of ", "CheckIN", latitude,
                    longitude);
            /*
             * HttpClient Client = new DefaultHttpClient(); String
             * SetServerString = "";
             * 
             * // Create Request to server and get response
             * 
             * HttpGet httpget = new HttpGet(
             * "http://wibman.com/pnt/send_message.php?message=" + name +
             * "checked in&Latitude=" + latitude + "&Longitude=" +
             * longitude); ResponseHandler<String> responseHandler = new
             * BasicResponseHandler(); SetServerString =
             * Client.execute(httpget, responseHandler);
             */

            // Show response on activity

            // content.setText(SetServerString);
         catch (Exception ex) 
            ex.printStackTrace();
            // content.setText("Fail!");
        
        return null;
    

    protected void onPostExecute(Void result) 

        try 
            Log.e("aaaaaaaaaaaaaaaaaaaaaaaaaaa",
                    json.getString(KEY_SUCCESS));
            if (json.getString(KEY_SUCCESS) != null) 
                // loginErrorMsg.setText("");
                String res = json.getString(KEY_SUCCESS);

                if (Integer.parseInt(res) == 1) 
                    /*userId = json.getString(KEY_UID);
                    userFName = json.getString(KEY_FNAME);

                    userFName.replace("\"", "");

                    userId.replace("\"", "");

                    Log.e("uid=aaa", userId);
                    Log.e("nameuser", userFName);*/

                    Intent dashboard = new Intent(getApplicationContext(),
                            MainActivity.class);

                    // Close all views before launching
                    // Dashboard
                    startActivity(dashboard);

                    // Close Login Screen
                    finish();

                 else 
                    // Error in login
                    // loginErrorMsg.setText("Incorrect username/password");

                    _ProgressDialog.cancel();

                    alert.showAlertDialog(NotificationActivity.this,
                            "Attendence Failed..",
                            "Mark Attendence Failed.", false);
                    // loginStatusTxtView.setText("Incorrect username/password");
                

             else 
                // Error in login
                // loginErrorMsg.setText("Incorrect username/password");

                _ProgressDialog.cancel();

                alert.showAlertDialog(NotificationActivity.this,
                        "Attendence Failed..", "Mark Attendence Failed.",
                        false);
                // loginStatusTxtView.setText("Incorrect username/password");
            
         catch (JSONException e) 
            e.printStackTrace();
            Log.e("error", e.getMessage());
        

        _ProgressDialog.dismiss();

    


 

Manifest.xml

   <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.markattendence.markattendence"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="10"
    android:targetSdkVersion="18" />

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />

<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />

<!-- Creates a custom permission so only this app can receive its messages. -->
<permission
    android:name="com.markattendence.markattendence.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />

<uses-permission android:name="com.markattendence.markattendence.permission.C2D_MESSAGE" />
<uses-permission android:name="com.markattendence.activites.permission.C2D_MESSAGE" />

<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<!-- Network State Permissions to detect Internet status -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!-- Permission to vibrate -->
<uses-permission android:name="android.permission.VIBRATE" />

<uses-feature android:name="android.hardware.camera" />
<uses-feature
    android:name="android.hardware.camera.front"
    android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
    android:allowBackup="true"
    android:icon="@drawable/mmes_logo"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.markattendence.markattendence.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name="com.markattendence.markattendence.MarkAttendenceActivity" >
    </activity>
    <activity android:name="com.markattendence.markattendence.NotificationActivity" >
    </activity>

    <receiver
        android:name="com.google.android.gcm.GCMBroadcastReceiver"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>

            <!-- Receives the actual messages. -->
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <!-- Receives the registration id. -->
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

            <category android:name="com.markattendence.markattendence" />
        </intent-filter>
    </receiver>

    <service android:name="com.markattendence.markattendence.GCMIntentService" />
</application>

我在接收通知时遇到问题。服务器端代码工作正常。

我的日志猫说:

"multicast_id":5884981605957538237,"success":1,"failure":0,"canonical_ids":0,"results":["message_id":"0:1393495991926450%978fee92f9fd7ecd"]

主要问题是,如果设备有示例应用程序,它会在该应用程序而不是我的自定义应用程序中获得通知。如果我删除该应用程序,我不会收到任何通知。所以我很困惑,通知必须在我的应用程序而不是 androidhive 应用程序中接收,但推送通知显示在 androidhive 应用程序中。请帮我解决这个问题。提前致谢。

【问题讨论】:

我也在使用 XMPP 在 android 中开发聊天基础应用程序,我必须实现通知。例如,当用户 A 向用户 B 发送好友请求时,通知会发送给用户 B,同样情况下,当一个用户喜欢用户 xyz 的图片时,通知会发送给该用户 \。请指导我如何实施。我能够从名册中获得朋友,并且只获得在线朋友并且还实现了消息传递。 需要帮助***.com/questions/35812304/… 如果您使用 Firebase,请检查您是否确实将消息发送到 Android 应用 【参考方案1】:

用于将推送发送到特定设备。首先,您需要从 FCM 中选择令牌:

String token = FirebaseInstanceId.getInstance().getToken();

然后这个唯一令牌用于从服务器发布请求发送推送请求。请找到发布请求的标头以及所需的正文结构。

标题

Content-Type     'application/json'
Authorization    'key=(server-key)'

注意:标题中不允许使用这些值。这里的“服务器密钥”是您从 FCM 控制台提供的浏览器密钥。

推送请求正文


  "data": 
    "NotificationDetailsID": 1131,
    "MessageGroup": "HR",
    "Message": "this is notification"
  ,
  "to": "firebase-token-of-androidDevice"

这是服务器端的实现,肯定会起作用。正如我们最后测试的那样。即使应用关闭,您也会收到推送。

【讨论】:

【参考方案2】:

您的清单中有一些错误只会在旧 Android 版本上导致问题:

您的包裹名称是com.markattendence.markattendence

因此你应该改变这个:

<permission android:name="com.markattendence.markattendence.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />

到这里:

<permission android:name="com.markattendence.markattendence.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />
<uses-permission android:name="com.markattendence.markattendence.permission.C2D_MESSAGE" />

还有这个:

<receiver
    android:name="com.google.android.gcm.GCMBroadcastReceiver"
    android:permission="com.google.android.c2dm.permission.SEND" >
    <intent-filter>

        <!-- Receives the actual messages. -->
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <!-- Receives the registration id. -->
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

        <category android:name="com.markattendence.activites" />
    </intent-filter>
</receiver>

到这里:

<receiver
    android:name="com.google.android.gcm.GCMBroadcastReceiver"
    android:permission="com.google.android.c2dm.permission.SEND" >
    <intent-filter>

        <!-- Receives the actual messages. -->
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <!-- Receives the registration id. -->
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

        <category android:name="com.markattendence.markattendence" />
    </intent-filter>
</receiver>

【讨论】:

这给出错误:02-27 18:38:20.033: E/AndroidRuntime(18666): java.lang.RuntimeException: Unable to instance service com.markattendence.markattendence.GCMIntentService: java.lang. ClassNotFoundException: com.markattendence.markattendence.GCMIntentService @user3360307 也许您的 GCMIntentService 类位于不同的包中。你应该把它放在 com.markattendence.markattendence 我的包结构是 src -> com.markattendence.activities 这个包包含所有的类。 @user3360307 清单中定义的主包是com.markattendence.markattendence。您正在使用的 GCMBroadcastReceiver 类正在该主包中寻找 GCMIntentService。您应该更改清单中声明的​​包或更改接收器类(通过创建从此类继承的新类)以指定在哪里可以找到 GCMIntentService。 我更新了,但我仍然没有收到任何通知。日志猫说: "multicast_id":8576925643238404960,"success":1,"failure":0,"canonical_ids":0,"results": ["message_id":"0:1393563435884942%978fee92f9fd7ecd"] 【参考方案3】:

如果您可以发送通知并配置 GCM,那么问题应该出在网络上。尝试查看您的端口是否没有被阻止通知(我有类似的问题 - 我可以在解锁端口后发送但没有收到通知我收到通知)。

【讨论】:

端口未被阻止我已经检查了该答案,发现网络一切正常。当我运行 androidhive 示例时,它可以正常工作,并且我会收到该应用程序的通知,但是当我在我的应用程序中实现它时它不起作用 您在 GCM 发送通知时解锁了吗? 这是什么意思? 在开发者控制台中,您应该查看 GCM 云并将其打开。使用 GSM 意味着登录谷歌到开发者控制台并解锁一些选项。

以上是关于在android中未收到推送通知的主要内容,如果未能解决你的问题,请参考以下文章

某些设备在 android 中未收到推送通知

在 Android 自定义操作系统中未收到 FCM 推送通知

IOS Firebase 云功能中未收到推送通知

在 iOS 中未收到推送通知消息

在 iPhone 中未收到任何推送通知

在 GCM 中未收到推送通知