Blackberry - How to use notification icon in statusbar - user-interface

In RIM Blackberry OS 4.6+ there is a new feature - ability to show notification icon in statusbar. Integrated application use it to give quick and informative information for user: Dealler - missed calls, Messages - unread messages etc.
removed dead ImageShack link
Possible use of notification icon:
missed events
RSS updates
object status (ex. weather/app activity/gps signal strength)
other
I would like to post a howto guide for this feature.

ApplicationIndicator class
To add/modify/remove notification icon we can use ApplicationIndicator class:
Represents an application indicator that consists of an icon and optional numeric value.
The icon is placed in indicators area along with others such as new mail counter, calendar reminders, missed calls counter, security status and others.
Application can register only one indicator and has to register it every time the phone starts.
All indicators are cleared upon phone restart.
Indicators may be not visible if there will be no space on statusbar
Indicator dimensions depend on current theme and phone screen size.
The icon size varies from 10x10 up to 24x24.
If indicator is initialized with a big icon then an exception is thrown.
Indicator can have optional numeric value that usually serves as a counter.
The value can be negative, 0 or positive.
If indicator is used as a counter it's better to hide it when its value is equal to 0.
If indicator value is too big, it will display '99+' or '999+'
Add notification icon
For this we should create instance of ApplicationIcon:
Application icon class is used in conjunction with application indicator and application messages.
It incapsulates image and its painting properties.
EncodedImage mImage = EncodedImage.getEncodedImageResource("indicator_icon.png");
ApplicationIcon mIcon = new ApplicationIcon(mImage);
Then we should register ApplicationIndicator with ApplicationIndicatorRegistry:
ApplicationIndicatorRegistry.register(icon, iconOnly, visible)
icon - an icon to be displayed in the indicators area
iconOnly - specifies if indicator should have icon representation only and no value
visible - specifies whether indicator has to be visible initially
ApplicationIndicatorRegistry reg = ApplicationIndicatorRegistry.getInstance();
ApplicationIndicator indicator = reg.register(mIcon, false, true);
Modify indicator icon and value
To modify icon, use ApplicationIndicator.setIcon method:
ApplicationIndicatorRegistry reg = ApplicationIndicatorRegistry.getInstance();
ApplicationIndicator appIndicator = reg.getApplicationIndicator();
appIndicator.setIcon(icon);
To modify number value, use ApplicationIndicator.setValue method:
ApplicationIndicatorRegistry reg = ApplicationIndicatorRegistry.getInstance();
ApplicationIndicator appIndicator = reg.getApplicationIndicator();
appIndicator.setValue(value);
If very big value is provided then indicator will display '99+' or '999+'.
To hide or show indicator, use ApplicationIndicator.setVisible
Unregister ApplicationIndicator
Most likely you don't want your app indicator to stay in statusbar, it's better to ApplicationIndicatorRegistry.unregister() it on app close.
Sample application
Icons:
removed dead ImageShack links
Screenshots:
removed dead ImageShack links
Code:
import net.rim.blackberry.api.messagelist.ApplicationIcon;
import net.rim.blackberry.api.messagelist.ApplicationIndicator;
import net.rim.blackberry.api.messagelist.ApplicationIndicatorRegistry;
import net.rim.device.api.system.EncodedImage;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.Menu;
import net.rim.device.api.ui.container.MainScreen;
class Scr extends MainScreen {
EncodedImage mImageGreen = EncodedImage
.getEncodedImageResource("bb_icon_green.png");
ApplicationIcon mIconGreen = new ApplicationIcon(mImageGreen);
EncodedImage mImageRed = EncodedImage
.getEncodedImageResource("bb_icon_red.png");
ApplicationIcon mIconRed = new ApplicationIcon(mImageRed);
ApplicationIcon mIcon = mIconGreen;
public Scr() {
add(new LabelField("Use menu to:"));
add(new LabelField("Register indicator"));
add(new LabelField("Increment value"));
add(new LabelField("Decrement value"));
add(new LabelField("Switch icon"));
add(new LabelField("Unregister indicator"));
}
MenuItem menuRegister = new MenuItem("register", 0, 0) {
public void run() {
registerIndicator();
};
};
protected int mValue = 0;
MenuItem menuIncrement = new MenuItem("increment", 0, 0) {
public void run() {
mValue++;
updateValue(mValue);
};
};
MenuItem menuDecrement = new MenuItem("decrement", 0, 0) {
public void run() {
mValue--;
updateValue(mValue);
};
};
MenuItem menuSwitchIcon = new MenuItem("icon", 0, 0) {
public void run() {
mIcon = (mIcon == mIconGreen) ? mIconRed : mIconGreen;
updateIcon(mIcon);
};
};
MenuItem menuUnregister = new MenuItem("unregister", 0, 0) {
public void run() {
unregisterIndicator();
};
};
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(menuRegister);
menu.add(menuIncrement);
menu.add(menuDecrement);
menu.add(menuSwitchIcon);
menu.add(menuUnregister);
}
private void registerIndicator() {
try {
ApplicationIndicatorRegistry reg = ApplicationIndicatorRegistry
.getInstance();
ApplicationIndicator indicator =
reg.register(mIcon, false, true);
} catch (Exception e) {
}
}
private void unregisterIndicator() {
try {
ApplicationIndicatorRegistry reg = ApplicationIndicatorRegistry
.getInstance();
reg.unregister();
} catch (Exception e) {
}
}
void updateValue(int value) {
try {
ApplicationIndicatorRegistry reg = ApplicationIndicatorRegistry
.getInstance();
ApplicationIndicator appIndicator =
reg.getApplicationIndicator();
appIndicator.setValue(value);
} catch (Exception e) {
}
}
void updateIcon(ApplicationIcon icon) {
try {
ApplicationIndicatorRegistry reg = ApplicationIndicatorRegistry
.getInstance();
ApplicationIndicator appIndicator =
reg.getApplicationIndicator();
appIndicator.setIcon(icon);
} catch (Exception e) {
}
}
}

Related

How to do a Close Confirmation with a Xamarin Forms mac App?

I have a Xamarin.Forms application for iOS, Android, and now hopefully Mac. I made all the adjustments for the UI to look great on Mac. Submitted it for approval where it was rejected because the user can close the window while the app and menu bar is still running. So I figure I would just add a confirmation pop-up asking if they want to exit the app when they try to close the window.
OK = Terminate the App.
Cancel = Keep the window open.
I find lots of articles on how to handle this with a Xamarin.Mac app, but nothing on how to handle Xamarin.Forms on Mac. The FormsApplicationDelegate does not give access to the View Controller or the Window Delegate in order to override the WindowShouldClose method. I found that I can use NSAlert to do the pop-up which works great. Now I cannot find anything on what to do when the user responds. Open to suggestions.
private void Window_WillClose(object sender, System.EventArgs e)
{
NSNotification senderNotification = ((NSNotification)sender);
NSWindow closingWindow = (NSWindow)senderNotification.Object;
var confirmation = new NSAlert()
{
AlertStyle = NSAlertStyle.Warning,
InformativeText = "Are you sure you want to exit the App?",
MessageText = "Exit?"
};
confirmation.AddButton("OK");
confirmation.AddButton("Cancel");
var result = confirmation.RunModal();
if (result == 1001)
{
//Cancel closing the window
}
else
{
//terminate the app
}
}
After a lot of experimenting, I did find a solution. Here is what officially passed Apple's review. It requires that n menu action is linked as "New Window". It keeps tracks of the open windows and when there is only one left, it prompts to close the app. If the user closes all the windows and keeps the app running, they have the option to open a new window in the menu.
[Register("AppDelegate")]
public class AppDelegate : FormsApplicationDelegate
{
public NSWindow window;
private bool closeApp;
private List<NSWindow> openWindows;
public override NSWindow MainWindow
{
get { return window; }
}
public AppDelegate()
{
this.closeApp = false;
this.openWindows = new List<NSWindow>();
createNewWindow();
}
[Action("newWindow:")]
public void newWindow(NSObject sender)
{
createNewWindow();
this.window.MakeKeyAndOrderFront(sender);
LoadApplication(new App());
base.DidFinishLaunching(null);
}
private void createNewWindow()
{
var style = NSWindowStyle.Closable | NSWindowStyle.Resizable | NSWindowStyle.Titled;
var rect = new CoreGraphics.CGRect(200, 1000, 1024, 768);
window = new MainWindow(rect, style, NSBackingStore.Buffered, false);
window.Title = "MyApp"; // choose your own Title here
window.TitleVisibility = NSWindowTitleVisibility.Hidden;
window.WillClose += Window_WillClose;
openWindows.Add(window);
}
private void Window_WillClose(object sender, System.EventArgs e)
{
openWindows.Remove((NSWindow)((NSNotification)sender).Object);
if (openWindows.Count == 0)
{
var confirmation = new NSAlert()
{
AlertStyle = NSAlertStyle.Warning,
InformativeText = "Do you want to exit the app?",
MessageText = "Exit?"
};
confirmation.AddButton("Yes");
confirmation.AddButton("No");
var result = confirmation.RunModal();
if (result == 1001)
{
this.closeApp = false;
}
else
{
//terminate the app
this.closeApp = true;
}
}
}
public override bool ApplicationShouldTerminateAfterLastWindowClosed(NSApplication sender)
{
return closeApp;
}
public override void DidFinishLaunching(NSNotification notification)
{
Forms.Init();
LoadApplication(new App());
base.DidFinishLaunching(notification);
}
}

How to make a SWT window/shell and all the components on it adjustable?

So I have created windows/shells with buttons in an application but I want everything to resize when expanded and not to stay in one corner. I have used SWT and window builder to achieve this I used Absolute layout and now when I press full screen it is all in one corner how could I make this aesthetically pleasing so all the buttons and labels expand as well?
Please take a look at Standard layouts in SWT. Refer How to position your widgets and Understanding Layouts.
For Example below is a sample code where I have created 2 labels and 2 text in a Grid Layout which will FILL horizontally when you resize. You can change it according to your needs.
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class SampleApplication
{
protected Shell shell;
private Text text;
private Text text_1;
/**
* Launch the application.
* #param args
*/
public static void main(final String[] args)
{
try
{
SampleApplication window = new SampleApplication();
window.open();
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open()
{
Display display = Display.getDefault();
createContents();
shell.open();
shell.layout();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
}
/**
* Create contents of the window.
*/
protected void createContents()
{
shell = new Shell();
shell.setSize(450, 224);
shell.setText("SWT Application");
shell.setLayout(new GridLayout(2, false));
Label lblNewLabel = new Label(shell, SWT.NONE);
lblNewLabel.setText("Name");
lblNewLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
text = new Text(shell, SWT.BORDER);
text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
Label lblNewLabel_1 = new Label(shell, SWT.NONE);
lblNewLabel_1.setText("ID");
lblNewLabel_1.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
text_1 = new Text(shell, SWT.BORDER);
text_1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
}
}

Xamarin dismiss keyboard

So I have a searchbar(My searchbar all have a custom renderer) on one page. When a user fills in their search term they get redirect to searchpage where their results get shown.
The problem I have here is that suddenly the searchbar on the new page gets focussed (because I pass the search term from the previous page into this searchbar) and the software keyboard shows.
I want to dismiss keyboard or prevent the keyboard from showing. But when the user clicks inside the searchbar than ofcourse the keyboard can appear.
Note this question has been asked before, the answers I followed were never successfull. Here you can find what I have tried
First try: Unfocus
Just unfocussing my entry, did not work. Tried it both in my constructor and in my OnAppearing code of the page
Second try: Focus other element
Tried focussing my listview, but keyboard stil showed up
Third try: Dependency service
https://forums.xamarin.com/discussion/comment/172077#Comment_172077
Interface:
public interface IKeyboardHelper
{
void HideKeyboard();
}
iOS:
public class iOSKeyboardHelper : IKeyboardHelper
{
public void HideKeyboard()
{
UIApplication.SharedApplication.KeyWindow.EndEditing(true);
}
}
Droid:
public class DroidKeyboardHelper : IKeyboardHelper
{
public void HideKeyboard()
{
var context = Forms.Context;
var inputMethodManager = context.GetSystemService(Context.InputMethodService) as InputMethodManager;
if (inputMethodManager != null && context is Activity)
{
var activity = context as Activity;
var token = activity.CurrentFocus?.WindowToken;
inputMethodManager.HideSoftInputFromWindow(token, HideSoftInputFlags.None);
activity.Window.DecorView.ClearFocus();
}
}
}
Usage in Xamarin Forms:
DependencyService.Get<IKeyboardHelper>().HideKeyboard();
EDIT
My renderer's code for my search page
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
if (Control != null)
{
var searchView = Control;
searchView.Iconified = true;
searchView.SetIconifiedByDefault(false);
// (Resource.Id.search_mag_icon); is wrong / Xammie bug
int searchIconId = Context.Resources.GetIdentifier("android:id/search_mag_icon", null, null);
var icon = searchView.FindViewById(searchIconId);
(icon as ImageView).SetImageResource(Resource.Drawable.search_zwart);
int cancelIconId = Context.Resources.GetIdentifier("android:id/search_close_btn", null, null);
var eicon = searchView.FindViewById(cancelIconId);
(eicon as ImageView).SetImageResource(Resource.Drawable.close_zwart);
}
}

Can't paint an image after choosing it from JFileChooser

Good evening. I have read a lot of topics here on stackoverflow or even internet but I can't find the solution to my problem.
I have an interface like this:
When I click on "Load Image A", I can choose the image that I want. Next I want to paint this image under the JLabel "Image A". But it doesn't want to show up.
Here is the code I wrote:
package projet;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class MonPanelImage extends JPanel{
private static final long serialVersionUID = -8267224342030244581L;
private BufferedImage image;
public MonPanelImage(File adresse)
{
try{
image = ImageIO.read(adresse);
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponents(g);
System.out.println("paint");
if(image != null){
g.drawImage(image, 20, 20, this);
}
}
}
and here is where I call it:
//panel image. This is my second panel which will be for the images
final JPanel second = new JPanel(new BorderLayout());
//panel button. This is the third panel for the buttons
rows = 0;
cols = 3;
hgap = 5;
vgap = 0;
JPanel third = new JPanel(new GridLayout(rows,cols,hgap,vgap));
//buttons
JButton boutonLoad1 = new JButton("Load image A");
boutonLoad1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int retour = fc.showDialog(frame, "Charger l'image");
if(retour == JFileChooser.APPROVE_OPTION){
String pathImage1 = fc.getSelectedFile().getAbsolutePath();
path1 = pathImage1;
File file = fc.getSelectedFile();
MonPanelImage panelImage1 = new MonPanelImage(file);
second.add(panelImage1, BorderLayout.WEST);
second.revalidate();
second.repaint();
}
}
});
At the very end, i add the 3 panels to my frame and set the frame to visible.
But I can't paint an image. Maybe I'm not doing it properly. Can someone help me please?
Thanks
super.paintComponents(g);
First of all it should be super.paintComponent(g), without the "s".
second.add(panelImage1, BorderLayout.WEST);
You are adding your image to a component using a BorderLayout. The BorderLayout will respect the width of your component, which is 0, so there is nothing to paint.
Whenever, you do custom painting you need to override the getPreferredSize() method to return the size of your component so the layout manager can do its job.
However, an easier solution is to just use a JLabel with an Icon. There is no need to do custom painting when you are painting the image at its real size.

Add a notification icon at the status bar in BlackBerry JDE 4.5.0

I'm writing a Java application in BlackBerry JDE 4.5 that will start listening for some event at the start up. I want to display a small icon at the status bar.
I know its support in version 4.6.0 of the BlackBerry API set with ApplicationIcon, ApplicationIndicator and ApplicationIndicatorRegistry classes but which classes are there in BlackBerry JDE 4.5.0 API set?
Update
I think some support is there for 4.5.0 as I'm using Blackberry Pearl 8100 with OS v4.5.0.81 which displays Notification Icons at status bar for any incoming messages or calls.
I made the Alternale Entry point & Main CLDC app like this article below,
How To - Setup an alternate entry point for my application
I have got an article as,
How to - Make a running UI application go to the background and resume in the foreground
in which its said that
The alternate entry is going to call the main method with the parameter that is passed in, regardless of whether the application is running.
But in my case the main() is not getting called when I click on appIcon when the app is running in background.
It only updates appIcon & appName which is previously set in Alternate Entry Point.
So I m not getting where the control goes if its not calling main() when clicked on updatedIcon?
Is anyone has any idea on this issue?
I updated the appIcon & appName.
Now what I want is "When clicked on updatedIcon a particular screen should be opened & when the user goes back to Main Menu the app should get its original Icon, app name & the flow should go through main() when clicked on original app Icon"
I was thinking when I click on updated appIcon the control will go to main() but instead of calling main() it says,
Starting AppName
AppName already running
& directly it goes to first screen. and when I come back to Main Menu the app has updated icon & name
So how to get it?
Unfortunately it's not possible. What you can do is update application icon.
Also there are alternative ways of notification:
Notification Service for Blackberry OS 4.5 application
Update Application Icon
alt text http://img211.imageshack.us/img211/4527/icoupdate1.jpgalt text http://img697.imageshack.us/img697/3981/icon.jpgalt text http://img687.imageshack.us/img687/256/iconactive.jpgalt text http://img130.imageshack.us/img130/3277/icoupdate2.jpgalt text http://img691.imageshack.us/img691/6459/icoupdate3.jpg
Background running application:
public class NotifIconSrvc extends Application {
private int mCount = 0;
private int mSize = 0;
public NotifIconSrvc() {
Timer timer = new Timer();
timer.schedule(sendEventTask, 1000, 3000);
}
TimerTask sendEventTask = new TimerTask() {
public void run() {
// Post the GlobalEvent.
// Long = ci.samples.45.notificon
ApplicationManager.getApplicationManager().postGlobalEvent(
0x5a9f7caa171ab7b8L, mCount++, mSize++);
}
};
public static void main(String[] args) {
NotifIconSrvc app = new NotifIconSrvc();
app.enterEventDispatcher();
}
}
Main application:
public class NotifIconApp extends UiApplication
implements GlobalEventListener {
private Bitmap mIcon = Bitmap.getBitmapResource("icon.png");
private Bitmap mIconActive =
Bitmap.getBitmapResource("icon_active.png");
private Scr mScreen = new Scr();
public NotifIconApp() {
addGlobalEventListener(this);
pushScreen(mScreen);
}
public static void main(String[] args) {
NotifIconApp app = new NotifIconApp();
app.enterEventDispatcher();
}
public void eventOccurred(long guid, int count, int size,
Object object0, Object object1) {
if (0x5a9f7caa171ab7b8L == guid) {
Bitmap icon = getUpdateIconBitmap(mIcon, count, size);
HomeScreen.updateIcon(icon);
Bitmap rolloverIcon =
getUpdateIconBitmap(mIconActive, count, size);
HomeScreen.setRolloverIcon(rolloverIcon);
mScreen.updateScreen(count, size);
}
}
private Bitmap getUpdateIconBitmap(Bitmap bmp, int count, int size) {
int width = bmp.getWidth();
int height = bmp.getHeight();
Bitmap iconBmp = new Bitmap(width, height);
Graphics g = new Graphics(iconBmp);
XYRect rect = new XYRect(0, 0, width, height);
g.drawBitmap(rect, bmp, 0, 0);
g.setFont(g.getFont().derive(Font.BOLD, 20, Ui.UNITS_px,
Font.ANTIALIAS_STANDARD, Font.COLORED_OUTLINE_EFFECT));
String text = Integer.toString(count);
g.setColor(Color.BLACK);
g.drawText(text, 0, 2);
text = Integer.toString(size) + " Kb";
g.setColor(Color.GREEN);
g.drawText(text, 0, height - 22);
return iconBmp;
}
}
class Scr extends MainScreen {
LabelField mMessages;
String mLabelText = "message count: ";
String mTitleText = "message counter";
public Scr() {
add(mMessages = new LabelField(mLabelText));
setTitle(mTitleText);
}
void updateScreen(int count, int size) {
StringBuffer sb = new StringBuffer(Integer.toString(count));
sb.append("/");
sb.append(Integer.toString(size));
sb.append("Kb");
String text = sb.toString();
setTitle(mTitleText + "(" + text + ")");
mMessages.setText(mLabelText + text);
}
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(mMenuGoBG);
}
MenuItem mMenuGoBG = new MenuItem("go background", 0, 0) {
public void run() {
UiApplication.getUiApplication().requestBackground();
}
};
}

Resources