1

Here is my full push notification listener.

public class MyApp extends UiApplication {
    public static void main(String[] args) {
        PushAgent pa = new PushAgent();
        pa.enterEventDispatcher();
    }
}

Is this class extended correctly?

public class PushAgent extends Application {
private static final String PUSH_PORT = "32023";
private static final String BPAS_URL = "http://pushapi.eval.blackberry.com";
private static final String APP_ID = "2727-c55087eR3001rr475448i013212a56shss2";
private static final String CONNECTION_SUFFIX = ";deviceside=false;ConnectionType=mds-public";

public static final long ID = 0x749cb23a75c60e2dL;

private MessageReadingThread messageReadingThread;

public PushAgent() {
    if (!CoverageInfo.isCoverageSufficient(CoverageInfo.COVERAGE_BIS_B)) {
        return;
    }
    if (DeviceInfo.isSimulator()) {
        return;
    }
    messageReadingThread = new MessageReadingThread();
    messageReadingThread.start();
    registerBpas();
}

private static class MessageReadingThread extends Thread {

    private boolean running;
    private ServerSocketConnection socket;
    private HttpServerConnection conn;
    private InputStream inputStream;
    private PushInputStream pushInputStream;

    public MessageReadingThread() {
        this.running = true;
    }

    public void run() {
        String url = "http://:" + PUSH_PORT + CONNECTION_SUFFIX;

        try {
            socket = (ServerSocketConnection) Connector.open(url);
        } catch (IOException ex) {
        }

        while (running) {
            try {
                Object o = socket.acceptAndOpen();
                conn = (HttpServerConnection) o;
                inputStream = conn.openInputStream();
                pushInputStream = new MDSPushInputStream(conn, inputStream);
                PushMessageReader.process(pushInputStream, conn);
            } catch (Exception e) {
                if (running) {
                    running = false;
                }
            } finally {
                close(conn, pushInputStream, null);
            }
        }
    }
}

public static void close(Connection conn, InputStream is, OutputStream os) {
    if (os != null) {
        try {
            os.close();
        } catch (IOException e) {
        }
    }
    if (is != null) {
        try {
            is.close();
        } catch (IOException e) {
        }
    }
    if (conn != null) {
        try {
            conn.close();
        } catch (IOException e) {
        }
    }
}

private String formRegisterRequest(String bpasUrl, String appId,
        String token) {
    StringBuffer sb = new StringBuffer(bpasUrl);
    sb.append("/mss/PD_subReg?");
    sb.append("serviceid=").append(appId);
    sb.append("&osversion=").append(DeviceInfo.getSoftwareVersion());
    sb.append("&model=").append(DeviceInfo.getDeviceName());
    if (token != null && token.length() > 0) {
        sb.append("&").append(token);
    }
    return sb.toString();
}

private void registerBpas() {
    final String registerUrl = formRegisterRequest(BPAS_URL, APP_ID, null)
            + CONNECTION_SUFFIX;
    Object theSource = new Object() {
        public String toString() {
            return "Oriental Daily";
        }
    };

    NotificationsManager.registerSource(ID, theSource,
            NotificationsConstants.IMPORTANT);

    new Thread() {
        public void run() {
            try {
                HttpConnection httpConnection = (HttpConnection) Connector
                        .open(registerUrl);
                InputStream is = httpConnection.openInputStream();
                String response = new String(IOUtilities.streamToBytes(is));
                close(httpConnection, is, null);

                String nextUrl = formRegisterRequest(BPAS_URL, APP_ID,
                        response) + CONNECTION_SUFFIX;
                HttpConnection nextHttpConnection = (HttpConnection) Connector
                        .open(nextUrl);
                InputStream nextInputStream = nextHttpConnection
                        .openInputStream();
                response = new String(
                        IOUtilities.streamToBytes(nextInputStream));
                close(nextHttpConnection, is, null);
            } catch (IOException e) {
            }
        }
    }.start();
}
}
}

This is the process;

public class PushMessageReader {
private static final String MESSAGE_ID_HEADER = "Push-Message-ID";
private static final String MESSAGE_TYPE_TEXT = "text";
private static final String MESSAGE_TYPE_IMAGE = "image";

private static final int MESSAGE_ID_HISTORY_LENGTH = 10;
private static String[] messageIdHistory = new String[MESSAGE_ID_HISTORY_LENGTH];
private static byte historyIndex;

private static byte[] buffer = new byte[15 * 1024];
private static byte[] imageBuffer = new byte[10 * 1024];

public static final long ID = 0x749cb23a75c60e2dL;
public static Bitmap popup = Bitmap.getBitmapResource("icon_24.png");

private PushMessageReader() {
}

public static void process(PushInputStream pis, Connection conn) {
    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();

        if (!alreadyReceived(msgId)) {
            byte[] binaryData;

            if (msgId == null) {
                msgId = String.valueOf(System.currentTimeMillis());
            }

            if (msgType.indexOf(MESSAGE_TYPE_TEXT) >= 0) {
                int size = pis.read(buffer);
                binaryData = new byte[size];
                System.arraycopy(buffer, 0, binaryData, 0, size);

                NotificationsManager.triggerImmediateEvent(ID, 0, null,
                        null);
                processTextMessage(buffer);
            } else if (msgType.indexOf(MESSAGE_TYPE_IMAGE) >= 0) {
                int size = pis.read(buffer);

                if (encoding != null && encoding.equalsIgnoreCase("base64")) {
                    Base64InputStream bis = new Base64InputStream(
                            new ByteArrayInputStream(buffer, 0, size));
                    size = bis.read(imageBuffer);
                }

                binaryData = new byte[size];
                System.arraycopy(buffer, 0, binaryData, 0, size);
            }
        }
        pis.accept();
    } catch (Exception e) {

    } finally {
        PushAgent.close(conn, pis, null);
    }
}

private static boolean alreadyReceived(String id) {
    if (id == null) {
        return false;
    }

    if (Arrays.contains(messageIdHistory, id)) {
        return true;
    }

    messageIdHistory[historyIndex++] = id;

    if (historyIndex >= MESSAGE_ID_HISTORY_LENGTH) {
        historyIndex = 0;
    }
    return false;
}

private static void processTextMessage(final byte[] data) {
    synchronized (Application.getEventLock()) {

        UiEngine ui = Ui.getUiEngine();

        GlobalDialog screen = new GlobalDialog("New Notification",
                "Article ID : " + new String(data), new String(data));

        ui.pushGlobalScreen(screen, 1, UiEngine.GLOBAL_QUEUE);
    }
}

static class GlobalDialog extends PopupScreen implements
        FieldChangeListener {
    ButtonField mOKButton = new ButtonField("OK", ButtonField.CONSUME_CLICK
            | FIELD_HCENTER);
    String data = "";

    public GlobalDialog(String title, String text, String data) {
        super(new VerticalFieldManager());
        this.data = data;

        add(new LabelField(title));
        add(new SeparatorField(SeparatorField.LINE_HORIZONTAL));
        add(new LabelField(text, DrawStyle.HCENTER));

        mOKButton.setChangeListener(this);
        add(mOKButton);
    }

    public void fieldChanged(Field field, int context) {
        if (mOKButton == field) {
            try {
                ApplicationManager.getApplicationManager().launch(
                        "OrientalDailyBB");
                ApplicationManager.getApplicationManager().postGlobalEvent(
                        ID, 0, 0, data, null);

                ApplicationIndicatorRegistry reg = ApplicationIndicatorRegistry
                        .getInstance();
                reg.unregister();

                close();
            } catch (ApplicationManagerException e) {
            }
        }
    }
}
}

In this project, I checked Auto-run on startup so that this background app listener will run all the time and set the start tier to 7 in the BB App Descriptor.

However, it cannot display the popup Dialog, but I can see the device has received the push notification.

After the dialog popup and user click OK will start the OrientalDailyBB project and display the particular MainScreen.

FYI: The listener priority is higher than the OrientalDailyBB project because it is a background application. So when I install OrientalDailyBB, it will install this listener too. It happened because this listener is not in the OrientalDailyBB project folder, but is in a different folder. I did separate them to avoid the background application being terminated when the user quits from OrientalDailyBB.

Nate
  • 31,017
  • 13
  • 83
  • 207
Alan Lai
  • 1,296
  • 2
  • 12
  • 16
  • are you sure, u getting push notifications ? – Rince Thomas Jul 31 '12 at 06:35
  • refer this http://rincethomas.blogspot.in/2012/07/push-notification-in-blackberry.html – Rince Thomas Jul 31 '12 at 06:36
  • Tested with install 2 jad files. When only 1 jad file then cannot – Alan Lai Jul 31 '12 at 06:56
  • what you mean by "Tested with install 2 jad files" ? – Rince Thomas Jul 31 '12 at 06:58
  • download and install push.jad and orientaldailybb.jad then no problem. – Alan Lai Jul 31 '12 at 07:10
  • download and install orientaldailybb.jad (using updatejad.exe to merge 2 jad) then failed – Alan Lai Jul 31 '12 at 07:11
  • @AlanLai I am having similar issues. I have posted my question [here][1] [http://%5B1%5D:%20http://stackoverflow.com/questions/16274327/push-message-not-received-in-device]: as well. Do you mind sharing your executable file for the client side App. The above code that you posted will only run in background? Were you able to resolve your issue of receiving push messages? – Sarah Apr 29 '13 at 10:26

1 Answers1

1

I believe that this is a threading problem. pushGlobalScreen is a message you could try to use with invokeLater.

UiApplication.getUiApplication().invokeLater(new Runnable() {
  public void run() {
    ui.pushGlobalScreen(screen, 1, UiEngine.GLOBAL_QUEUE);
  }
});

you could try to push the application to the foreground too.

Clot
  • 139
  • 3