在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中未收到推送通知的主要内容,如果未能解决你的问题,请参考以下文章