我是新手推送通知,我正在尝试向已经注册到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应用程序中。请帮我解决这个问题。提前致谢。
答案 0 :(得分:1)
您的清单中有一些错误只会导致旧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>
答案 1 :(得分:1)
用于将推送发送到特定设备。首先,您需要从FCM中选择令牌:
String token = FirebaseInstanceId.getInstance().getToken();
然后,此唯一令牌用于从服务器发布请求发送推送请求。请查找帖子请求的标题以及正文的所需结构。
<强>接头强>
Content-Type 'application/json'
Authorization 'key=(server-key)'
注意:标题中不允许使用这些值。这里的服务器密钥&#39;是FCM控制台提供的浏览器密钥。
推送请求正文
{
"data": {
"NotificationDetailsID": 1131,
"MessageGroup": "HR",
"Message": "this is notification"
},
"to": "firebase-token-of-androidDevice"
}
这是服务器端实现,这肯定会有效。正如我们在最后测试的那样。当应用程序关闭时,您将收到推送。
答案 2 :(得分:0)
如果您可以发送通知并配置GCM,那么问题应该出在网络上。尝试查看您的端口是否未被阻止通知(我有类似的问题 - 我可以发送但在解锁我收到通知的端口后没有收到通知)。