目标:向Android客户端发送ping。我在用户对象中保存了一系列设备注册ID。
在我的应用程序中自动创建的GCMIntentService.java中,我在这里获得了注册ID
/**
* Called back when a registration token has been received from the Google
* Cloud Messaging service.
*
* @param context
* the Context
*/
@Override
public void onRegistered(Context context, String registration) {
Log.d(TAG, "onRegistered(context, registration), Registration: " + registration);
然后创建DeviceInfo对象(也预先定义了app引擎),然后通过另一个端点将此ID添加到用户。我已经确认这是有效的/看到保持的字符串并假设我的设备现在已正确注册。
当后端发生某些事情时,我有一个自定义通知类并运行此方法:
public void sendNotificationPingToUsers(
@Named("userIds") ArrayList<Long> userIds,
ZeppaNotification notification) throws IOException {
Sender sender = new Sender(Constants.SENDER_ID);
PersistenceManager mgr = getPersistenceManager();
try {
ArrayList<String> allDevices = new ArrayList<String>();
for (int i = 0; i < userIds.size(); i++) {
long userId = userIds.get(i);
ZeppaUser zeppaUser = mgr
.getObjectById(ZeppaUser.class, userId);
if (zeppaUser != null) {
ZeppaNotification specificNotification = new ZeppaNotification();
specificNotification.setToUserId(userId);
specificNotification.setFromUserId(notification
.getFromUserId());
specificNotification.setEventId(notification.getEventId());
specificNotification.setExtraMessage(notification
.getExtraMessage());
specificNotification.setNotificationType(notification
.getType());
String extraMessage = specificNotification
.getExtraMessage();
if (extraMessage.length() > 1000) {
extraMessage = extraMessage.substring(0, 1000)
+ "[...]";
}
mgr.makePersistent(specificNotification);
allDevices.addAll(zeppaUser.getDevices());
}
}
if (!allDevices.isEmpty()) {
Message msg = new Message.Builder().collapseKey("sendToSync")
.build();
MulticastResult result = sender.send(msg, allDevices, 5);
result.getTotal();
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
mgr.close();
}
}
我传入了另一个通知,因此我可以为所有用户重新创建它,将其保存在通知表中,然后对设备执行ping操作,以便它可以将此项和其他任何用户拉出来并创建状态栏通知。
此方法,同样在GCMIntentService中:
@Override
public void onMessage(Context context, Intent intent) {
Log.d(TAG, "received message ping");
永远不会被调用,这就是我试图从设备方面处理所有事情的地方。任何人都可以指出我可能做错了什么,或者我是否错误地解释了这项服务的工作方式?
谢谢
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="19" />
<permission
android:name="com.minook.zeppa.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.minook.zeppa.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application
android:name=".ZeppaApplication"
android:allowBackup="true"
android:icon="@drawable/zeppa_icon"
android:label="@string/app_name"
android:testOnly="false"
android:theme="@style/ZeppaTheme"
android:uiOptions="none" >
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity
android:name=".LoginActivity"
android:label="@string/app_name"
android:logo="@drawable/zeppa_icon"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".CreateAccountActivity"
android:label="@string/create_account"
android:logo="@drawable/zeppa_icon" >
</activity>
<activity
android:name=".NewFriendsActivity"
android:label="@string/add_friends"
android:logo="@drawable/zeppa_icon" >
</activity>
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
</activity>
<activity
android:name=".EventViewActivity"
android:label="@string/app_name"
android:logo="@drawable/zeppa_icon" >
</activity>
<activity
android:name=".NewEventActivity"
android:label="@string/app_name"
android:logo="@drawable/zeppa_icon" >
</activity>
<activity
android:name=".UserActivity"
android:label="@string/app_name"
android:logo="@drawable/zeppa_icon" >
</activity>
<activity
android:name=".ZeppaPreferenceActivity"
android:label="@string/event_details"
android:logo="@drawable/zeppa_icon" >
</activity>
<!--
<activity
android:name=".RegisterActivity"
android:launchMode="singleTop" >
</activity>
-->
<service android:name=".GCMIntentService" />
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.minook.zeppa" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.minook.zeppa" />
</intent-filter>
</receiver>
</application>
另一个注意:我尝试使用项目编号和GAE控制台生成的服务器密钥,没有指定的IP。到目前为止都没有工作过。
答案 0 :(得分:0)
我刚才意识到我再也没有回过头来。 事实证明,他的app-engine创建的GCM代码并不是理想的做法。这是我的应用程序中的基本代码,现在成功地从后端发送发送到同步并在状态栏中显示通知。
public class ZeppaGCMReceiver extends WakefulBroadcastReceiver {
final private static String TAG = "GCMIntentService";
private static String registrationId = null;
public static void register(final ZeppaApplication application) {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(application
.getApplicationContext());
try {
registrationId = gcm.register(Constants.PROJECT_NUMBER);
Log.d(TAG, "gcm.register( " + registrationId + " )");
ZeppaUser currentUser = ZeppaUserSingleton.getInstance().getUser();
if (currentUser.getDevices() == null
|| !currentUser.getDevices().contains(registrationId)) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
Zeppauserendpoint.Builder endpointBuilder = new Zeppauserendpoint.Builder(
AndroidHttp.newCompatibleTransport(),
new JacksonFactory(),
application.getGoogleAccountCredential());
endpointBuilder = CloudEndpointUtils
.updateBuilder(endpointBuilder);
Zeppauserendpoint userEndpoint = endpointBuilder
.build();
try {
RegisterUserDevice registerTask = userEndpoint
.registerUserDevice(
ZeppaUserSingleton.getInstance().getUserId(),
registrationId);
registerTask.execute();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}.execute();
} else {
Log.d(TAG, "Already Registered");
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void unregister(final ZeppaApplication application) {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(application
.getApplicationContext());
// TODO: registration id in preferences and
try {
gcm.unregister();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "received message ping");
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
String messageType = gcm.getMessageType(intent);
Log.d(TAG, "MessageType: " + messageType);
if (messageType == null) {
Log.d(TAG, "Message is null");
return;
} else if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
.equals(messageType)) {
Log.d(TAG, "Error!");
return;
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
.equals(messageType)) {
Log.d(TAG, "Deleted");
return;
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
.equals(messageType)) {
Log.d(TAG, "Message");
handlePingInAsync(context);
} else {
Log.d(TAG, "WTF are you..? " + intent.toString());
}
}
private void handlePingInAsync(Context context) {
Context[] param = {context};
new AsyncTask<Context, Void, Void>() {
@Override
protected Void doInBackground(Context... params) {
Context context = params[0];
GoogleAccountCredential credential = getCredential(context);
if (credential == null) {
return null;
}
Zeppanotificationendpoint.Builder endpointBuilder = new Zeppanotificationendpoint.Builder(
AndroidHttp.newCompatibleTransport(),
new JacksonFactory(), credential);
endpointBuilder = CloudEndpointUtils
.updateBuilder(endpointBuilder);
Zeppanotificationendpoint notificationEndpoint = endpointBuilder
.build();
try {
SharedPreferences prefs = context.getSharedPreferences(
Constants.SHARED_PREFS, Context.MODE_PRIVATE);
Long userId = prefs.getLong(Constants.USER_ID, -1);
if (userId > 0) {
GetUnseenNotifications getUnseenNotifications = notificationEndpoint
.getUnseenNotifications(userId);
CollectionResponseZeppaNotification collectionResponse = getUnseenNotifications
.execute();
if (collectionResponse == null
|| collectionResponse.getItems() == null) {
} else {
List<ZeppaNotification> notifications = collectionResponse
.getItems();
sendNotificationsForResult(notifications,
context);
try {
NotificationSingleton.getInstance()
.addAllNotifcations(notifications);
} catch (NullPointerException ex) {
ex.printStackTrace();
}
}
} else {
Log.d(TAG, "No Set userId");
}
} catch (IOException ioEx) {
ioEx.printStackTrace();
}
return null;
}
}.execute(param);
}
private GoogleAccountCredential getCredential(Context context) {
GoogleAccountCredential credential = ((ZeppaApplication) context.getApplicationContext())
.getGoogleAccountCredential();
if (credential == null) {
SharedPreferences prefs = context.getSharedPreferences(
Constants.SHARED_PREFS, Context.MODE_PRIVATE);
String email = prefs.getString(Constants.EMAIL_ADDRESS, null);
if (email != null && !email.isEmpty() && Constants.IS_CONNECTED) {
credential = GoogleAccountCredential.usingAudience(context,
Constants.APP_ENGINE_AUDIENCE_CODE);
credential.setSelectedAccountName(email);
return credential;
}
return null;
} else {
return credential;
}
}
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
private void sendNotificationsForResult(List<ZeppaNotification> resultList,
Context context) {
Log.d(TAG, "trying to send Notifications for result");
Notification.Builder notifBuilder = new Notification.Builder(context);
if (resultList.size() > 1) {
notifBuilder.setContentTitle(resultList.size()
+ " new notifications");
StringBuilder stringBuilder = new StringBuilder();
for (ZeppaNotification notification : resultList) {
stringBuilder.append(notification.getExtraMessage()).append(
'\n');
}
notifBuilder.setContentText(stringBuilder.toString());
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(Constants.INTENT_NOTIFICATIONS, true);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
intent, 0);
notifBuilder.setContentIntent(pendingIntent);
} else {
ZeppaNotification notification = resultList.get(0);
manageSingleNotification(context, notification, notifBuilder);
notifBuilder.setContentText(notification.getExtraMessage());
}
notifBuilder.setLights(Color.CYAN, 750, 3000);
notifBuilder.setAutoCancel(true);
notifBuilder.setSmallIcon(R.drawable.notif_ic_zeppa);
Notification notification = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
notifBuilder.setPriority(Notification.PRIORITY_DEFAULT);
notification = notifBuilder.build();
} else {
notification = notifBuilder.getNotification();
}
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Log.d(TAG, "Notification Should Post");
notificationManager.notify(0, notification);
}
private void manageSingleNotification(Context context,
ZeppaNotification notification, Notification.Builder builder) {
Intent intent = null;
switch (notification.getNotificationOrdinal()) {
case 0:
builder.setContentTitle("New Friend Request");
intent = new Intent(context, NewFriendsActivity.class);
break;
case 1:
builder.setContentTitle("New Connection");
intent = new Intent(context, UserActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_USER_ID,
notification.getFromUserId());
break;
case 2:
builder.setContentTitle("Event Recommendation");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
case 3:
builder.setContentTitle("New Invite");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
case 4:
builder.setContentTitle("Event Comment");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
case 5:
builder.setContentTitle("Event Canceled");
intent = new Intent(context, MainActivity.class);
intent.putExtra(Constants.INTENT_NOTIFICATIONS, false);
break;
case 6:
builder.setContentTitle("Event Updated");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
case 7:
builder.setContentTitle("Friend Joined Event");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
case 8:
builder.setContentTitle("Friend Left Event");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
case 9:
builder.setContentTitle("Let's Find a Time?");
break;
case 10:
builder.setContentTitle("Time Found!");
break;
case 11:
builder.setContentTitle("Event Reposted");
intent = new Intent(context, EventViewActivity.class);
intent.putExtra(Constants.INTENT_ZEPPA_EVENT_ID,
notification.getEventId());
break;
default: // this shouldnt happen
builder.setContentTitle("New Zeppa Notification");
intent = new Intent(context, MainActivity.class);
intent.putExtra(Constants.INTENT_NOTIFICATIONS, false);
break;
}
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
intent, 0);
builder.setContentIntent(pendingIntent);
}
}
然后我的Manifest需要:
<permission
android:name="package.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="package.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<receiver
android:name="package.ZeppaGCMReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="package.GCMIntentService" />
</intent-filter>
</receiver>
<service
android:name="package.ZeppaGCMService"
android:enabled="true" />
然后,最后,从我的端点类,当某些事情输入数据库时,我确定应该通知哪些用户,并解雇了这个方法:
注意:getDevices只返回android设备IDS。我摆脱了DeviceInfo类,它似乎没有用,但这应该是处理这个的不正确方法。 iOS的处理方式不同,我相信你知道。如果我改变这个/如果人们想要看到iOS实现,将会更新。
public void sendNotificationPingToUsers(
@Named("userIds") List<Long> userIds,
ZeppaNotification notification) {
Sender sender = new Sender(Constants.SENDER_ID);
PersistenceManager mgr = getPersistenceManager();
try {
List<String> allDevices = new ArrayList<String>();
for (int i = 0; i < userIds.size(); i++) {
long userId = userIds.get(i);
ZeppaUser zeppaUser = mgr
.getObjectById(ZeppaUser.class, userId);
if (zeppaUser != null) {
ZeppaNotification specificNotification = new ZeppaNotification();
specificNotification.setToUserId(userId);
specificNotification.setFromUserId(notification
.getFromUserId());
specificNotification.setEventId(notification.getEventId());
specificNotification.setExtraMessage(notification
.getExtraMessage());
specificNotification.setNotificationType(notification
.getType());
mgr.makePersistent(specificNotification);
allDevices.addAll(zeppaUser.getDevices());
}
}
if (!allDevices.isEmpty()) {
Message msg = new Message.Builder().collapseKey("sendToSync")
.build();
MulticastResult result = sender.send(msg, allDevices, 500);
result.getTotal();
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
mgr.close();
}
}