I am struggling for long with push messaging in BlackBerry. I am able to register successfully for push messaging with a returned code of rc=200
. However, when I run the server side code, be it in PHP or .Net, I get a successful returned code but the device never receives the message.
My PHP code is as follows:
<?php
ini_set('display_errors','1');
error_reporting(E_ALL);
// APP ID provided by RIM
$appid = '3385-xxxxxxxxxxx';
// Password provided by RIM
$password = 'xxxxxx';
//Deliver before timestamp
$deliverbefore = gmdate('Y-m-d\TH:i:s\Z', strtotime('+35 minutes'));
//An array of address must be in PIN format or "push_all"
$addresstosendto[] = 'xxxx';
$addresses = '';
foreach ($addresstosendto as $value) {
$addresses .= '<address address-value="' . $value . '"/>';
}
// create a new cURL resource
$err = false;
$ch = curl_init();
$messageid = microtime(true);
$data = '--mPsbVQo0a68eIL3OAxnm'. "\r\n" .
'Content-Type: application/xml; charset=UTF-8' . "\r\n\r\n" .
'<?xml version="1.0"?>
<!DOCTYPE pap PUBLIC "-//WAPFORUM//DTD PAP 2.1//EN" "http://www.openmobilealliance.org/tech/DTD/pap_2.1.dtd">
<pap>
<push-message push-id="' . $messageid . '" deliver-before-timestamp="' . $deliverbefore . '" source-reference="' . $appid . '">'
. $addresses .
'<quality-of-service delivery-method="confirmed"/>
</push-message>
</pap>' . "\r\n" .
'--mPsbVQo0a68eIL3OAxnm' . "\r\n" .
'Content-Type: text/plain' . "\r\n" .
'Push-Message-ID: ' . $messageid . "\r\n\r\n" .
stripslashes('r') . "\r\n" .
'--mPsbVQo0a68eIL3OAxnm--' . "\n\r";
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, "https://pushapi.eval.blackberry.com/mss/PD_pushRequest");//"https://cp3385.pushapi.eval.blackberry.com/mss/PD_pushRequest"
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_USERAGENT, "Hallgren Networks BB Push Server/1.0");
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $appid . ':' . $password);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: multipart/related; boundary=mPsbVQo0a68eIL3OAxnm; type=application/xml", "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2", "Connection: keep-alive"));
// grab URL and pass it to the browser
echo $xmldata = curl_exec($ch);
// close cURL resource, and free up system resources
curl_close($ch);
//Start parsing response into XML data that we can read and output
$p = xml_parser_create();
xml_parse_into_struct($p, $xmldata, $vals);
$errorcode = xml_get_error_code($p);
if ($errorcode > 0) {
echo xml_error_string($errorcode);
$err = true;
}
xml_parser_free($p);
echo 'Our PUSH-ID: ' . $messageid . "<br \>\n";
if (!$err && $vals[1]['tag'] == 'PUSH-RESPONSE') {
echo 'PUSH-ID: ' . $vals[1]['attributes']['PUSH-ID'] . "<br \>\n";
echo 'REPLY-TIME: ' . $vals[1]['attributes']['REPLY-TIME'] . "<br \>\n";
echo 'Response CODE: ' . $vals[2]['attributes']['CODE'] . "<br \>\n";
echo 'Response DESC: ' . $vals[2]['attributes']['DESC'] . "<br \> \n";
} else {
echo '<p>An error has occured</p>' . "\n";
echo 'Error CODE: ' . $vals[1]['attributes']['CODE'] . "<br \>\n";
echo 'Error DESC: ' . $vals[1]['attributes']['DESC'] . "<br \>\n";
}
?>
My .NET code is as follows:
public bool pushToWidget(string pushedMessage, string pushPin)
{
String BESAddress = "https://pushapi.eval.blackberry.com/mss/PD_pushRequest";
String BESWebserverListenPort = "33074";
String widgetNotificationUrl = "https://pushapi.eval.blackberry.com/mss/PD_pushRequest";
String pushUserName = "xxxx@xxx.com";
String pushPassword = "xxx@xxx";
String pushPort = "33074 ";
string Boundary = "Boundary ";
String ID = "3385-xxxxxxxxxxxxxxxxxxxxx";
//String pushPin = "xxxxxxxx";
string DeliverBefore = DateTime.UtcNow.AddMinutes(60).ToString("s",
System.Globalization.CultureInfo.InvariantCulture) + "Z";
Response.Write(DeliverBefore);
bool success = true;
StringBuilder Data = new StringBuilder();
Data.AppendLine("--" + Boundary);
Data.AppendLine("Content-Type: application/xml; charset=utf-8");
Data.AppendLine("");
Data.AppendLine("<?xml version=\"1.0\"?>");
Data.AppendLine("<!DOCTYPE pap PUBLIC \"-//WAPFORUM//DTD PAP 2.1//EN\">");
Data.AppendLine("<pap>");
Data.AppendLine("<push-message push-id=" + (char)34 + ID + (char)34 + " deliver-before-timestamp=" +
(char)34 + DeliverBefore + (char)34 + " source-reference=" + (char)34 + pushUserName + (char)34 + ">");
Data.AppendLine("<address address-value=\"" + pushPin + "\"/>");
Data.AppendLine("<quality-of-service delivery-method=\"unconfirmed\"/>");
Data.AppendLine("</push-message>");
Data.AppendLine("</pap>");
Data.AppendLine("--" + Boundary);
Data.AppendLine("Content-Type: text/plain");
Data.AppendLine("Push-Message-ID: " + ID);
Data.AppendLine("");
Data.AppendLine(pushedMessage);
Data.AppendLine("--" + Boundary + "--");
Data.AppendLine("");
byte[] bytes = Encoding.ASCII.GetBytes(Data.ToString());
Stream requestStream = null;
HttpWebResponse HttpWRes = null;
HttpWebRequest HttpWReq = null;
try
{
//http://<BESName>:<BESPort>/push?
//String DESTINATTION="<299A7C32/EMAIL>&PORT=<PushPort>&REQUESTURI=/"
// Build the URL to define our connection to the BES.
string httpURL = BESAddress + ":" + BESWebserverListenPort
+ "/push?DESTINATION=" + pushPin + "&PORT=" + pushPort
+ "&REQUESTURI=/";
//make the connection
HttpWReq = (HttpWebRequest)WebRequest.Create(httpURL);
HttpWReq.Method = ("POST");
//add the headers nessecary for the push
HttpWReq.ContentType = "text/plain";
HttpWReq.ContentLength = bytes.Length;
// ******* Test this *******
HttpWReq.Headers.Add("X-Rim-Push-Id", pushPin + "~" + DateTime.Now); //"~" +pushedMessage +
HttpWReq.Headers.Add("X-Rim-Push-Reliability", "application-preferred");
HttpWReq.Headers.Add("X-Rim-Push-NotifyURL", (widgetNotificationUrl + pushPin + "~" + pushedMessage
+ "~" + DateTime.Now).Replace(" ", ""));
// *************************
HttpWReq.Credentials = new NetworkCredential(pushUserName, pushPassword);
Console.WriteLine(pushedMessage);
requestStream = HttpWReq.GetRequestStream();
//Write the data from the source
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
//get the response
HttpWRes = (HttpWebResponse)HttpWReq.GetResponse();
String response = HttpWRes.ToString();
//if the MDS received the push parameters correctly it will either respond with okay or accepted
if (HttpWRes.StatusCode == HttpStatusCode.OK || HttpWRes.StatusCode == HttpStatusCode.Accepted)
{
success = true;
}
else
{
success = false;
}
//Close the streams
HttpWRes.Close();
requestStream.Close();
}
catch (System.Exception e)
{
success = false;
}
return success;
}
I am running the following code in my App to listen for incoming message:
public static void process(PushInputStream pis, Connection conn) {
System.out.println("Reading incoming push message ...");
try {
HttpServerConnection httpConn;
if (conn instanceof HttpServerConnection) {
httpConn = (HttpServerConnection) conn;
} else {
throw new IllegalArgumentException("Can not process non-http pushes, expected HttpServerConnection but have "
+ conn.getClass().getName());
}
String msgId = httpConn.getHeaderField(MESSAGE_ID_HEADER);
String msgType = httpConn.getType();
String encoding = httpConn.getEncoding();
System.out.println("Message props: ID=" + msgId + ", Type=" + msgType + ", Encoding=" + encoding);
boolean accept = true;
if (!alreadyReceived(msgId)) {
byte[] binaryData;
if (msgId == null) {
msgId = String.valueOf(System.currentTimeMillis());
}
if (msgType == null) {
System.out.println("Message content type is NULL");
accept = false;
} else if (msgType.indexOf(MESSAGE_TYPE_TEXT) >= 0) {
// a string
int size = pis.read(buffer);
binaryData = new byte[size];
System.arraycopy(buffer, 0, binaryData, 0, size);
PushMessage message = new PushMessage(msgId, System.currentTimeMillis(), binaryData, true, true );
String text = new String( message.getData(), "UTF-8" );
try{
final Dialog screen = new Dialog(Dialog.D_OK_CANCEL, " "+text,
Dialog.OK,
//mImageGreen.getBitmap(),
null, Manager.VERTICAL_SCROLL);
final UiEngine ui = Ui.getUiEngine();
Application.getApplication().invokeAndWait(new Runnable() {
public void run() {
NotificationsManager.triggerImmediateEvent(0x749cb23a76c66e2dL, 0, null, null);
ui.pushGlobalScreen(screen, 0, UiEngine.GLOBAL_QUEUE);
}
});
screen.setDialogClosedListener(new MyDialogClosedListener());
}
catch (Exception e) {
// TODO: handle exception
}
// TODO report message
} else {
System.out.println("Unknown message type " + msgType);
accept = false;
}
} else {
System.out.println("Received duplicate message with ID " + msgId);
}
pis.accept();
} catch (Exception e) {
System.out.println("Failed to process push message: " + e);
}
}
The above is part of the App code that is run to read the incoming message. I have posted the server side codes in detail as I am struggling with Push Messaging for a very long time and would appreciate if somebody can guide me in the right direction. Considering the fact that I am getting a "success" returned code from the server side code, could the issue be in listening and processing the message at the front end? I can share the client side App on request. Please help.