\n\u003Cuses-permission android:name=\"com.synyx.cloudmessagetest.permission.C2D_MESSAGE\"/>\n \u003C!-- App receives GCM messages. -->\n\u003Cuses-permission android:name=\"com.google.android.c2dm.permission.RECEIVE\"/>\n \u003C!-- GCM connects to Google Services. -->\n\u003Cuses-permission android:name=\"android.permission.INTERNET\"/>\n \u003C!-- GCM requires a Google account. -->\n\u003Cuses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>\n \u003C!-- Keeps the processor from sleeping when a message is received. -->\n\u003Cuses-permission android:name=\"android.permission.WAKE_LOCK\"/>\n",[79,972,973,977,982,987,992,997,1002,1007,1012,1017,1022,1027,1032],{"__ignoreMap":77},[82,974,975],{"class":84,"line":85},[82,976,644],{"emptyLinePlaceholder":490},[82,978,979],{"class":84,"line":109},[82,980,981],{},"\u003Cpermission\n",[82,983,984],{"class":84,"line":133},[82,985,986],{}," android:name=\"com.synyx.cloudmessagetest.permission.C2D_MESSAGE\"\n",[82,988,989],{"class":84,"line":154},[82,990,991],{}," android:protectionLevel=\"signature\"/>\n",[82,993,994],{"class":84,"line":163},[82,995,996],{},"\u003Cuses-permission android:name=\"com.synyx.cloudmessagetest.permission.C2D_MESSAGE\"/>\n",[82,998,999],{"class":84,"line":232},[82,1000,1001],{}," \u003C!-- App receives GCM messages. -->\n",[82,1003,1004],{"class":84,"line":621},[82,1005,1006],{},"\u003Cuses-permission android:name=\"com.google.android.c2dm.permission.RECEIVE\"/>\n",[82,1008,1009],{"class":84,"line":677},[82,1010,1011],{}," \u003C!-- GCM connects to Google Services. -->\n",[82,1013,1014],{"class":84,"line":739},[82,1015,1016],{},"\u003Cuses-permission android:name=\"android.permission.INTERNET\"/>\n",[82,1018,1019],{"class":84,"line":745},[82,1020,1021],{}," \u003C!-- GCM requires a Google account. -->\n",[82,1023,1024],{"class":84,"line":751},[82,1025,1026],{},"\u003Cuses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>\n",[82,1028,1029],{"class":84,"line":757},[82,1030,1031],{}," \u003C!-- Keeps the processor from sleeping when a message is received. -->\n",[82,1033,1034],{"class":84,"line":763},[82,1035,1036],{},"\u003Cuses-permission android:name=\"android.permission.WAKE_LOCK\"/>\n",[18,1038,1039],{},"And declare a GCM broadcast receiver within the application tag:",[72,1041,1043],{"className":692,"code":1042,"language":694,"meta":77,"style":77},"\n\u003Creceiver\n android:name=\"com.google.android.gcm.GCMBroadcastReceiver\"\n android:permission=\"com.google.android.c2dm.permission.SEND\">\n \u003Cintent-filter>\n \u003Caction android:name=\"com.google.android.c2dm.intent.RECEIVE\"/>\n \u003Caction android:name=\"com.google.android.c2dm.intent.REGISTRATION\"/>\n \u003Ccategory android:name=\"com.synyx.cloudmessagetest\"/>\n \u003C/intent-filter>\n\u003C/receiver>\n\u003Cservice android:name=\".GCMIntentService\"/>\n",[79,1044,1045,1049,1054,1059,1064,1069,1074,1079,1084,1089,1094],{"__ignoreMap":77},[82,1046,1047],{"class":84,"line":85},[82,1048,644],{"emptyLinePlaceholder":490},[82,1050,1051],{"class":84,"line":109},[82,1052,1053],{},"\u003Creceiver\n",[82,1055,1056],{"class":84,"line":133},[82,1057,1058],{}," android:name=\"com.google.android.gcm.GCMBroadcastReceiver\"\n",[82,1060,1061],{"class":84,"line":154},[82,1062,1063],{}," android:permission=\"com.google.android.c2dm.permission.SEND\">\n",[82,1065,1066],{"class":84,"line":163},[82,1067,1068],{}," \u003Cintent-filter>\n",[82,1070,1071],{"class":84,"line":232},[82,1072,1073],{}," \u003Caction android:name=\"com.google.android.c2dm.intent.RECEIVE\"/>\n",[82,1075,1076],{"class":84,"line":621},[82,1077,1078],{}," \u003Caction android:name=\"com.google.android.c2dm.intent.REGISTRATION\"/>\n",[82,1080,1081],{"class":84,"line":677},[82,1082,1083],{}," \u003Ccategory android:name=\"com.synyx.cloudmessagetest\"/>\n",[82,1085,1086],{"class":84,"line":739},[82,1087,1088],{}," \u003C/intent-filter>\n",[82,1090,1091],{"class":84,"line":745},[82,1092,1093],{},"\u003C/receiver>\n",[82,1095,1096],{"class":84,"line":751},[82,1097,1098],{},"\u003Cservice android:name=\".GCMIntentService\"/>\n",[18,1100,1101],{},"The GCMIntentService has to be created by us. And that is what we’ll do now. First off, the GCMIntentService has to\nextend the class GCMBaseIntentService:",[72,1103,1105],{"className":584,"code":1104,"language":586,"meta":77,"style":77},"public class GCMIntentService extends GCMBaseIntentService {\n",[79,1106,1107],{"__ignoreMap":77},[82,1108,1109],{"class":84,"line":85},[82,1110,1104],{},[18,1112,1113],{},"Now implement all the necessary methods. The only method we will use for this little test is onMessage(). We want to\nquickly see if we get a message for this app, so that we can confirm that it works. So we just create a notification\nwith the Notification Builder.",[18,1115,1116],{},"Because we are on an older minimum version of Android, we need to add the support library to have access to the\nNotification Builder. Add it by right clicking the project -> Android tools -> Add Support Library.",[18,1118,1119],{},"First in the onMessage() method, we need to get access to the Main Thread of our App.",[72,1121,1123],{"className":584,"code":1122,"language":586,"meta":77,"style":77},"Handler h = new Handler(Looper.getMainLooper());\nh.post(new Runnable() {\n public void run() {\n }\n}\n",[79,1124,1125,1130,1135,1140,1145],{"__ignoreMap":77},[82,1126,1127],{"class":84,"line":85},[82,1128,1129],{},"Handler h = new Handler(Looper.getMainLooper());\n",[82,1131,1132],{"class":84,"line":109},[82,1133,1134],{},"h.post(new Runnable() {\n",[82,1136,1137],{"class":84,"line":133},[82,1138,1139],{}," public void run() {\n",[82,1141,1142],{"class":84,"line":154},[82,1143,1144],{}," }\n",[82,1146,1147],{"class":84,"line":163},[82,1148,1149],{},"}\n",[18,1151,1152],{},"In the run() method, we get us an Intent from our MainActivity",[72,1154,1156],{"className":584,"code":1155,"language":586,"meta":77,"style":77},"Intent notificationIntent = new Intent(context, CloudMessageTestActivity.class);\n",[79,1157,1158],{"__ignoreMap":77},[82,1159,1160],{"class":84,"line":85},[82,1161,1155],{},[18,1163,1164],{},"And then wrap it with a PendingIntent for the NotificationBuilder",[72,1166,1168],{"className":584,"code":1167,"language":586,"meta":77,"style":77},"PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,\n notificationIntent, 0);\n",[79,1169,1170,1175],{"__ignoreMap":77},[82,1171,1172],{"class":84,"line":85},[82,1173,1174],{},"PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,\n",[82,1176,1177],{"class":84,"line":109},[82,1178,1179],{}," notificationIntent, 0);\n",[18,1181,1182],{},"Finally, use the NotificationBuilder to create and send the notification",[72,1184,1186],{"className":584,"code":1185,"language":586,"meta":77,"style":77},"NotificationCompat.Builder builder = new NotificationCompat.Builder(\n context);\nbuilder.setContentIntent(pendingIntent);\nbuilder.setAutoCancel(true);\nbuilder.setSmallIcon(R.drawable.ic_launcher);\n//this is added on the server side\nString text = intent.getStringExtra(\"text\");\nbuilder.setContentText(text);\nbuilder.setContentTitle(\"New message from the cloud!\");\nNotification noti = builder.build();\nNotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);\n//just set the mId to 1, because we don't care about it in this case\nmNotificationManager.notify(1, noti);\n",[79,1187,1188,1193,1198,1203,1208,1213,1218,1223,1228,1233,1238,1243,1248],{"__ignoreMap":77},[82,1189,1190],{"class":84,"line":85},[82,1191,1192],{},"NotificationCompat.Builder builder = new NotificationCompat.Builder(\n",[82,1194,1195],{"class":84,"line":109},[82,1196,1197],{}," context);\n",[82,1199,1200],{"class":84,"line":133},[82,1201,1202],{},"builder.setContentIntent(pendingIntent);\n",[82,1204,1205],{"class":84,"line":154},[82,1206,1207],{},"builder.setAutoCancel(true);\n",[82,1209,1210],{"class":84,"line":163},[82,1211,1212],{},"builder.setSmallIcon(R.drawable.ic_launcher);\n",[82,1214,1215],{"class":84,"line":232},[82,1216,1217],{},"//this is added on the server side\n",[82,1219,1220],{"class":84,"line":621},[82,1221,1222],{},"String text = intent.getStringExtra(\"text\");\n",[82,1224,1225],{"class":84,"line":677},[82,1226,1227],{},"builder.setContentText(text);\n",[82,1229,1230],{"class":84,"line":739},[82,1231,1232],{},"builder.setContentTitle(\"New message from the cloud!\");\n",[82,1234,1235],{"class":84,"line":745},[82,1236,1237],{},"Notification noti = builder.build();\n",[82,1239,1240],{"class":84,"line":751},[82,1241,1242],{},"NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);\n",[82,1244,1245],{"class":84,"line":757},[82,1246,1247],{},"//just set the mId to 1, because we don't care about it in this case\n",[82,1249,1250],{"class":84,"line":763},[82,1251,1252],{},"mNotificationManager.notify(1, noti);\n",[18,1254,1255],{},"That’ it with the GCMIntentService.",[18,1257,1258],{},"Now we let the app register itself with GCM in our MainActivity, which is fairly easy:",[72,1260,1262],{"className":584,"code":1261,"language":586,"meta":77,"style":77},"//set your senderId from the API here!\n private static final String SENDER_ID = \"1234567890\";\n@Override\nprotected void onCreate(Bundle savedInstanceState) {\n GCMRegistrar.checkDevice(this);\n GCMRegistrar.checkManifest(this);\n final String regId = GCMRegistrar.getRegistrationId(this);\n // if we don't have a regId yet, register at gcm\n if (regId.equals(\"\")) {\n GCMRegistrar.register(this, SENDER_ID);\n Toast.makeText(getApplicationContext(), \"Registered GCM!\", Toast.LENGTH_LONG).show();\n // just log the registrationId for this test case.\n Log.i(this.getClass().getName(), \"id: \" + GCMRegistrar.getRegistrationId(this));\n } else {\n Log.i(this.getClass().getName(), \"Already registered\");\n Toast.makeText(getApplicationContext(), \"Already registered at GCM!\", Toast.LENGTH_LONG).show();\n Log.i(this.getClass().getName(), \"id: \" + GCMRegistrar.getRegistrationId(this));\n }\n}\n",[79,1263,1264,1269,1274,1279,1284,1289,1294,1299,1304,1309,1314,1319,1324,1329,1334,1339,1344,1348,1353],{"__ignoreMap":77},[82,1265,1266],{"class":84,"line":85},[82,1267,1268],{},"//set your senderId from the API here!\n",[82,1270,1271],{"class":84,"line":109},[82,1272,1273],{}," private static final String SENDER_ID = \"1234567890\";\n",[82,1275,1276],{"class":84,"line":133},[82,1277,1278],{},"@Override\n",[82,1280,1281],{"class":84,"line":154},[82,1282,1283],{},"protected void onCreate(Bundle savedInstanceState) {\n",[82,1285,1286],{"class":84,"line":163},[82,1287,1288],{}," GCMRegistrar.checkDevice(this);\n",[82,1290,1291],{"class":84,"line":232},[82,1292,1293],{}," GCMRegistrar.checkManifest(this);\n",[82,1295,1296],{"class":84,"line":621},[82,1297,1298],{}," final String regId = GCMRegistrar.getRegistrationId(this);\n",[82,1300,1301],{"class":84,"line":677},[82,1302,1303],{}," // if we don't have a regId yet, register at gcm\n",[82,1305,1306],{"class":84,"line":739},[82,1307,1308],{}," if (regId.equals(\"\")) {\n",[82,1310,1311],{"class":84,"line":745},[82,1312,1313],{}," GCMRegistrar.register(this, SENDER_ID);\n",[82,1315,1316],{"class":84,"line":751},[82,1317,1318],{}," Toast.makeText(getApplicationContext(), \"Registered GCM!\", Toast.LENGTH_LONG).show();\n",[82,1320,1321],{"class":84,"line":757},[82,1322,1323],{}," // just log the registrationId for this test case.\n",[82,1325,1326],{"class":84,"line":763},[82,1327,1328],{}," Log.i(this.getClass().getName(), \"id: \" + GCMRegistrar.getRegistrationId(this));\n",[82,1330,1331],{"class":84,"line":769},[82,1332,1333],{}," } else {\n",[82,1335,1336],{"class":84,"line":775},[82,1337,1338],{}," Log.i(this.getClass().getName(), \"Already registered\");\n",[82,1340,1341],{"class":84,"line":781},[82,1342,1343],{}," Toast.makeText(getApplicationContext(), \"Already registered at GCM!\", Toast.LENGTH_LONG).show();\n",[82,1345,1346],{"class":84,"line":787},[82,1347,1328],{},[82,1349,1350],{"class":84,"line":792},[82,1351,1352],{}," }\n",[82,1354,1355],{"class":84,"line":798},[82,1356,1149],{},[18,1358,1359],{},"Don’t forget to replace the SENDER_ID with yours!",[18,1361,1362],{},"I haven’t implemented a way to let the server know the registrationId, because reading it from the log seemed sufficient\nfor me in this case.",[18,1364,1365],{},"With this, we finished our small app and can begin implementing the server part.",[523,1367,1369],{"id":1368},"the-web-application","The Web Application",[18,1371,1372],{},"For the Web Application, I created a maven web project with spring-webmvc and named it ‘GCMTestServer’. I’ll leave out\nthe config stuff for now, as everyone can use his/her favorite stack for this. The full sources with the configs are\nattached at the end of the blogpost.",[18,1374,1375,1376,1380],{},"Instead of just copying the GCM server library into the project, I searched a bit and found someone, who created a\nrepository for\nit. (",[22,1377,1378],{"href":1378,"rel":1379},"https://github.com/slorber/gcm-server-repository",[26],")",[18,1382,1383],{},"We start with creating the Sender class, which isn’t that hard either.",[72,1385,1387],{"className":584,"code":1386,"language":586,"meta":77,"style":77},"public class GCMSender {\n public String apiKey = null;\n public GCMSender(String apiKey) {\n this.apiKey = apiKey;\n }\n public String send(String text, String id) throws IOException {\n Sender sender = new Sender(apiKey);\n Builder builder = new Message.Builder();\n builder.addData(\"text\", text);\n Result result = sender.send(builder.build(), id, 5);\n if (result.getMessageId() != null) {\n String canonicalRegId = result.getCanonicalRegistrationId();\n if (canonicalRegId != null) {\n // same device has more than on registration ID: update database\n return \"same device has more than on registration ID: update database\";\n }\n } else {\n String error = result.getErrorCodeName();\n if (error.equals(Constants.ERROR_NOT_REGISTERED)) {\n // application has been removed from device - unregister database\n return \"application has been removed from device - unregister database\";\n }\n }\n return null;\n }\n}\n",[79,1388,1389,1394,1399,1404,1409,1414,1419,1424,1429,1434,1439,1444,1449,1454,1459,1464,1469,1474,1479,1484,1489,1494,1498,1502,1507,1511],{"__ignoreMap":77},[82,1390,1391],{"class":84,"line":85},[82,1392,1393],{},"public class GCMSender {\n",[82,1395,1396],{"class":84,"line":109},[82,1397,1398],{}," public String apiKey = null;\n",[82,1400,1401],{"class":84,"line":133},[82,1402,1403],{}," public GCMSender(String apiKey) {\n",[82,1405,1406],{"class":84,"line":154},[82,1407,1408],{}," this.apiKey = apiKey;\n",[82,1410,1411],{"class":84,"line":163},[82,1412,1413],{}," }\n",[82,1415,1416],{"class":84,"line":232},[82,1417,1418],{}," public String send(String text, String id) throws IOException {\n",[82,1420,1421],{"class":84,"line":621},[82,1422,1423],{}," Sender sender = new Sender(apiKey);\n",[82,1425,1426],{"class":84,"line":677},[82,1427,1428],{}," Builder builder = new Message.Builder();\n",[82,1430,1431],{"class":84,"line":739},[82,1432,1433],{}," builder.addData(\"text\", text);\n",[82,1435,1436],{"class":84,"line":745},[82,1437,1438],{}," Result result = sender.send(builder.build(), id, 5);\n",[82,1440,1441],{"class":84,"line":751},[82,1442,1443],{}," if (result.getMessageId() != null) {\n",[82,1445,1446],{"class":84,"line":757},[82,1447,1448],{}," String canonicalRegId = result.getCanonicalRegistrationId();\n",[82,1450,1451],{"class":84,"line":763},[82,1452,1453],{}," if (canonicalRegId != null) {\n",[82,1455,1456],{"class":84,"line":769},[82,1457,1458],{}," // same device has more than on registration ID: update database\n",[82,1460,1461],{"class":84,"line":775},[82,1462,1463],{}," return \"same device has more than on registration ID: update database\";\n",[82,1465,1466],{"class":84,"line":781},[82,1467,1468],{}," }\n",[82,1470,1471],{"class":84,"line":787},[82,1472,1473],{}," } else {\n",[82,1475,1476],{"class":84,"line":792},[82,1477,1478],{}," String error = result.getErrorCodeName();\n",[82,1480,1481],{"class":84,"line":798},[82,1482,1483],{}," if (error.equals(Constants.ERROR_NOT_REGISTERED)) {\n",[82,1485,1486],{"class":84,"line":803},[82,1487,1488],{}," // application has been removed from device - unregister database\n",[82,1490,1491],{"class":84,"line":808},[82,1492,1493],{}," return \"application has been removed from device - unregister database\";\n",[82,1495,1496],{"class":84,"line":813},[82,1497,1468],{},[82,1499,1500],{"class":84,"line":818},[82,1501,1352],{},[82,1503,1504],{"class":84,"line":824},[82,1505,1506],{}," return null;\n",[82,1508,1509],{"class":84,"line":829},[82,1510,1413],{},[82,1512,1513],{"class":84,"line":835},[82,1514,1149],{},[18,1516,1517],{},"To send messages from the server, I created a small jsp page where I can enter the text and the RegistrationId of the\nuser to send the message to:",[72,1519,1523],{"className":1520,"code":1521,"language":1522,"meta":77,"style":77},"language-html shiki shiki-themes github-light github-dark","\u003C%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\" %> \u003C%@page\ncontentType=\"text/html\" pageEncoding=\"UTF-8\"%>\n\u003C!DOCTYPE html>\n\u003Chtml>\n \u003Chead>\n \u003Cmeta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n \u003Clink\n rel=\"stylesheet\"\n type=\"text/css\"\n href=\"/GCMTestServer/frontend_resources/style.css\"\n media=\"screen\"\n />\n \u003Ctitle>GCM Sender\u003C/title>\n \u003C/head>\n \u003Cbody>\n \u003Ch1>GCM Sender\u003C/h1>\n \u003Cc:if test=\"${success == true}\">\n \u003Cdiv class=\"success\">sending successful!\u003C/div>\n \u003C/c:if>\n \u003Cc:if test=\"${error == true}\">\n \u003Cdiv class=\"error\">\n Error at sending!\n \u003Cp>${errormessage}\u003C/p>\n \u003C/div>\n \u003C/c:if>\n \u003Cform method=\"POST\">\n \u003Clabel for=\"text\">Text\u003C/label\n >\u003Cinput name=\"text\" id=\"text\" type=\"text\" />\u003Cbr />\n \u003Clabel for=\"id\">Registration-Id\u003C/label\n >\u003Cinput name=\"id\" id=\"id\" type=\"text\" />\u003Cbr />\n \u003Cinput type=\"submit\" />\n \u003C/form>\n \u003C/body>\n\u003C/html>\n","html",[79,1524,1525,1539,1544,1559,1567,1577,1605,1612,1622,1632,1642,1652,1657,1671,1680,1689,1701,1718,1741,1750,1765,1780,1785,1799,1808,1816,1833,1854,1891,1909,1939,1955,1964,1973],{"__ignoreMap":77},[82,1526,1527,1531,1534,1536],{"class":84,"line":85},[82,1528,1530],{"class":1529},"s7hpK","\u003C",[82,1532,1533],{"class":221},"%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\" %> ",[82,1535,1530],{"class":1529},[82,1537,1538],{"class":221},"%@page\n",[82,1540,1541],{"class":84,"line":109},[82,1542,1543],{"class":221},"contentType=\"text/html\" pageEncoding=\"UTF-8\"%>\n",[82,1545,1546,1549,1553,1556],{"class":84,"line":133},[82,1547,1548],{"class":221},"\u003C!",[82,1550,1552],{"class":1551},"s9eBZ","DOCTYPE",[82,1554,1555],{"class":88}," html",[82,1557,1558],{"class":221},">\n",[82,1560,1561,1563,1565],{"class":84,"line":154},[82,1562,1530],{"class":221},[82,1564,1522],{"class":1551},[82,1566,1558],{"class":221},[82,1568,1569,1572,1575],{"class":84,"line":163},[82,1570,1571],{"class":221}," \u003C",[82,1573,1574],{"class":1551},"head",[82,1576,1558],{"class":221},[82,1578,1579,1582,1585,1588,1591,1594,1597,1599,1602],{"class":84,"line":232},[82,1580,1581],{"class":221}," \u003C",[82,1583,1584],{"class":1551},"meta",[82,1586,1587],{"class":88}," http-equiv",[82,1589,1590],{"class":221},"=",[82,1592,1593],{"class":92},"\"Content-Type\"",[82,1595,1596],{"class":88}," content",[82,1598,1590],{"class":221},[82,1600,1601],{"class":92},"\"text/html; charset=UTF-8\"",[82,1603,1604],{"class":221}," />\n",[82,1606,1607,1609],{"class":84,"line":621},[82,1608,1581],{"class":221},[82,1610,1611],{"class":1551},"link\n",[82,1613,1614,1617,1619],{"class":84,"line":677},[82,1615,1616],{"class":88}," rel",[82,1618,1590],{"class":221},[82,1620,1621],{"class":92},"\"stylesheet\"\n",[82,1623,1624,1627,1629],{"class":84,"line":739},[82,1625,1626],{"class":88}," type",[82,1628,1590],{"class":221},[82,1630,1631],{"class":92},"\"text/css\"\n",[82,1633,1634,1637,1639],{"class":84,"line":745},[82,1635,1636],{"class":88}," href",[82,1638,1590],{"class":221},[82,1640,1641],{"class":92},"\"/GCMTestServer/frontend_resources/style.css\"\n",[82,1643,1644,1647,1649],{"class":84,"line":751},[82,1645,1646],{"class":88}," media",[82,1648,1590],{"class":221},[82,1650,1651],{"class":92},"\"screen\"\n",[82,1653,1654],{"class":84,"line":757},[82,1655,1656],{"class":221}," />\n",[82,1658,1659,1661,1664,1667,1669],{"class":84,"line":763},[82,1660,1581],{"class":221},[82,1662,1663],{"class":1551},"title",[82,1665,1666],{"class":221},">GCM Sender\u003C/",[82,1668,1663],{"class":1551},[82,1670,1558],{"class":221},[82,1672,1673,1676,1678],{"class":84,"line":769},[82,1674,1675],{"class":221}," \u003C/",[82,1677,1574],{"class":1551},[82,1679,1558],{"class":221},[82,1681,1682,1684,1687],{"class":84,"line":775},[82,1683,1571],{"class":221},[82,1685,1686],{"class":1551},"body",[82,1688,1558],{"class":221},[82,1690,1691,1693,1695,1697,1699],{"class":84,"line":781},[82,1692,1581],{"class":221},[82,1694,14],{"class":1551},[82,1696,1666],{"class":221},[82,1698,14],{"class":1551},[82,1700,1558],{"class":221},[82,1702,1703,1705,1708,1711,1713,1716],{"class":84,"line":787},[82,1704,1581],{"class":221},[82,1706,1707],{"class":1529},"c:if",[82,1709,1710],{"class":88}," test",[82,1712,1590],{"class":221},[82,1714,1715],{"class":92},"\"${success == true}\"",[82,1717,1558],{"class":221},[82,1719,1720,1723,1726,1729,1731,1734,1737,1739],{"class":84,"line":792},[82,1721,1722],{"class":221}," \u003C",[82,1724,1725],{"class":1551},"div",[82,1727,1728],{"class":88}," class",[82,1730,1590],{"class":221},[82,1732,1733],{"class":92},"\"success\"",[82,1735,1736],{"class":221},">sending successful!\u003C/",[82,1738,1725],{"class":1551},[82,1740,1558],{"class":221},[82,1742,1743,1746,1748],{"class":84,"line":798},[82,1744,1745],{"class":221}," \u003C/",[82,1747,1707],{"class":1529},[82,1749,1558],{"class":221},[82,1751,1752,1754,1756,1758,1760,1763],{"class":84,"line":803},[82,1753,1581],{"class":221},[82,1755,1707],{"class":1529},[82,1757,1710],{"class":88},[82,1759,1590],{"class":221},[82,1761,1762],{"class":92},"\"${error == true}\"",[82,1764,1558],{"class":221},[82,1766,1767,1769,1771,1773,1775,1778],{"class":84,"line":808},[82,1768,1722],{"class":221},[82,1770,1725],{"class":1551},[82,1772,1728],{"class":88},[82,1774,1590],{"class":221},[82,1776,1777],{"class":92},"\"error\"",[82,1779,1558],{"class":221},[82,1781,1782],{"class":84,"line":813},[82,1783,1784],{"class":221}," Error at sending!\n",[82,1786,1787,1790,1792,1795,1797],{"class":84,"line":818},[82,1788,1789],{"class":221}," \u003C",[82,1791,18],{"class":1551},[82,1793,1794],{"class":221},">${errormessage}\u003C/",[82,1796,18],{"class":1551},[82,1798,1558],{"class":221},[82,1800,1801,1804,1806],{"class":84,"line":824},[82,1802,1803],{"class":221}," \u003C/",[82,1805,1725],{"class":1551},[82,1807,1558],{"class":221},[82,1809,1810,1812,1814],{"class":84,"line":829},[82,1811,1745],{"class":221},[82,1813,1707],{"class":1529},[82,1815,1558],{"class":221},[82,1817,1818,1820,1823,1826,1828,1831],{"class":84,"line":835},[82,1819,1581],{"class":221},[82,1821,1822],{"class":1551},"form",[82,1824,1825],{"class":88}," method",[82,1827,1590],{"class":221},[82,1829,1830],{"class":92},"\"POST\"",[82,1832,1558],{"class":221},[82,1834,1835,1837,1840,1843,1845,1848,1851],{"class":84,"line":840},[82,1836,1722],{"class":221},[82,1838,1839],{"class":1551},"label",[82,1841,1842],{"class":88}," for",[82,1844,1590],{"class":221},[82,1846,1847],{"class":92},"\"text\"",[82,1849,1850],{"class":221},">Text\u003C/",[82,1852,1853],{"class":1551},"label\n",[82,1855,1856,1859,1862,1865,1867,1869,1872,1874,1876,1879,1881,1883,1886,1889],{"class":84,"line":845},[82,1857,1858],{"class":221}," >\u003C",[82,1860,1861],{"class":1551},"input",[82,1863,1864],{"class":88}," name",[82,1866,1590],{"class":221},[82,1868,1847],{"class":92},[82,1870,1871],{"class":88}," id",[82,1873,1590],{"class":221},[82,1875,1847],{"class":92},[82,1877,1878],{"class":88}," type",[82,1880,1590],{"class":221},[82,1882,1847],{"class":92},[82,1884,1885],{"class":221}," />\u003C",[82,1887,1888],{"class":1551},"br",[82,1890,1604],{"class":221},[82,1892,1893,1895,1897,1899,1901,1904,1907],{"class":84,"line":851},[82,1894,1722],{"class":221},[82,1896,1839],{"class":1551},[82,1898,1842],{"class":88},[82,1900,1590],{"class":221},[82,1902,1903],{"class":92},"\"id\"",[82,1905,1906],{"class":221},">Registration-Id\u003C/",[82,1908,1853],{"class":1551},[82,1910,1911,1913,1915,1917,1919,1921,1923,1925,1927,1929,1931,1933,1935,1937],{"class":84,"line":857},[82,1912,1858],{"class":221},[82,1914,1861],{"class":1551},[82,1916,1864],{"class":88},[82,1918,1590],{"class":221},[82,1920,1903],{"class":92},[82,1922,1871],{"class":88},[82,1924,1590],{"class":221},[82,1926,1903],{"class":92},[82,1928,1878],{"class":88},[82,1930,1590],{"class":221},[82,1932,1847],{"class":92},[82,1934,1885],{"class":221},[82,1936,1888],{"class":1551},[82,1938,1604],{"class":221},[82,1940,1942,1944,1946,1948,1950,1953],{"class":84,"line":1941},31,[82,1943,1722],{"class":221},[82,1945,1861],{"class":1551},[82,1947,1878],{"class":88},[82,1949,1590],{"class":221},[82,1951,1952],{"class":92},"\"submit\"",[82,1954,1604],{"class":221},[82,1956,1958,1960,1962],{"class":84,"line":1957},32,[82,1959,1745],{"class":221},[82,1961,1822],{"class":1551},[82,1963,1558],{"class":221},[82,1965,1967,1969,1971],{"class":84,"line":1966},33,[82,1968,1675],{"class":221},[82,1970,1686],{"class":1551},[82,1972,1558],{"class":221},[82,1974,1976,1979,1981],{"class":84,"line":1975},34,[82,1977,1978],{"class":221},"\u003C/",[82,1980,1522],{"class":1551},[82,1982,1558],{"class":221},[18,1984,1985],{},"In the corresponding Controller to process the request, send the message:",[72,1987,1989],{"className":584,"code":1988,"language":586,"meta":77,"style":77}," @RequestMapping(value = \"send\", method = RequestMethod.POST)\n public String send(Model model,\n @RequestParam(\"text\") String text,\n @RequestParam(\"id\") String id) {\n String error = null;\n try {\n error = gcmSender.send(text, id);\n } catch (IOException ex) {\n model.addAttribute(\"error\", true);\n model.addAttribute(\"errormessage\", ex.getMessage());\n }\n if (error == null) {\n model.addAttribute(\"success\", true);\n } else {\n model.addAttribute(\"error\", true);\n model.addAttribute(\"errormessage\", error);\n }\n return \"sender\";\n }\n",[79,1990,1991,1996,2001,2006,2011,2016,2021,2026,2031,2036,2041,2046,2051,2056,2061,2065,2070,2074,2079],{"__ignoreMap":77},[82,1992,1993],{"class":84,"line":85},[82,1994,1995],{}," @RequestMapping(value = \"send\", method = RequestMethod.POST)\n",[82,1997,1998],{"class":84,"line":109},[82,1999,2000],{}," public String send(Model model,\n",[82,2002,2003],{"class":84,"line":133},[82,2004,2005],{}," @RequestParam(\"text\") String text,\n",[82,2007,2008],{"class":84,"line":154},[82,2009,2010],{}," @RequestParam(\"id\") String id) {\n",[82,2012,2013],{"class":84,"line":163},[82,2014,2015],{}," String error = null;\n",[82,2017,2018],{"class":84,"line":232},[82,2019,2020],{}," try {\n",[82,2022,2023],{"class":84,"line":621},[82,2024,2025],{}," error = gcmSender.send(text, id);\n",[82,2027,2028],{"class":84,"line":677},[82,2029,2030],{}," } catch (IOException ex) {\n",[82,2032,2033],{"class":84,"line":739},[82,2034,2035],{}," model.addAttribute(\"error\", true);\n",[82,2037,2038],{"class":84,"line":745},[82,2039,2040],{}," model.addAttribute(\"errormessage\", ex.getMessage());\n",[82,2042,2043],{"class":84,"line":751},[82,2044,2045],{}," }\n",[82,2047,2048],{"class":84,"line":757},[82,2049,2050],{}," if (error == null) {\n",[82,2052,2053],{"class":84,"line":763},[82,2054,2055],{}," model.addAttribute(\"success\", true);\n",[82,2057,2058],{"class":84,"line":769},[82,2059,2060],{}," } else {\n",[82,2062,2063],{"class":84,"line":775},[82,2064,2035],{},[82,2066,2067],{"class":84,"line":781},[82,2068,2069],{}," model.addAttribute(\"errormessage\", error);\n",[82,2071,2072],{"class":84,"line":787},[82,2073,2045],{},[82,2075,2076],{"class":84,"line":792},[82,2077,2078],{}," return \"sender\";\n",[82,2080,2081],{"class":84,"line":798},[82,2082,1144],{},[18,2084,2085],{},"Now we are ready to test it!",[18,2087,2088],{},"Start the app, copy the RegistrationId from the Logs, start the Server, enter the RegistrationId and a small text, and\nthere you go:",[18,2090,2091],{},[444,2092],{"alt":2093,"src":2094},"\"notification\"","https://media.synyx.de/uploads//2012/12/notification-300x221.jpg",[18,2096,2097],{},"To get a better understanding, you can also read the rest of the starting guide and the other documentation.",[18,2099,2100],{},"All together, it’s really easy to use the GCM libraries and the messages are beeing sent to the user very fast (around\none second for me). I haven’t tried to use it in a greater context with more users yet, but I don’t think google will\nfail on this behalf 😛",[18,2102,2103,2104],{},"As promised, here are the full sources:",[22,2105,2108],{"href":2106,"rel":2107},"https://media.synyx.de/uploads//2012/12/CloudMessageTest.zip",[26],"CloudMessageTest",[470,2110,2111],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7hpK, html code.shiki .s7hpK{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":77,"searchDepth":109,"depth":109,"links":2113},[2114,2115],{"id":960,"depth":109,"text":961},{"id":1368,"depth":109,"text":1369},[2117,2118],"mobile-blog","tutorial","2013-01-08T08:21:24","https://synyx.de/blog/a-small-look-into-google-cloud-messages/",{},"/blog/a-small-look-into-google-cloud-messages",{"title":933,"description":943},{"loc":2122},"blog/a-small-look-into-google-cloud-messages",[2127,498,2128,2129,2130,2131,2132],"android","gcm","google-cloud","messages","messaging","push-notification","Within the scope of some Android R&D I took a look at Google’s Cloud Message Service, GCM. Well, the starter guide at http://developer.android.com/google/gcm/gs.html is almost all you need to get started,…","OAaYVJ_tCf4EjtyhcR8UEkVStNcR69sWPts5WylIFqc",[2136,2139,2142,2145,2148,2151,2154,2157,2160,2163,2166,2169,2172,2175,2178,2181,2184,2187,2190,2193,2196,2199,2201,2204,2207,2210,2213,2215,2218,2221,2224,2227,2230,2233,2236,2239,2242,2245,2248,2251,2254,2257,2260,2263,2266,2269,2272,2275,2278,2281,2284,2287,2290,2293,2296,2298,2301,2304,2307,2310,2313,2316,2319,2321,2324,2327,2330,2333,2336,2339,2342,2345,2348,2351,2354,2357,2360,2363,2366,2369,2372,2375,2378,2381,2384,2387,2390,2393,2396,2399,2402,2405,2408,2411,2414,2417,2420,2423,2426,2428,2431,2434,2437,2440,2442,2445,2448,2451,2454,2457,2460,2463,2466,2469,2472,2475,2478,2481,2484,2487,2490,2493,2496,2499,2502,2505,2508,2511,2514,2517,2519,2522,2525,2528,2531,2534,2537,2540,2543,2546,2549,2552],{"slug":2137,"name":2138},"abel","Jennifer Abel",{"slug":2140,"name":2141},"allmendinger","Otto Allmendinger",{"slug":2143,"name":2144},"antony","Ben Antony",{"slug":2146,"name":2147},"arrasz","Joachim Arrasz",{"slug":2149,"name":2150},"bauer","David Bauer",{"slug":2152,"name":2153},"bechtold","Janine Bechtold",{"slug":2155,"name":2156},"boersig","Jasmin Börsig",{"slug":2158,"name":2159},"buch","Fabian Buch",{"slug":2161,"name":2162},"buchloh","Aljona Buchloh",{"slug":2164,"name":2165},"burgard","Julia Burgard",{"slug":2167,"name":2168},"caspar-schwedes","Caspar Schwedes",{"slug":2170,"name":2171},"christina-schmitt","Christina Schmitt",{"slug":2173,"name":2174},"clausen","Michael Clausen",{"slug":2176,"name":2177},"contargo_poetzsch","Thomas Pötzsch",{"slug":2179,"name":2180},"damrath","Sebastian Damrath",{"slug":2182,"name":2183},"daniel","Markus Daniel",{"slug":2185,"name":2186},"dasch","Julia Dasch",{"slug":2188,"name":2189},"denman","Joffrey Denman",{"slug":2191,"name":2192},"dfuchs","Daniel Fuchs",{"slug":2194,"name":2195},"dobler","Max Dobler",{"slug":2197,"name":2198},"dobriakov","Vladimir Dobriakov",{"slug":2200,"name":2200},"dreiqbik",{"slug":2202,"name":2203},"dschaefer","Denise Schäfer",{"slug":2205,"name":2206},"dschneider","Dominik Schneider",{"slug":2208,"name":2209},"duerlich","Isabell Duerlich",{"slug":2211,"name":2212},"dutkowski","Bernd Dutkowski",{"slug":2214,"name":2214},"eifler",{"slug":2216,"name":2217},"essig","Tim Essig",{"slug":2219,"name":2220},"ferstl","Maximilian Ferstl",{"slug":2222,"name":2223},"fey","Prisca Fey",{"slug":2225,"name":2226},"frank","Leonard Frank",{"slug":2228,"name":2229},"franke","Arnold Franke",{"slug":2231,"name":2232},"frischer","Nicolette Rudmann",{"slug":2234,"name":2235},"fuchs","Petra Fuchs",{"slug":2237,"name":2238},"gari","Sarah Gari",{"slug":2240,"name":2241},"gast","Gast",{"slug":2243,"name":2244},"graf","Johannes Graf",{"slug":2246,"name":2247},"grammlich","Daniela Grammlich",{"slug":2249,"name":2250},"guthardt","Sabrina Guthardt",{"slug":2252,"name":2253},"haeussler","Johannes Häussler",{"slug":2255,"name":2256},"hammann","Daniel Hammann",{"slug":2258,"name":2259},"heetel","Julian Heetel",{"slug":2261,"name":2262},"heft","Florian Heft",{"slug":2264,"name":2265},"heib","Sebastian Heib",{"slug":2267,"name":2268},"heisler","Ida Heisler",{"slug":2270,"name":2271},"helm","Patrick Helm",{"slug":2273,"name":2274},"herbold","Michael Herbold",{"slug":2276,"name":2277},"hofmann","Peter Hofmann",{"slug":2279,"name":2280},"hopf","Florian Hopf",{"slug":2282,"name":2283},"jaud","Alina Jaud",{"slug":2285,"name":2286},"jayasinghe","Robin De Silva Jayasinghe",{"slug":2288,"name":2289},"jbuch","Jonathan Buch",{"slug":2291,"name":2292},"junghanss","Gitta Junghanß",{"slug":2294,"name":2295},"kadyietska","Khrystyna Kadyietska",{"slug":9,"name":2297},"Marc Kannegiesser",{"slug":2299,"name":2300},"karoly","Robert Károly",{"slug":2302,"name":2303},"karrasz","Katja Arrasz-Schepanski",{"slug":2305,"name":2306},"kaufmann","Florian Kaufmann",{"slug":2308,"name":2309},"kesler","Mike Kesler",{"slug":2311,"name":2312},"kirchgaessner","Bettina Kirchgäßner",{"slug":2314,"name":2315},"klem","Yannic Klem",{"slug":2317,"name":2318},"klenk","Timo Klenk",{"slug":935,"name":2320},"Tobias Knell",{"slug":2322,"name":2323},"knoll","Anna-Lena Knoll",{"slug":2325,"name":2326},"knorre","Matthias Knorre",{"slug":2328,"name":2329},"koenig","Melanie König",{"slug":2331,"name":2332},"kraft","Thomas Kraft",{"slug":2334,"name":2335},"krupicka","Florian Krupicka",{"slug":2337,"name":2338},"kuehn","Christian Kühn",{"slug":2340,"name":2341},"lange","Christian Lange",{"slug":2343,"name":2344},"larrasz","Luca Arrasz",{"slug":2346,"name":2347},"leist","Sascha Leist",{"slug":2349,"name":2350},"lihs","Michael Lihs",{"slug":2352,"name":2353},"linsin","David Linsin",{"slug":2355,"name":2356},"maniyar","Christian Maniyar",{"slug":2358,"name":2359},"martin","Björnie",{"slug":2361,"name":2362},"martin-koch","Martin Koch",{"slug":2364,"name":2365},"matt","Tobias Matt",{"slug":2367,"name":2368},"mennerich","Christian Mennerich",{"slug":2370,"name":2371},"menz","Alexander Menz",{"slug":2373,"name":2374},"meseck","Frederick Meseck",{"slug":2376,"name":2377},"messner","Oliver Messner",{"slug":2379,"name":2380},"michael-ploed","Michael Plöd",{"slug":2382,"name":2383},"mies","Marius Mies",{"slug":2385,"name":2386},"mihai","Alina Mihai",{"slug":2388,"name":2389},"moeller","Jörg Möller",{"slug":2391,"name":2392},"mohr","Rebecca Mohr",{"slug":2394,"name":2395},"moretti","David Moretti",{"slug":2397,"name":2398},"mueller","Sven Müller",{"slug":2400,"name":2401},"muessig","Alexander Müssig",{"slug":2403,"name":2404},"neupokoev","Grigory Neupokoev",{"slug":2406,"name":2407},"nussbaecher","Carmen Nussbächer",{"slug":2409,"name":2410},"ochs","Pascal Ochs",{"slug":2412,"name":2413},"oelhoff","Jan Oelhoff",{"slug":2415,"name":2416},"oengel","Yasin Öngel",{"slug":2418,"name":2419},"oezsoy","Enis Özsoy",{"slug":2421,"name":2422},"posch","Maya Posch",{"slug":2424,"name":2425},"ralfmueller","Ralf Müller",{"slug":2427,"name":2427},"redakteur",{"slug":2429,"name":2430},"reich","Michael Reich",{"slug":2432,"name":2433},"reinhard","Karl-Ludwig Reinhard",{"slug":2435,"name":2436},"rmueller","Rebecca Müller",{"slug":2438,"name":2439},"rosum","Jan Rosum",{"slug":2441,"name":2441},"rueckert",{"slug":2443,"name":2444},"ruessel","Sascha Rüssel",{"slug":2446,"name":2447},"sauter","Moritz Sauter",{"slug":2449,"name":2450},"schaefer","Julian Schäfer",{"slug":2452,"name":2453},"scherer","Petra Scherer",{"slug":2455,"name":2456},"schlicht","Anne Schlicht",{"slug":2458,"name":2459},"schmidt","Jürgen Schmidt",{"slug":2461,"name":2462},"schneider","Tobias Schneider",{"slug":2464,"name":2465},"seber","Benjamin Seber",{"slug":2467,"name":2468},"sommer","Marc Sommer",{"slug":2470,"name":2471},"speaker-fels","Jakob Fels",{"slug":2473,"name":2474},"speaker-gierke","Oliver Gierke",{"slug":2476,"name":2477},"speaker-krupa","Malte Krupa",{"slug":2479,"name":2480},"speaker-mader","Jochen Mader",{"slug":2482,"name":2483},"speaker-meusel","Tim Meusel",{"slug":2485,"name":2486},"speaker-milke","Oliver Milke",{"slug":2488,"name":2489},"speaker-paluch","Mark Paluch",{"slug":2491,"name":2492},"speaker-schad","Jörg Schad",{"slug":2494,"name":2495},"speaker-schalanda","Jochen Schalanda",{"slug":2497,"name":2498},"speaker-schauder","Jens Schauder",{"slug":2500,"name":2501},"speaker-unterstein","Johannes Unterstein",{"slug":2503,"name":2504},"speaker-wolff","Eberhard Wolff",{"slug":2506,"name":2507},"speaker-zoerner","Stefan Zörner",{"slug":2509,"name":2510},"stefan-belger","Stefan Belger",{"slug":2512,"name":2513},"steinegger","Roland Steinegger",{"slug":2515,"name":2516},"stern","sternchen synyx",{"slug":2518,"name":2518},"synyx",{"slug":2520,"name":2521},"szulc","Mateusz Szulc",{"slug":2523,"name":2524},"tamara","Tamara Tunczinger",{"slug":2526,"name":2527},"theuer","Tobias Theuer",{"slug":2529,"name":2530},"thieme","Sandra Thieme",{"slug":2532,"name":2533},"thies-clasen","Marudor",{"slug":2535,"name":2536},"toernstroem","Olle Törnström",{"slug":2538,"name":2539},"ullinger","Max Ullinger",{"slug":2541,"name":2542},"ulrich","Stephan Ulrich",{"slug":2544,"name":2545},"wagner","Stefan Wagner",{"slug":2547,"name":2548},"weigel","Andreas Weigel",{"slug":2550,"name":2551},"werner","Fabian Werner",{"slug":2553,"name":2554},"wolke","Sören Wolke",["Reactive",2556],{"$scookieConsent":2557,"$ssite-config":2559},{"functional":2558,"analytics":2558},false,{"_priority":2560,"env":2564,"name":2565,"url":2566},{"name":2561,"env":2562,"url":2563},-10,-15,0,"production","nuxt-app","https://synyx.de",["Set"],["ShallowReactive",2569],{"category-cloud":-1,"authors":-1},"/blog/tags/cloud"]