diff --git a/Advanced UI/README.md b/Advanced UI/README.md index 03f90d5..0988b33 100644 --- a/Advanced UI/README.md +++ b/Advanced UI/README.md @@ -15,6 +15,7 @@ The sample code for this application is Open Source under the [Apache 2.0 Licens **Author(s)** * [Tim Windsor](https://github.com/timwindsor) +* [Terrill Dent](https://github.com/terrilldent) **Dependencies** @@ -32,12 +33,12 @@ The sample code for this application is Open Source under the [Apache 2.0 Licens ## Contributing Changes -Please see the [README](https://github.com/blackberry/BlackBerry-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. +Please see the [README](https://github.com/blackberry/Samples-For-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. ## Bug Reporting and Feature Requests -If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/BlackBerry-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/BlackBerry-Java/issues). +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-For-Java/issues) for the Sample. ## Disclaimer diff --git a/Advanced UI/src/com/samples/toolkit/ui/component/AutoScaleImageField.java b/Advanced UI/src/com/samples/toolkit/ui/component/AutoScaleImageField.java new file mode 100644 index 0000000..7a93f71 --- /dev/null +++ b/Advanced UI/src/com/samples/toolkit/ui/component/AutoScaleImageField.java @@ -0,0 +1,123 @@ +/* +* Copyright (c) 2011 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package com.samples.toolkit.ui.component; + +import net.rim.device.api.math.*; +import net.rim.device.api.system.*; +import net.rim.device.api.ui.*; + + +public class AutoScaleImageField extends Field +{ + public static final long REDUCE_TO_WIDTH = 1L << 0; + public static final long REDUCE_TO_HEIGHT = 1L << 1; + + private int _scale32; + + private EncodedImage _normalImage; + private EncodedImage _normalScaledImage; + + private EncodedImage _focusedImage; + private EncodedImage _focusedScaledImage; + + + public AutoScaleImageField( EncodedImage normalImage, long style ) + { + this( normalImage, null, style ); + } + + public AutoScaleImageField( EncodedImage normalImage, EncodedImage focusedImage, long style ) + { + super( style ); + + if( focusedImage == null ) { + focusedImage = normalImage; + } + + if( normalImage.getWidth() != focusedImage.getWidth() + || normalImage.getHeight() != focusedImage.getHeight() ) { + throw new IllegalArgumentException(); + } + + _scale32 = Fixed32.ONE; + + _normalImage = normalImage; + _focusedImage = focusedImage; + } + + protected void layout( int width, int height ) + { + int imageWidth = _normalImage.getWidth(); + int widthScale32 = Fixed32.ONE; + if( isStyle( REDUCE_TO_WIDTH ) && imageWidth > width ) { + widthScale32 = Fixed32.toFP( imageWidth ) / width; + } + + int imageHeight = _normalImage.getHeight(); + int heightScale32 = Fixed32.ONE; + if( isStyle( REDUCE_TO_HEIGHT ) && imageHeight > height ) { + heightScale32 = Fixed32.toFP( imageHeight ) / height; + } + + int scale32 = Math.max( widthScale32, heightScale32 ); + if( scale32 == Fixed32.ONE ) { + // No scaling necessary + _normalScaledImage = _normalImage; + _focusedScaledImage = _focusedImage; + } else if( scale32 != _scale32 ) { + // We need to scale the images (and by a different factor from last time) + _scale32 = scale32; + _normalScaledImage = _normalImage.scaleImage32( scale32, scale32 ); + if( isStyle( Field.FOCUSABLE ) ) { + _focusedScaledImage = _focusedImage.scaleImage32( scale32, scale32 ); + } + } + + setExtent( Math.min( width, _normalScaledImage.getScaledWidth() ), Math.min( height, _normalScaledImage.getScaledHeight() ) ); + } + + protected void paint( Graphics g ) + { + if( g.isDrawingStyleSet( g.DRAWSTYLE_FOCUS ) ) { + g.drawImage( 0, 0, _focusedScaledImage.getScaledWidth(), _focusedScaledImage.getScaledHeight(), _focusedScaledImage, 0, 0, 0 ); + } else { + g.drawImage( 0, 0, _normalScaledImage.getScaledWidth(), _normalScaledImage.getScaledHeight(), _normalScaledImage, 0, 0, 0 ); + } + } + + protected void drawFocus( Graphics g, boolean on ) + { + // The DRAWSTYLE_FOCUS bit should already be set properly, so we can just call paint() + paint( g ); + } +/* + protected void onFocus( int direction) + { + super.onFocus( direction ); + invalidate(); + } + + protected void onUnfocus() + { + super.onUnfocus(); + invalidate(); + } +*/ +} + + + diff --git a/Advanced UI/src/com/samples/toolkit/ui/component/BaseButtonField.java b/Advanced UI/src/com/samples/toolkit/ui/component/BaseButtonField.java index e499d15..4d8954f 100644 --- a/Advanced UI/src/com/samples/toolkit/ui/component/BaseButtonField.java +++ b/Advanced UI/src/com/samples/toolkit/ui/component/BaseButtonField.java @@ -72,13 +72,13 @@ protected boolean keyChar( char character, int status, int time ) protected boolean navigationClick( int status, int time ) { - clickButton(); + if (status != 0) clickButton(); return true; } protected boolean trackwheelClick( int status, int time ) { - clickButton(); + if (status != 0) clickButton(); return true; } @@ -93,6 +93,23 @@ protected boolean invokeAction( int action ) return super.invokeAction( action ); } + protected boolean touchEvent( TouchEvent message ) + { + int x = message.getX( 1 ); + int y = message.getY( 1 ); + if( x < 0 || y < 0 || x > getExtent().width || y > getExtent().height ) { + // Outside the field + return false; + } + switch( message.getEvent() ) { + + case TouchEvent.UNCLICK: + clickButton(); + return true; + } + return super.touchEvent( message ); + } + public void setDirty( boolean dirty ) { // We never want to be dirty or muddy } diff --git a/Advanced UI/src/com/samples/toolkit/ui/component/ListStyleButtonField.java b/Advanced UI/src/com/samples/toolkit/ui/component/ListStyleButtonField.java index 93e2ed2..85bef0b 100644 --- a/Advanced UI/src/com/samples/toolkit/ui/component/ListStyleButtonField.java +++ b/Advanced UI/src/com/samples/toolkit/ui/component/ListStyleButtonField.java @@ -234,13 +234,13 @@ protected boolean keyChar( char character, int status, int time ) protected boolean navigationClick( int status, int time ) { - clickButton(); + if (status != 0) clickButton(); return true; } protected boolean trackwheelClick( int status, int time ) { - clickButton(); + if (status != 0) clickButton(); return true; } diff --git a/Advanced UI/src/com/samples/toolkit/ui/component/SliderField.java b/Advanced UI/src/com/samples/toolkit/ui/component/SliderField.java index 47a9c1f..a3dad1d 100644 --- a/Advanced UI/src/com/samples/toolkit/ui/component/SliderField.java +++ b/Advanced UI/src/com/samples/toolkit/ui/component/SliderField.java @@ -22,459 +22,386 @@ import net.rim.device.api.system.*; import net.rim.device.api.ui.*; +import net.rim.device.api.util.*; public class SliderField extends Field { - Bitmap _imageThumb; + private final static int STATE_NORMAL = 0; + private final static int STATE_FOCUSED = 1; + private final static int STATE_PRESSED = 2; - Bitmap _imageSlider; - Bitmap _imageSliderLeft; - Bitmap _imageSliderCenter; - Bitmap _imageSliderRight; + private final static int NUM_STATES = 3; - Bitmap _imageSliderFocus; - Bitmap _imageSliderFocusLeft; - Bitmap _imageSliderFocusCenter; - Bitmap _imageSliderFocusRight; - private int _numStates; - private int _currentState; - private boolean _selected; + private Bitmap[] _thumb = new Bitmap[ NUM_STATES ]; + private Bitmap[] _progress = new Bitmap[ NUM_STATES ]; + private Bitmap[] _base = new Bitmap[ NUM_STATES ]; + private Bitmap[] _progressTile = new Bitmap[ NUM_STATES ]; + private Bitmap[] _baseTile = new Bitmap[ NUM_STATES ]; - private int _xLeftBackMargin; - private int _xRightBackMargin; - private int _thumbWidth; private int _thumbHeight; - - private int _totalHeight; - private int _totalWidth; + private int _progressWidth; + private int _progressHeight; + private int _baseWidth; + private int _baseHeight; + + private int _leftCapWidth; + private int _rightCapWidth; - private int _rop; // for tiling - private int _backgroundColours[]; - private int _backgroundSelectedColours[]; + private boolean _focused; + private boolean _pressed; + + private int _numValues; + private int _currentValue; + + private int _preferredHeight; - private int _defaultSelectColour = 0x977DED; - private int _defaultBackgroundColour = 0xEEEEEE; - private int _defaultHoverColour = 0x999999; + // These values can be cached in layout() for use in paint() + private int _baseY; + private int _progressY; + private int _thumbY; + private int _trackWidth; - /** - * Bitmap thumb - The image that is used as the state indicator, it moves sideways - * Bitmap sliderBackground - the background image is stretched to fit, only stretched horizontally - * int numStates - the number of increments. NOTE: this DOES NOT include zero position (will be one larger than you say) - * int initialState - NOTE: this INCLUDES ZERO POSITION. - * int xLeftBackMargin - the amount of the background image to be used as the left side of image - * int xRightBackMargin - the amount of background image to be used as right side of image - * Everything between the left and right side gets tiled - * - * pre: NumStates must be greater or equal to initialState - * pre: NumStates must be greater than 1 - */ - public SliderField( Bitmap thumb - , Bitmap sliderBackground - , int numStates - , int initialState - , int xLeftBackMargin - , int xRightBackMargin ) + // Used to tile the base and progress bitmaps + private int _rop; + + + public SliderField( Bitmap normalThumb, Bitmap normalProgress, Bitmap normalBase, + Bitmap focusedThumb, Bitmap focusedProgress, Bitmap focusedBase, + int numValues, int initialValue, int leftCapWidth, int rightCapWidth ) { - this( thumb, sliderBackground, sliderBackground, numStates, initialState, xLeftBackMargin, xRightBackMargin, FOCUSABLE ); + this( normalThumb, normalProgress, normalBase, + focusedThumb, focusedProgress, focusedBase, + null, null, null, + numValues, initialValue, leftCapWidth, rightCapWidth, 0 ); } - public SliderField( Bitmap thumb - , Bitmap sliderBackground - , int numStates - , int initialState - , int xLeftBackMargin - , int xRightBackMargin - , long style ) - { - this( thumb, sliderBackground, sliderBackground, numStates, initialState, xLeftBackMargin, xRightBackMargin, style ); + public SliderField( Bitmap normalThumb, Bitmap normalProgress, Bitmap normalBase, + Bitmap focusedThumb, Bitmap focusedProgress, Bitmap focusedBase, + int numValues, int initialValue, int leftCapWidth, int rightCapWidth, long style ) + { + this( normalThumb, normalProgress, normalBase, + focusedThumb, focusedProgress, focusedBase, + null, null, null, + numValues, initialValue, leftCapWidth, rightCapWidth, style ); } - public SliderField( Bitmap thumb - , Bitmap sliderBackground - , Bitmap sliderBackgroundFocus - , int numStates - , int initialState - , int xLeftBackMargin - , int xRightBackMargin ) + public SliderField( Bitmap normalThumb, Bitmap normalProgress, Bitmap normalBase, + Bitmap focusedThumb, Bitmap focusedProgress, Bitmap focusedBase, + Bitmap pressedThumb, Bitmap pressedProgress, Bitmap pressedBase, + int numValues, int initialValue, int leftCapWidth, int rightCapWidth ) { - this( thumb, sliderBackground, sliderBackgroundFocus, numStates, initialState, xLeftBackMargin, xRightBackMargin, FOCUSABLE ); + this( normalThumb, normalProgress, normalBase, + focusedThumb, focusedProgress, focusedBase, + pressedThumb, pressedProgress, pressedBase, + numValues, initialValue, leftCapWidth, rightCapWidth, 0 ); } - public SliderField( Bitmap thumb - , Bitmap sliderBackground - , Bitmap sliderBackgroundFocus - , int numStates - , int initialState - , int xLeftBackMargin - , int xRightBackMargin - , long style ) + public SliderField( Bitmap normalThumb, Bitmap normalProgress, Bitmap normalBase, + Bitmap focusedThumb, Bitmap focusedProgress, Bitmap focusedBase, + Bitmap pressedThumb, Bitmap pressedProgress, Bitmap pressedBase, + int numValues, int initialValue, int leftCapWidth, int rightCapWidth, long style ) { super( style ); - if( initialState > numStates || numStates < 2 ){ + if( numValues < 2 || initialValue >= numValues ) { + throw new IllegalArgumentException( "invalid value parameters" ); } - _imageThumb = thumb; - _imageSlider = sliderBackground; - _imageSliderFocus = sliderBackgroundFocus; - _numStates = numStates; - setState( initialState ); - - _xLeftBackMargin = xLeftBackMargin; - _xRightBackMargin = xRightBackMargin; - - _rop = _imageSlider.hasAlpha() ? Graphics.ROP_SRC_ALPHA : Graphics.ROP_SRC_COPY; + if( normalThumb == null || normalProgress == null || normalBase == null + || focusedThumb == null || focusedProgress == null || focusedBase == null ) { + throw new IllegalArgumentException( "thumb, normal, focused are required" ); + } + + _thumbWidth = normalThumb.getWidth(); + _thumbHeight = normalThumb.getHeight(); + _progressWidth = normalProgress.getWidth(); + _progressHeight = normalProgress.getHeight(); + _baseWidth = normalBase.getWidth(); + _baseHeight = normalBase.getHeight(); + + if( focusedThumb.getWidth() != _thumbWidth || focusedThumb.getHeight() != _thumbHeight + || focusedProgress.getHeight() != _progressHeight || focusedBase.getHeight() != _baseHeight ) { + throw new IllegalArgumentException( "all base bitmaps and all progress bitmaps must be the same height" ); + } + if( pressedThumb != null && pressedProgress != null && pressedBase != null ) { + if( pressedThumb.getWidth() != _thumbWidth || pressedThumb.getHeight() != _thumbHeight + || pressedProgress.getHeight() != _progressHeight || pressedBase.getHeight() != _baseHeight ) { + throw new IllegalArgumentException( "all base bitmaps and all progress bitmaps must be the same height" ); + } + } + + _leftCapWidth = leftCapWidth; + _rightCapWidth = rightCapWidth; - _thumbWidth = thumb.getWidth(); - _thumbHeight = thumb.getHeight(); + _rop = Graphics.ROP_SRC_COPY; - initBitmaps(); + initBitmaps( normalThumb, normalProgress, normalBase, STATE_NORMAL ); + initBitmaps( focusedThumb, focusedProgress, focusedBase, STATE_FOCUSED ); + + if( pressedThumb != null && pressedProgress != null && pressedBase != null ) { + initBitmaps( pressedThumb, pressedProgress, pressedBase, STATE_PRESSED ); + } else { + // The pressed images are optional -- if they aren't provided, just use the focused images + _thumb[ STATE_PRESSED ] = _thumb[ STATE_FOCUSED ]; + _progress[ STATE_PRESSED ] = _progress[ STATE_FOCUSED ]; + _base[ STATE_PRESSED ] = _base[ STATE_FOCUSED ]; + _progressTile[ STATE_PRESSED ] = _progressTile[ STATE_FOCUSED ]; + _baseTile[ STATE_PRESSED ] = _baseTile[ STATE_FOCUSED ]; + } + + _preferredHeight = Math.max( _thumbHeight, Math.max( _progressHeight, _baseHeight ) ); + + _numValues = numValues; + setValue( initialValue ); } - /** - * colours - An array of colours, one for each of the states - * selectColours - An array of colours, one for each selected state + * Cuts up the background image and margins you provide + * to make the left, center, and right bitmaps */ - public SliderField( Bitmap thumb - , Bitmap sliderBackground - , int numStates - , int initialState - , int xLeftBackMargin - , int xRightBackMargin - , int[] colours - , int[] selectColours ) + public void initBitmaps( Bitmap thumb, Bitmap progress, Bitmap base, int state ) { - this(thumb, sliderBackground, sliderBackground, numStates, initialState, xLeftBackMargin, xRightBackMargin, FOCUSABLE ); - - if( colours.length != numStates+1 ){ + if( progress.getWidth() <= _leftCapWidth + || base.getWidth() <= _rightCapWidth ) { throw new IllegalArgumentException(); } - _backgroundColours = colours; - _backgroundSelectedColours = selectColours; - } + + if( thumb.hasAlpha() || progress.hasAlpha() || base.hasAlpha() ) { + // If any one of our images has an alpha channel we need to use ROP_SRC_ALPHA instead of ROP_SRC_COPY + _rop = Graphics.ROP_SRC_ALPHA; + } + + _thumb[ state ] = thumb; + _progress[ state ] = progress; + _base[ state ] = base; - /** - * Cuts up the background image and margins you provide - * to make the left, center, and right bitmaps - */ - public void initBitmaps() - { - int height = _imageSlider.getHeight(); + int[] argbCopyBuffer; - _imageSliderLeft = new Bitmap( _xLeftBackMargin, height ); - _imageSliderCenter = new Bitmap( _imageSlider.getWidth() - _xRightBackMargin - _xLeftBackMargin, height); - _imageSliderRight = new Bitmap( _xRightBackMargin, height ); + // Create the progress tile (i.e. to the left of the thumb) + int progressTileWidth = progress.getWidth() - _leftCapWidth; + int progressTileHeight = progress.getHeight(); - copy( _imageSlider, 0, 0, _xLeftBackMargin, height, _imageSliderLeft ); - copy( _imageSlider, _xLeftBackMargin, 0, _imageSlider.getWidth() - _xRightBackMargin - _xLeftBackMargin, height, _imageSliderCenter); - copy( _imageSlider, _imageSlider.getWidth() - _xRightBackMargin, 0, _xRightBackMargin, height, _imageSliderRight); - - _imageSliderFocusLeft = new Bitmap( _xLeftBackMargin, height ); - _imageSliderFocusCenter = new Bitmap( _imageSlider.getWidth() - _xRightBackMargin - _xLeftBackMargin, height); - _imageSliderFocusRight = new Bitmap( _xRightBackMargin, height ); - - copy( _imageSliderFocus, 0, 0, _xLeftBackMargin, height, _imageSliderFocusLeft ); - copy( _imageSliderFocus, _xLeftBackMargin, 0, _imageSlider.getWidth() - _xRightBackMargin - _xLeftBackMargin, height, _imageSliderFocusCenter); - copy( _imageSliderFocus, _imageSlider.getWidth() - _xRightBackMargin, 0, _xRightBackMargin, height, _imageSliderFocusRight); - } + Bitmap progressTile = new Bitmap( progressTileWidth, progressTileHeight ); - private void copy(Bitmap src, int x, int y, int width, int height, Bitmap dest) { - int[] argbData = new int[width * height]; - src.getARGB(argbData, 0, width, x, y, width, height); - for(int tx = 0; tx < dest.getWidth(); tx += width) { - for(int ty = 0; ty < dest.getHeight(); ty += height) { - dest.setARGB(argbData, 0, width, tx, ty, width, height); - } - } + argbCopyBuffer = new int[ progressTileWidth * progressTileHeight ]; + progress.getARGB( argbCopyBuffer, 0, progressTileWidth, _leftCapWidth, 0, progressTileWidth, progressTileHeight ); + progressTile.setARGB( argbCopyBuffer, 0, progressTileWidth, 0, 0, progressTileWidth, progressTileHeight ); + + // Create the base tile (i.e. to the right of the thumb) + int baseTileWidth = base.getWidth() - _rightCapWidth; + int baseTileHeight = base.getHeight(); + + Bitmap baseTile = new Bitmap( baseTileWidth, baseTileHeight ); + + argbCopyBuffer = new int[ baseTileWidth * baseTileHeight ]; + base.getARGB( argbCopyBuffer, 0, baseTileWidth, 0, 0, baseTileWidth, baseTileHeight ); + baseTile.setARGB( argbCopyBuffer, 0, baseTileWidth, 0, 0, baseTileWidth, baseTileHeight ); + + _progressTile[ state ] = progressTile; + _baseTile[ state ] = baseTile; } - /** - * Change the state of the switch. Zero is far left - * @param on - if true, the switch will be set to on state - */ - public void setState(int newState) { - if( newState > _numStates ){ + public void setValue( int newValue ) + { + if( newValue < 0 || newValue >= _numValues ){ throw new IllegalArgumentException(); - } else { - _currentState = newState; - invalidate(); } + _currentValue = newValue; + fieldChangeNotify( FieldChangeListener.PROGRAMMATIC ); + invalidate(); } - /** - * @return The current state that is selected - * State zero is on the far left, and increase to the right - */ - public int getState() { - return _currentState; + public int getValue() + { + return _currentValue; } - /** - * @return The number of states the slider has - */ - public int getNumStates() { - return _numStates; - } - - /** - * @return The current background colour being used - */ - public int getColour() { - if(_backgroundSelectedColours != null) { - return _backgroundSelectedColours[getState()]; - } - return 0x000000; + public int getNumValues() + { + return _numValues; } - public int getPreferredWidth() { - return _totalWidth; + public int getPreferredWidth() + { + return Integer.MAX_VALUE; } - public int getPreferredHeight() { - return _totalHeight; + public int getPreferredHeight() + { + return _preferredHeight; } - // Similar to TextFields layout() - protected void layout( int width, int height ) { - if (width < 0 || height < 0) - throw new IllegalArgumentException(); + protected void layout( int width, int height ) + { + width = Math.min( width, getPreferredWidth() ); + height = Math.min( height, getPreferredHeight() ); - // We'll take all we can get - _totalWidth = width; + // Cache some values for paint() and input handling + _progressY = ( height - _progressHeight ) / 2; + _baseY = ( height - _baseHeight ) / 2; + _thumbY = ( height - _thumbHeight ) / 2; - // The largest of the two image heights - _totalHeight = Math.max(_imageSlider.getHeight(), _imageThumb.getHeight()); + // The thumb should ride along the track from one end cap to the other but not cover up either one + _trackWidth = width - _leftCapWidth - _rightCapWidth; - setExtent( _totalWidth, _totalHeight ); + setExtent( width, height ); } + - public void paint( Graphics g ) - { - // Calculate the slider position - int sliderHeight = _imageSlider.getHeight(); - int sliderBackYOffset = ( _totalHeight - sliderHeight ) >> 1; - - // Determine a Background Color for the slider - int backgroundColor = _defaultBackgroundColour; - if( _backgroundSelectedColours != null || _backgroundColours != null ) { - - if( _selected ) { - backgroundColor = _backgroundSelectedColours != null ? _backgroundSelectedColours[getState()] : _defaultSelectColour; - } else if(g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS)) { - backgroundColor = _backgroundColours != null ? _backgroundColours[getState()] : _defaultHoverColour; - } else { - backgroundColor = _defaultBackgroundColour; - } - } - g.setColor( backgroundColor ); - g.fillRect( 1, sliderBackYOffset + 1, _totalWidth - 2, sliderHeight - 2 ); +public void paint( Graphics g ) +{ + int contentWidth = getContentWidth(); + + int thumbX = _leftCapWidth + ( _trackWidth - _thumbWidth ) * _currentValue / ( _numValues - 1 ); + int transitionX = thumbX + _thumbWidth / 2; - if(g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS)) { - paintSliderBackground( g, _imageSliderFocusLeft, _imageSliderFocusCenter, _imageSliderFocusRight ); - } else { - paintSliderBackground( g, _imageSliderLeft, _imageSliderCenter, _imageSliderRight ); - } - - // Calculate the thumb position - int thumbXOffset = ( ( _totalWidth - _thumbWidth ) * _currentState ) / _numStates; - - // Draw the thumb - g.drawBitmap( thumbXOffset, ( _totalHeight - _thumbHeight ) >> 1, _thumbWidth, _thumbHeight, _imageThumb, 0, 0 ); - } + int currentState = _pressed ? STATE_PRESSED : ( _focused ? STATE_FOCUSED : STATE_NORMAL ); + + Bitmap thumb = _thumb[ currentState ]; + Bitmap progress = _progress[ currentState ]; + Bitmap base = _base[ currentState ]; + Bitmap progressTile = _progressTile[ currentState ]; + Bitmap baseTile = _baseTile[ currentState ]; + + // Draw the left cap, and tile the progress region + g.drawBitmap( 0, _progressY, _leftCapWidth, _progressHeight, progress, 0, 0 ); + g.tileRop( _rop, _leftCapWidth, _progressY, transitionX - _leftCapWidth, _progressHeight, progressTile, 0, 0 ); + + // Draw the right cap, and tile the base region + g.drawBitmap( contentWidth - _rightCapWidth, _baseY, _rightCapWidth, _baseHeight, base, _baseWidth - _rightCapWidth, 0 ); + g.tileRop( _rop, transitionX, _baseY, contentWidth - transitionX - _rightCapWidth, _baseHeight, baseTile, 0, 0 ); + + // Draw the thumb + g.drawBitmap( thumbX, _thumbY, _thumbWidth, _thumbHeight, thumb, 0, 0 ); +} - private void paintSliderBackground( Graphics g, Bitmap left, Bitmap middle, Bitmap right ) +protected void drawFocus( Graphics g, boolean on ) { - int sliderHeight = _imageSlider.getHeight(); - int sliderBackYOffset = ( _totalHeight - sliderHeight ) >> 1; - - // Left - g.drawBitmap( 0, sliderBackYOffset, _xLeftBackMargin, sliderHeight, left, 0, 0 );//lefttop - // Middle - g.tileRop( _rop, _xRightBackMargin, sliderBackYOffset, _totalWidth - _xLeftBackMargin - _xRightBackMargin, sliderHeight, middle, 0, 0 );//top - // Right - g.drawBitmap( _totalWidth - _xRightBackMargin, sliderBackYOffset, _xRightBackMargin, sliderHeight, right, 0, 0 );//lefttop + // The paint() method looks after drawing the focus for us } - - public void paintBackground( Graphics g ) + + protected void onFocus( int direction ) { - // nothing + _focused = true; + invalidate(); + super.onFocus( direction ); } - - protected void drawFocus( Graphics g, boolean on ) + + protected void onUnfocus() { - boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ); - try { - if( on ) { - g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true ); - } - paint( g ); - } finally { - g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus ); - } + _focused = false; + invalidate(); + super.onUnfocus(); } - - /** - * Traps touch input events. - * - *

This method handles touch input events. DOWN events cause this ButtonField - * to enter a focused state, which is in fact handled at the Manager level. CLICK - * events cause this ButtonField to enter an active (pressed) state. UNCLICK events - * invoke {@link invokeAction} and {@link trackwheelUnclick} methods in sequence. The remaining - * touch input events are consumed and/or ignored. - * - * @param message {@link TouchEvent} object containing various input parameters - * including the event type and touch coordinates. - * @return True if the event was consumed; otherwise, false. - * @throws IllegalArgumentException If message is null. - * - */ //#ifndef VER_4.6.1 | VER_4.6.0 | VER_4.5.0 | VER_4.2.1 | VER_4.2.0 - protected boolean touchEvent(TouchEvent message) + protected boolean touchEvent( TouchEvent message ) { - boolean isConsumed = false; - boolean isOutOfBounds = false; - int x = message.getX(1); - int y = message.getY(1); - // Check to ensure point is within this field - if(x < 0 || y < 0 || x > getExtent().width || y > getExtent().height) { - isOutOfBounds = true; - } - switch(message.getEvent()) { + int event = message.getEvent(); + switch( event ) { + case TouchEvent.CLICK: - case TouchEvent.MOVE: - if(isOutOfBounds) return true; // consume - _selected = true; // Pressed effect - - // update state - int stateWidth = getExtent().width / _numStates; - int numerator = x / stateWidth; - int denominator = x % stateWidth; - if( denominator > stateWidth / 2 ) { - numerator++; - } - _currentState = numerator; - invalidate(); - - isConsumed = true; - break; - case TouchEvent.UNCLICK: - if(isOutOfBounds) { - _selected = false; // Reset presssed effect - return true; + case TouchEvent.DOWN: + // If we currently have the focus, we still get told about a click in a different part of the screen + if( touchEventOutOfBounds( message ) ) { + return false; } + // fall through - // A field change notification is only sent on UNCLICK to allow for recovery - // should the user cancel, i.e. click and move off the button - - _selected = false; // Reset pressed effect + case TouchEvent.MOVE: + _pressed = true; + setValueByTouchPosition( message.getX( 1 ) ); + fieldChangeNotify( 0 ); + return true; - // Update state - stateWidth = getExtent().width / _numStates; - numerator = x / stateWidth; - denominator = x % stateWidth; - if( denominator > stateWidth / 2 ) { - numerator++; - } - _currentState = numerator; + case TouchEvent.UNCLICK: + case TouchEvent.UP: + _pressed = false; invalidate(); + return true; - fieldChangeNotify(0); - - isConsumed = true; - break; + default: + return false; } - return isConsumed; } + + private boolean touchEventOutOfBounds( TouchEvent message ) + { + int x = message.getX( 1 ); + int y = message.getY( 1 ); + return ( x < 0 || y < 0 || x > getWidth() || y > getHeight() ); + } + + private void setValueByTouchPosition( int x ) + { + _currentValue = MathUtilities.clamp( 0, ( x - _leftCapWidth ) * _numValues / _trackWidth, _numValues - 1 ); + invalidate(); + } + + //#endif - protected boolean navigationMovement(int dx, int dy, int status, int time) + protected boolean navigationMovement( int dx, int dy, int status, int time ) { - if( _selected ) - { - if(dx > 0 || dy > 0) { - incrementState(); - fieldChangeNotify( 0 ); - return true; - } else if(dx < 0 || dy < 0) { - decrementState(); - fieldChangeNotify( 0 ); - return true; + if( _pressed ) { + if( dx > 0 || dy > 0 ) { + incrementValue(); + } else { + decrementValue(); } + fieldChangeNotify( 0 ); + return true; } return super.navigationMovement( dx, dy, status, time); } - public void decrementState() { - if(_currentState > 0) { - _currentState--; + private void incrementValue() + { + if( _currentValue + 1 < _numValues ) { + _currentValue++; invalidate(); } } - public void incrementState() { - if(_currentState < _numStates) { - _currentState++; + private void decrementValue() + { + if( _currentValue > 0 ) { + _currentValue--; invalidate(); } } - - /** - * Invokes an action on this field. The only action that is recognized by this method is - * {@link Field#ACTION_INVOKE}, which toggles this field from being checked and unchecked. - */ - protected boolean invokeAction(int action) { - switch(action) { - case ACTION_INVOKE: { - toggleSelected(); - return true; - } + protected boolean invokeAction( int action ) + { + if( action == ACTION_INVOKE ) { + togglePressed(); + return true; } return false; } - /** - * Listens for the space key to be pressed - * When pressed, state is toggles - */ - protected boolean keyChar( char key, int status, int time ) { + protected boolean keyChar( char key, int status, int time ) + { if( key == Characters.SPACE || key == Characters.ENTER ) { - toggleSelected(); + togglePressed(); return true; } - return false; } - protected boolean trackwheelClick( int status, int time ) { - if( isEditable() ) { - toggleSelected(); - return true; - } - return super.trackwheelClick(status, time); - } - - /** - * Toggles the state of the switch - */ - private void toggleSelected() { - _selected = !_selected; - invalidate(); - } - - public void setDirty( boolean dirty ) + protected boolean trackwheelClick( int status, int time ) { - // We never want to be dirty or muddy + togglePressed(); + return true; } - public void setMuddy( boolean muddy ) + private void togglePressed() { - // We never want to be dirty or muddy + _pressed = !_pressed; + invalidate(); } } diff --git a/Advanced UI/src/com/samples/toolkit/ui/container/FieldSet.java b/Advanced UI/src/com/samples/toolkit/ui/container/FieldSet.java new file mode 100644 index 0000000..9f8f982 --- /dev/null +++ b/Advanced UI/src/com/samples/toolkit/ui/container/FieldSet.java @@ -0,0 +1,125 @@ +/* +* Copyright (c) 2011 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +package com.samples.toolkit.ui.container; + +import net.rim.device.api.ui.*; +import net.rim.device.api.ui.container.*; +import net.rim.device.api.ui.decor.*; + + +public class FieldSet extends VerticalFieldManager +{ + private String _title; + private Border _titleBorder; + private Border _contentBorder; + + public FieldSet( String title, Border titleBorder, Border contentBorder, long style ) + { + super( style ); + + _title = title; + _titleBorder = titleBorder; + _contentBorder = contentBorder; + } + + protected void applyFont() + { + setBorder( new FieldSetBorder( _title, getFont(), _titleBorder, _contentBorder ), true ); + } + + + private static class FieldSetBorder extends Border + { + private String _title; + private Font _font; + private Border _titleBorder; + private Border _contentBorder; + + private Background _titleBackground; + + private int _titleAreaHeight; + private int _titleBorderTopAndBottom; + private int _titleBorderLeftAndRight; + + private XYRect _paintRect = new XYRect(); + + + public FieldSetBorder( String title, Font font, Border titleBorder, Border contentBorder ) + { + super( getComposedBorderEdges( font, titleBorder, contentBorder ), 0 ); + + _title = title; + _font = font; + _titleBorder = titleBorder; + _contentBorder = contentBorder; + + _titleBackground = titleBorder.getBackground(); + + _titleAreaHeight = titleBorder.getTop() + font.getHeight() + titleBorder.getBottom(); + _titleBorderTopAndBottom = titleBorder.getTop() + titleBorder.getBottom(); + _titleBorderLeftAndRight = titleBorder.getLeft() + titleBorder.getRight(); + } + + public static XYEdges getComposedBorderEdges( Font font, Border titleBorder, Border contentBorder ) + { + if( titleBorder.getLeft() != contentBorder.getLeft() + || titleBorder.getRight() != contentBorder.getRight() ) { + throw new IllegalArgumentException( "borders must have matching left and right edges" ); + } + + return new XYEdges( + titleBorder.getTop() + font.getHeight() + titleBorder.getBottom() + contentBorder.getTop(), + contentBorder.getRight(), + contentBorder.getBottom(), + contentBorder.getLeft() ); + } + + public void paint( Graphics graphics, XYRect rect ) + { + // paint() is always called from the event thread so we don't have to worry about concurrent access to _paintRect + _paintRect.set( rect.x, rect.y, rect.width, _titleAreaHeight ); + _titleBorder.paint( graphics, _paintRect ); + + if( _titleBackground != null ) { + _paintRect.x += _titleBorder.getLeft(); + _paintRect.y += _titleBorder.getTop(); + _paintRect.width -= _titleBorderLeftAndRight; + _paintRect.height -= _titleBorderTopAndBottom; + _titleBackground.draw( graphics, _paintRect ); + } + + _paintRect.set( rect.x, rect.y + _titleAreaHeight, rect.width, rect.height - _titleAreaHeight ); + _contentBorder.paint( graphics, _paintRect ); + + Font oldFont = graphics.getFont(); + try { + graphics.setFont( _font ); + graphics.drawText( _title, rect.x + _titleBorder.getLeft(), rect.y + _titleBorder.getTop(), DrawStyle.ELLIPSIS, rect.width - _titleBorderLeftAndRight ); + } finally { + graphics.setFont( oldFont ); + } + } + + public Background getBackground() + { + return _contentBorder.getBackground(); + } + + } + +} diff --git a/Advanced UI/src/com/samples/toolkit/ui/container/JustifiedEvenlySpacedHorizontalFieldManager.java b/Advanced UI/src/com/samples/toolkit/ui/container/JustifiedEvenlySpacedHorizontalFieldManager.java index f2f7639..35903e0 100644 --- a/Advanced UI/src/com/samples/toolkit/ui/container/JustifiedEvenlySpacedHorizontalFieldManager.java +++ b/Advanced UI/src/com/samples/toolkit/ui/container/JustifiedEvenlySpacedHorizontalFieldManager.java @@ -46,7 +46,13 @@ protected void sublayout( int width, int height ) // There may be a few remaining pixels after dividing up the space // we must split up the space between the first and last buttons - int fieldWidth = width / numFields; + + //if there are no fields the current fieldWidth should be 0 + final int fieldWidth; + if (numFields == 0) + fieldWidth = 0; + else + fieldWidth = width / numFields; int firstFieldExtra = 0; int lastFieldExtra = 0; diff --git a/Advanced UI/src/com/samples/toolkit/ui/decor/BitmapBorderBackground.java b/Advanced UI/src/com/samples/toolkit/ui/decor/BitmapBorderBackground.java new file mode 100644 index 0000000..411bf9a --- /dev/null +++ b/Advanced UI/src/com/samples/toolkit/ui/decor/BitmapBorderBackground.java @@ -0,0 +1,72 @@ +//#preprocessor + +/* +* Copyright (c) 2011 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +//#ifndef VER_4.1.0 | VER_4.2.0 | VER_4.2.1 | VER_4.3.0 | VER_4.5.0 + + +package com.samples.toolkit.ui.decor; + +import net.rim.device.api.ui.*; +import net.rim.device.api.ui.decor.*; +import net.rim.device.api.ui.Graphics; +import net.rim.device.api.ui.XYRect; +import net.rim.device.api.system.*; + +public class BitmapBorderBackground extends Background +{ + private Bitmap _background; + private Border _bitmapBorder; + private XYEdges _edges; + private int _fillColor = - 1; + + public BitmapBorderBackground( XYEdges edges, Bitmap background ) + { + _background = background; + _edges = edges; + + _bitmapBorder = BorderFactory.createBitmapBorder( _edges, _background ); + } + + public BitmapBorderBackground( XYEdges edges, Bitmap background, int fillColor ) + { + this( edges, background ); + _fillColor = fillColor; + } + + public void draw( Graphics g, XYRect rect ) + { + _bitmapBorder.paint( g, rect ); + + if( _fillColor != - 1 && rect.width > _edges.left + _edges.right && rect.height > _edges.top + _edges.bottom ) { + int oldColor = g.getColor(); + try { + g.setColor( _fillColor ); + g.fillRect( rect.x + _edges.left, rect.y + _edges.top, rect.width - _edges.left - _edges.right, rect.height - _edges.top - _edges.bottom ); + } finally { + g.setColor( oldColor ); + } + } + } + + public boolean isTransparent() + { + return _background.hasAlpha(); + } +} +//#endif diff --git a/Advanced UI/src/com/samples/toolkit/ui/decor/BitmapMask.java b/Advanced UI/src/com/samples/toolkit/ui/decor/BitmapMask.java new file mode 100644 index 0000000..e940635 --- /dev/null +++ b/Advanced UI/src/com/samples/toolkit/ui/decor/BitmapMask.java @@ -0,0 +1,249 @@ +/* +* Copyright (c) 2011 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package com.samples.toolkit.ui.decor; + +import net.rim.device.api.system.*; +import net.rim.device.api.ui.*; + + +/** + * A helper class for applying an alpha mask to a Bitmap + * + * The BitmapMask is created with a green image, and a set of edges. + * It is reusable (can be applied to multiple images) + * + * The green value become the alpha channel of the bitmaps passed into applyMask() + * Black (0x00) becomes transparent + * Green (0xFF) remains opaque + */ +public class BitmapMask +{ + private final int _alphaTop; + private final int _alphaRight; + private final int _alphaBottom; + private final int _alphaLeft; + + private final int _alphaWidth; + private final int _alphaHeight; + private final int _alphaInsideWidth; + private final int _alphaInsideHeight; + + private final int[] _alphaARGB; + private final int[] _cornerARGB; + + /** + * Bitmap mask + * @param edges the top, right, bottom, and left edges sizes + * @param alpha the green bitmap which will become the mask + */ + public BitmapMask( XYEdges edges, Bitmap alpha ) + { + //Initialize edges + if( edges == null ) { + throw new IllegalArgumentException( "BitmapMask: XYEdges edges is null." ); + } + if( edges.isEmpty() ) { + throw new IllegalArgumentException( "BitmapMask: XYEdges edges is empty." ); + } + + _alphaTop = edges.top; + _alphaRight = edges.right; + _alphaBottom = edges.bottom; + _alphaLeft = edges.left; + + // Initalize bitmap properties + if( alpha == null ) { + throw new IllegalArgumentException("BitmapMask: alpha is null."); + } + + _alphaWidth = alpha.getWidth(); + _alphaHeight = alpha.getHeight(); + + _alphaInsideWidth = _alphaWidth - _alphaLeft - _alphaRight; + _alphaInsideHeight = _alphaHeight - _alphaBottom - _alphaTop; + if( ( _alphaInsideWidth < 0 ) || ( _alphaInsideHeight < 0 ) ) { + throw new IllegalArgumentException("BitmapMask: Invalid alpha width and height."); + } + + _alphaARGB = new int[ _alphaWidth * _alphaHeight ]; + alpha.getARGB( _alphaARGB, 0, _alphaWidth, 0, 0, _alphaWidth, _alphaHeight ); + + for( int i=_alphaARGB.length-1; i>=0; i-- ) { + _alphaARGB[ i ] = ( _alphaARGB[ i ] << 16 ) & 0xff000000; + } + + _cornerARGB = new int[ Math.max( _alphaLeft, _alphaRight ) * Math.max( _alphaTop, _alphaBottom ) ]; + } + + public int getTop() + { + return _alphaTop; + } + + public int getRight() + { + return _alphaRight; + } + + public int getBottom() + { + return _alphaBottom; + } + + public int getLeft() + { + return _alphaLeft; + } + + public int getWidth() + { + return _alphaWidth; + } + + public int getHeight() + { + return _alphaHeight; + } + + /** + * Apply the mask to the given bitmap + * + * @param targetBitmap this bitmaps ARGB data will be modified with the alpha data from the mask + */ + public void applyMask( Bitmap targetBitmap ) + { + int targetWidth = targetBitmap.getWidth(); + int targetHeight = targetBitmap.getHeight(); + + int[] bufferARGB = new int[ targetWidth ]; + + int targetTop = Math.min( _alphaTop, targetHeight ); + int targetRight = Math.min( _alphaRight, targetWidth ); + int targetBottom = Math.min( _alphaBottom, targetHeight ); + int targetLeft = Math.min( _alphaLeft, targetWidth ); + + int targetInsideBottomY = targetHeight - targetBottom; + int targetInsideTopY = targetTop; + + int targetInsideRightX = targetWidth - targetRight; + int targetInsideLeftX = targetLeft; + + int targetInsideWidth = Math.max( targetInsideRightX - targetInsideLeftX, 0 ); + int targetInsideHeight = Math.max( targetInsideBottomY - targetInsideTopY, 0 ); + + + if( _alphaInsideWidth > 0) { + if( targetTop > 0 ) { + drawTileMask( _alphaLeft, 0, _alphaInsideWidth, _alphaTop, + targetLeft, 0, targetInsideWidth, targetTop, targetBitmap, bufferARGB ); // top + } + if( targetBottom > 0 ) { + drawTileMask( _alphaLeft, _alphaHeight - _alphaBottom, _alphaInsideWidth, _alphaBottom, + targetLeft, targetHeight - targetBottom, targetInsideWidth, targetBottom, targetBitmap, bufferARGB ); // bottom + } + } + if( _alphaInsideHeight > 0 ) { + if( targetLeft > 0 ) { + drawTileMask( 0, _alphaTop, _alphaLeft, _alphaInsideHeight, + 0, targetTop, targetLeft, targetInsideHeight, targetBitmap, bufferARGB ); // left + } + if( targetRight > 0 ) { + drawTileMask( _alphaWidth - _alphaRight, _alphaTop, _alphaRight, _alphaInsideHeight, + targetWidth - targetRight, targetTop, targetRight, targetInsideHeight, targetBitmap, bufferARGB ); // right + } + } + if( targetTop > 0 ) { + if( targetLeft > 0) { + drawCornerMask( 0, 0, _alphaLeft, _alphaTop, + 0, 0, targetBitmap ); // left top + } + if( targetRight > 0 ) { + drawCornerMask( _alphaLeft + _alphaInsideWidth, 0, _alphaRight, _alphaTop, + targetInsideRightX, 0, targetBitmap ); // right top + } + } + if( targetBottom > 0 ) { + if( targetLeft > 0 ) { + drawCornerMask( 0, _alphaHeight - _alphaBottom, _alphaLeft, _alphaBottom, + 0, targetHeight - targetBottom, targetBitmap ); // left bottom + } + if( targetRight > 0 ) { + drawCornerMask( _alphaWidth - _alphaRight, _alphaHeight - _alphaBottom, _alphaRight, _alphaBottom, + targetWidth - targetRight, targetHeight - targetBottom, targetBitmap ); // right bottom + } + } + } + + /** + * Apply a portion of the mask to the destination area. Tile if destination area is larger than source area + */ + private void drawTileMask( int sourceX, int sourceY, int sourceWidth, int sourceHeight, + int destX, int destY, int destWidth, int destHeight, + Bitmap targetBitmap, int[] bufferARGB ) + { + int sourceOffsetStart = sourceY * _alphaWidth + sourceX; + int sourceOffsetMax = ( sourceY + sourceHeight ) + _alphaWidth; + int sourceOffset = sourceOffsetStart; + + for( int y=0; y= sourceOffsetMax ) { + sourceOffset = sourceOffsetStart; + } + } + } + + + /** + * Apply a portion of the mask to the destination area. Tile if destination area is smaller than source area + */ + private void drawCornerMask( int sourceX, int sourceY, int sourceWidth, int sourceHeight, + int destX, int destY, + Bitmap targetBitmap ) + { + int sourceOffset = sourceY * _alphaWidth + sourceX; + int destOffset = 0; + + targetBitmap.getARGB( _cornerARGB, 0, sourceWidth, destX, destY, sourceWidth, sourceHeight ); + + for( int y=0; y + + + + + + diff --git a/NFC/LLCPDemo/.project b/NFC/LLCPDemo/.project new file mode 100644 index 0000000..a66769f --- /dev/null +++ b/NFC/LLCPDemo/.project @@ -0,0 +1,29 @@ + + + LLCPDemo + + + + + + net.rim.ejde.internal.builder.BlackBerryPreprocessBuilder + + + + + net.rim.ejde.internal.builder.BlackBerryResourcesBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + + net.rim.ejde.BlackBerryPreProcessNature + net.rim.ejde.BlackBerryProjectCoreNature + org.eclipse.jdt.core.javanature + + diff --git a/NFC/LLCPDemo/.settings/net.rim.browser.tools.debug.widget.prefs b/NFC/LLCPDemo/.settings/net.rim.browser.tools.debug.widget.prefs new file mode 100644 index 0000000..d9b0c31 --- /dev/null +++ b/NFC/LLCPDemo/.settings/net.rim.browser.tools.debug.widget.prefs @@ -0,0 +1,3 @@ +#Thu Jul 12 09:19:09 BST 2012 +eclipse.preferences.version=1 +outputfolder=build diff --git a/NFC/LLCPDemo/.settings/org.eclipse.jdt.core.prefs b/NFC/LLCPDemo/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b87a019 --- /dev/null +++ b/NFC/LLCPDemo/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Thu Jul 12 09:18:42 BST 2012 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore +org.eclipse.jdt.core.compiler.source=1.3 diff --git a/NFC/LLCPDemo/BlackBerry_App_Descriptor.xml b/NFC/LLCPDemo/BlackBerry_App_Descriptor.xml new file mode 100644 index 0000000..43e4f77 --- /dev/null +++ b/NFC/LLCPDemo/BlackBerry_App_Descriptor.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NFC/LLCPDemo/README.md b/NFC/LLCPDemo/README.md new file mode 100644 index 0000000..c804f1b --- /dev/null +++ b/NFC/LLCPDemo/README.md @@ -0,0 +1,53 @@ +# NFC LLCP Sample + + +The purpose of this application is to demonstrate how to transfer data from one NFC-enabled BlackBerry to another +using the NFC Logical Link Control Protocol (LLCP). + +To use this application, you’ll need to install it on two NFC enabled BlackBerry devices. +On the first device, select the Sender icon and on the second select the Receiver icon. +Adjust the text on the next screen on the sender device and click "Continue" and then place both devices back-to-back. +You should see the data transfer take place and this illustrated by messages on the activity log screen. + +The application is liberally instrumented with EventLogger Informational messages using the label "LLCPDemo" +that can be examined in the event log of a device. Use Alt-LGLG to set the log level to Information and to examine the +event log or use javaloader -u eventlog>eventlog.txt to extract the log to your PC over USB. + +The sample code for this application is Open Source under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0.html). + +**Applies To** + +* [BlackBerry Java SDK for Smartphones](http://us.blackberry.com/developers/javaappdev/) + + +**Author(s)** + +* [John Murray](https://github.com/jcmurray) +* [Martin Woolley](https://github.com/mdwoolley) + + +**Dependencies** + +1. BlackBerry Device Software 7.1 and above. + + +**Known Issues** + +None + +**To contribute code to this repository you must be [signed up as an official contributor](http://blackberry.github.com/howToContribute.html).** + + +## Contributing Changes + +Please see the [README](https://github.com/blackberry/BlackBerry-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. + + +## Bug Reporting and Feature Requests + +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/BlackBerry-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/BlackBerry-Java/issues). + + +## Disclaimer + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.cod b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.cod new file mode 100644 index 0000000..5c90c60 Binary files /dev/null and b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.cod differ diff --git a/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.csl b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.csl new file mode 100644 index 0000000..725a93b --- /dev/null +++ b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.csl @@ -0,0 +1 @@ +52525400=RIM Runtime API diff --git a/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.cso b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.cso new file mode 100644 index 0000000..1a589a3 --- /dev/null +++ b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.cso @@ -0,0 +1,5 @@ +33000000=RIMAPPSA2 +52424200=RIM Blackberry Apps API +52434900=RIM Crypto API - Internal +52435200=RIM Crypto API - RIM +4e464352=NFCRoutingAPI diff --git a/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.debug b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.debug new file mode 100644 index 0000000..f106498 Binary files /dev/null and b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.debug differ diff --git a/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.jad b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.jad new file mode 100644 index 0000000..0d923ae --- /dev/null +++ b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.jad @@ -0,0 +1,16 @@ +MIDlet-Name: LLCPDemo +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: LLCPDemo.jar +MIDlet-Jar-Size: 116307 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: LLCPDemo,img/my_icon.png, +RIM-MIDlet-Flags-1: 0 +Manifest-Version: 1.0 +RIM-COD-URL: LLCPDemo.cod +RIM-COD-Size: 48348 +RIM-COD-Creation-Time: 1342085635 +RIM-COD-Module-Name: LLCPDemo +RIM-COD-Module-Dependencies: net_rim_cldc,net_rim_nfc +RIM-COD-SHA1: 9f b5 69 92 d6 8e ef c5 87 1a 0c 91 45 53 3d 3e 20 92 85 5c diff --git a/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.jar b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.jar new file mode 100644 index 0000000..49aaa39 Binary files /dev/null and b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.jar differ diff --git a/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.rapc b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.rapc new file mode 100644 index 0000000..c2d282c --- /dev/null +++ b/NFC/LLCPDemo/deliverables/Standard/7.1.0/LLCPDemo.rapc @@ -0,0 +1,10 @@ +MIDlet-Name: LLCPDemo +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: LLCPDemo.jar +MIDlet-Jar-Size: 0 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: LLCPDemo,img/my_icon.png, +RIM-MIDlet-Flags-1: 0 + diff --git a/NFC/LLCPDemo/deliverables/Standard/LLCPDemo.alx b/NFC/LLCPDemo/deliverables/Standard/LLCPDemo.alx new file mode 100644 index 0000000..bd5389b --- /dev/null +++ b/NFC/LLCPDemo/deliverables/Standard/LLCPDemo.alx @@ -0,0 +1,31 @@ + + + + LLCPDemo + + + + + + 1.0.0 + + + BlackBerry Developer + + + Copyright (c) 2012 BlackBerry Developer + + + + 7.1.0 + + + LLCPDemo.cod + + + + + + + + diff --git a/NFC/LLCPDemo/res/img/icon.png b/NFC/LLCPDemo/res/img/icon.png new file mode 100644 index 0000000..193950c Binary files /dev/null and b/NFC/LLCPDemo/res/img/icon.png differ diff --git a/NFC/LLCPDemo/res/img/my_icon.png b/NFC/LLCPDemo/res/img/my_icon.png new file mode 100644 index 0000000..a5c0dcd Binary files /dev/null and b/NFC/LLCPDemo/res/img/my_icon.png differ diff --git a/NFC/LLCPDemo/res/img/rcv_icon.png b/NFC/LLCPDemo/res/img/rcv_icon.png new file mode 100644 index 0000000..9b58b0e Binary files /dev/null and b/NFC/LLCPDemo/res/img/rcv_icon.png differ diff --git a/NFC/LLCPDemo/res/img/receiver_clicked.png b/NFC/LLCPDemo/res/img/receiver_clicked.png new file mode 100644 index 0000000..8be7b91 Binary files /dev/null and b/NFC/LLCPDemo/res/img/receiver_clicked.png differ diff --git a/NFC/LLCPDemo/res/img/receiver_focus.png b/NFC/LLCPDemo/res/img/receiver_focus.png new file mode 100644 index 0000000..4e4678f Binary files /dev/null and b/NFC/LLCPDemo/res/img/receiver_focus.png differ diff --git a/NFC/LLCPDemo/res/img/receiver_no_focus.png b/NFC/LLCPDemo/res/img/receiver_no_focus.png new file mode 100644 index 0000000..4f95f58 Binary files /dev/null and b/NFC/LLCPDemo/res/img/receiver_no_focus.png differ diff --git a/NFC/LLCPDemo/res/img/sender_clicked.png b/NFC/LLCPDemo/res/img/sender_clicked.png new file mode 100644 index 0000000..c3ed3cb Binary files /dev/null and b/NFC/LLCPDemo/res/img/sender_clicked.png differ diff --git a/NFC/LLCPDemo/res/img/sender_focus.png b/NFC/LLCPDemo/res/img/sender_focus.png new file mode 100644 index 0000000..a201f12 Binary files /dev/null and b/NFC/LLCPDemo/res/img/sender_focus.png differ diff --git a/NFC/LLCPDemo/res/img/sender_no_focus.png b/NFC/LLCPDemo/res/img/sender_no_focus.png new file mode 100644 index 0000000..6894ea0 Binary files /dev/null and b/NFC/LLCPDemo/res/img/sender_no_focus.png differ diff --git a/NFC/LLCPDemo/res/img/snd_icon.png b/NFC/LLCPDemo/res/img/snd_icon.png new file mode 100644 index 0000000..92ec339 Binary files /dev/null and b/NFC/LLCPDemo/res/img/snd_icon.png differ diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/Constants.java b/NFC/LLCPDemo/src/nfc/sample/llcp/Constants.java new file mode 100644 index 0000000..472eeb4 --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/Constants.java @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp; + +public class Constants { + + public static final String MYAPP_VERSION = "1.0.0"; + + public static final int SND_BTN_STATE=0; + public static final int RCV_BTN_STATE=0; + + public static final int SND=0; + public static final int RCV=1; +} \ No newline at end of file diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/LLCPDemo.java b/NFC/LLCPDemo/src/nfc/sample/llcp/LLCPDemo.java new file mode 100644 index 0000000..419183d --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/LLCPDemo.java @@ -0,0 +1,33 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp; + +import net.rim.device.api.ui.UiApplication; +import nfc.sample.llcp.ui.RoleSelectionScreen; + +public class LLCPDemo extends UiApplication { + + public static void main(String[] args) { + Utilities.initLogging(); + LLCPDemo app = new LLCPDemo(); + app.enterEventDispatcher(); + } + + private LLCPDemo() { + pushScreen(new RoleSelectionScreen()); + } + +} diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/Utilities.java b/NFC/LLCPDemo/src/nfc/sample/llcp/Utilities.java new file mode 100644 index 0000000..5731dcf --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/Utilities.java @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp; + +import java.io.UnsupportedEncodingException; + +import net.rim.device.api.system.EventLogger; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.component.Dialog; + +public class Utilities { + + private static final long MYAPP_ID = 0xde587f9e4b151ce7L; + private static final String MYAPP_NAME = "LLCPDemo"; + + public static void log(String logMessage) { + try { + boolean ok = EventLogger.logEvent(MYAPP_ID, logMessage.getBytes("US-ASCII"), EventLogger.INFORMATION); + } catch(UnsupportedEncodingException e) { + } + } + + public static void initLogging() { + EventLogger.register(MYAPP_ID, MYAPP_NAME, EventLogger.VIEWER_STRING); + } + + public static void popupMessage(String message) { + synchronized(UiApplication.getEventLock()) { + Dialog.inform(message); + } + } + + public static boolean isOdd(int number) { + int remainder = number % 2; + return remainder == 1; + } +} diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/buttons/MsbConfig.java b/NFC/LLCPDemo/src/nfc/sample/llcp/buttons/MsbConfig.java new file mode 100644 index 0000000..44605af --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/buttons/MsbConfig.java @@ -0,0 +1,41 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp.buttons; + +import java.util.Hashtable; + + +/** + * A MultiStateButtonField has a series of states, each of which has multiple visual indications depending on + * focused/unfocused + * click/unclick + * + */ +public class MsbConfig { + + private Hashtable states = new Hashtable(); + + public void addState(MsbState state) { + Integer key = new Integer(state.getState_id()); + states.put(key,state); + } + + public MsbState getState(int state_id) { + MsbState state = (MsbState) states.get(new Integer(state_id)); + return state; + } + +} diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/buttons/MsbState.java b/NFC/LLCPDemo/src/nfc/sample/llcp/buttons/MsbState.java new file mode 100644 index 0000000..d714b9a --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/buttons/MsbState.java @@ -0,0 +1,104 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp.buttons; + +import net.rim.device.api.system.Bitmap; + +public class MsbState { + + public static final int DEFAULT_STATE=0; + + private int state_id; // zero is the default state + private String state_description; // e.g. "Service is currently ON" + private String state_label; // for display on buttons e.g. "ON" + + private Bitmap bmp_unfocused; + private Bitmap bmp_focused; + private Bitmap bmp_clicked; + private Bitmap bmp_unclicked; + + public MsbState(int state_id, String state_description, String state_label) { + this.state_id = state_id; + this.state_description = state_description; + this.state_label = state_label; + } + + public boolean equals(Object obj) { + if (obj instanceof MsbState) { + if (((MsbState) obj).getState_id() == this.state_id) { + return true; + } + } + return false; + } + + public int getState_id() { + return state_id; + } + + public void setState_id(int state_id) { + this.state_id = state_id; + } + + public String getState_description() { + return state_description; + } + + public void setState_description(String state_description) { + this.state_description = state_description; + } + + public String getState_label() { + return state_label; + } + + public void setState_label(String state_label) { + this.state_label = state_label; + } + + public Bitmap getbmp_unfocused() { + return bmp_unfocused; + } + + public void setbmp_unfocused(Bitmap bmp_unfocused) { + this.bmp_unfocused = bmp_unfocused; + } + + public Bitmap getbmp_focused() { + return bmp_focused; + } + + public void setbmp_focused(Bitmap bmp_focused) { + this.bmp_focused = bmp_focused; + } + + public Bitmap getbmp_clicked() { + return bmp_clicked; + } + + public void setbmp_clicked(Bitmap bmp_clicked) { + this.bmp_clicked = bmp_clicked; + } + + public Bitmap getbmp_unclicked() { + return bmp_unclicked; + } + + public void setbmp_unclicked(Bitmap bmp_unclicked) { + this.bmp_unclicked = bmp_unclicked; + } + +} diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/buttons/MultiStateButtonField.java b/NFC/LLCPDemo/src/nfc/sample/llcp/buttons/MultiStateButtonField.java new file mode 100644 index 0000000..21209a7 --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/buttons/MultiStateButtonField.java @@ -0,0 +1,147 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp.buttons; + +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.Graphics; +import net.rim.device.api.ui.TouchEvent; +import nfc.sample.llcp.Utilities; + +public class MultiStateButtonField extends Field { + + private MsbConfig config; + private int current_state; + private Bitmap current_bitmap; + private AlwaysExecutableCommand command; + + public MultiStateButtonField(MsbConfig config, AlwaysExecutableCommand command,int initial_state, long style) { + super(style); + this.config = config; + this.command = command; + this.current_state = initial_state; + current_bitmap = config.getState(initial_state).getbmp_unfocused(); + } + + protected void paint(Graphics graphics) { + if (current_bitmap != null) { + graphics.drawBitmap(0, 0, current_bitmap.getWidth(), current_bitmap.getHeight(), current_bitmap, 0, 0); + } else { + Utilities.log("XXXX "+config.getState(current_state).getState_label()+"-ERROR:current_bitmap=null"); + } + } + + protected void drawFocus(Graphics graphics, + boolean on) { + } + + public void setMsbState(int state_id) { + current_state = state_id; + current_bitmap = config.getState(state_id).getbmp_unfocused(); + } + + public int getMsbState() { + return current_state; + } + + protected boolean navigationClick(int status, + int time) { + setFocus(); + if (config.getState(current_state).getbmp_clicked() != null) { + current_bitmap = config.getState(current_state).getbmp_clicked(); + invalidate(); + } + return true; + } + + protected boolean navigationUnclick(int status, + int time) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " : " +"navigationUnclick"); + if (config.getState(current_state).getbmp_unclicked() != null) { + current_bitmap = config.getState(current_state).getbmp_unclicked(); + invalidate(); + } + // pass button so we can check its state + command.execute(null, this); + return true; + } + + protected boolean touchEvent(TouchEvent message) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " : " +"touchEvent"); + if (message.getY(1) < 0) { + return false; + } + if (message.getY(1) > getHeight()){ + return false; + } + if (message.getX(1) < 0){ + return false; + } + if (message.getX(1) > getWidth()){ + return false; + } + + setFocus(); + if (message.getEvent() == TouchEvent.DOWN && config.getState(current_state).getbmp_clicked() != null) { + current_bitmap = config.getState(current_state).getbmp_clicked(); + invalidate(); + return true; + } + if (message.getEvent() == TouchEvent.UP && config.getState(current_state).getbmp_focused() != null) { + current_bitmap = config.getState(current_state).getbmp_focused(); + invalidate(); +// Utilities.log("XXXX " + Thread.currentThread().getName() + " : " +"touchEvent executing command"); +// command.execute(null, this); + return true; + } + return false; + } + + protected void onFocus(int direction) { + if (config.getState(current_state).getbmp_focused() != null) { + current_bitmap = config.getState(current_state).getbmp_focused(); + invalidate(); + } + } + + protected void onUnfocus() { + if (config.getState(current_state).getbmp_unfocused() != null) { + current_bitmap = config.getState(current_state).getbmp_unfocused(); + invalidate(); + } + } + + public void setImage() { + current_bitmap = config.getState(current_state).getbmp_focused(); + } + + public boolean isFocusable() { + return true; + } + + protected void layout(int width, int height) { + setExtent(current_bitmap.getWidth(),current_bitmap.getHeight()); + } + + public int getPreferredWidth() { + return current_bitmap.getWidth(); + } + + public int getPreferredHeight() { + return current_bitmap.getHeight(); + } +} diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/commands/ReceiveCommand.java b/NFC/LLCPDemo/src/nfc/sample/llcp/commands/ReceiveCommand.java new file mode 100644 index 0000000..0825336 --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/commands/ReceiveCommand.java @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp.commands; + +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.command.ReadOnlyCommandMetadata; +import net.rim.device.api.ui.UiApplication; +import nfc.sample.llcp.Constants; +import nfc.sample.llcp.Utilities; +import nfc.sample.llcp.nfc.LlcpReceiver; +import nfc.sample.llcp.ui.ActivityScreen; + +public class ReceiveCommand extends AlwaysExecutableCommand { + + public void execute(ReadOnlyCommandMetadata metadata, Object context) { + synchronized(UiApplication.getUiApplication().getEventLock()) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " : " +"ReceiveCommand"); + ActivityScreen screen = new ActivityScreen(Constants.RCV); + LlcpReceiver receiver = new LlcpReceiver(screen); + receiver.start(); + UiApplication.getUiApplication().pushScreen(screen); + } + } + +} diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/commands/SendCommand.java b/NFC/LLCPDemo/src/nfc/sample/llcp/commands/SendCommand.java new file mode 100644 index 0000000..bdfa049 --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/commands/SendCommand.java @@ -0,0 +1,33 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp.commands; + +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.command.ReadOnlyCommandMetadata; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.container.MainScreen; +import nfc.sample.llcp.ui.ClientTextScreen; + +public class SendCommand extends AlwaysExecutableCommand { + + public void execute(ReadOnlyCommandMetadata metadata, Object context) { + synchronized(UiApplication.getUiApplication().getEventLock()) { + MainScreen screen = new ClientTextScreen(); + UiApplication.getUiApplication().pushScreen(screen); + } + } + +} diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/nfc/LlcpReceiver.java b/NFC/LLCPDemo/src/nfc/sample/llcp/nfc/LlcpReceiver.java new file mode 100644 index 0000000..e4f50f8 --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/nfc/LlcpReceiver.java @@ -0,0 +1,107 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp.nfc; + +import java.io.IOException; +import java.io.InputStream; + +import javax.microedition.io.Connector; + +import net.rim.device.api.io.IOUtilities; +import net.rim.device.api.io.nfc.llcp.LLCPConnection; +import net.rim.device.api.io.nfc.llcp.LLCPConnectionNotifier; +import net.rim.device.api.util.Arrays; +import nfc.sample.llcp.Utilities; +import nfc.sample.llcp.ui.ActivityScreen; + +public class LlcpReceiver implements Runnable { + + private ActivityScreen _screen; + + public LlcpReceiver(ActivityScreen screen) { + _screen = screen; + _screen.logEvent("Constructing LlcpReceiver"); + } + + public void run() { + _screen.logEvent("LlcpReceiver starting..."); + LLCPConnectionNotifier llcp_conn_notifier = null; + LLCPConnection llcp_conn = null; + InputStream in = null; + boolean completed_ok = false; + try { + // note mode=server + _screen.logEvent("Obtaining connection notifier"); + llcp_conn_notifier = (LLCPConnectionNotifier) Connector.open("urn:nfc:sn:llcpdemo;mode=server;timeout=120"); + _screen.logEvent("Got LlcpConnectionNotifier"); + llcp_conn = llcp_conn_notifier.acceptAndOpen(); + _screen.logEvent("Got LlcpConnection"); + in = llcp_conn.getInputStream(); + _screen.logEvent("Got InputStream"); + byte[] data = new byte[256]; + int bytesRead = in.read(data, 0, 256); + _screen.logEvent("Rcvd " + data.length + " bytes of data"); + String text = new String(data, "US-ASCII"); + _screen.logEvent("Rcvd text:" + text); + completed_ok = true; + } catch(Exception e) { + _screen.logEvent(e.getClass().getName() + ":" + e.getMessage()); + _screen.logEvent("LlcpReceiver is exiting abnormally"); + } finally { + close(llcp_conn_notifier, llcp_conn, in); + } + if(completed_ok) { + _screen.logEvent("LlcpReceiver finished OK"); + } + } + + public void close(LLCPConnectionNotifier llcp_conn_notifier, LLCPConnection llcp_conn, InputStream in) { + try { + if(in != null) { + in.close(); + _screen.logEvent("Stream closed"); + } + } catch(Exception e) { + _screen.logEvent("Stream closed error, " + e.getMessage()); + _screen.logEvent(e.getClass().getName() + ":" + e.getMessage()); + } + try { + if(llcp_conn != null) { + llcp_conn.close(); + _screen.logEvent("Connection closed"); + } + } catch(Exception e) { + _screen.logEvent("Connection closed error, " + e.getMessage()); + _screen.logEvent(e.getClass().getName() + ":" + e.getMessage()); + } + try { + if(llcp_conn_notifier != null) { + llcp_conn_notifier.close(); + _screen.logEvent("Connection notifier closed"); + } + } catch(Exception e) { + _screen.logEvent("Connection notifier closed error, " + e.getMessage()); + _screen.logEvent(e.getClass().getName() + ":" + e.getMessage()); + } + } + + public void start() { + Utilities.log("XXXX " + Thread.currentThread().getName() + " : " + "starting LcpReceiver thread"); + Thread thread = new Thread(this); + thread.start(); + } + +} diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/nfc/LlcpSender.java b/NFC/LLCPDemo/src/nfc/sample/llcp/nfc/LlcpSender.java new file mode 100644 index 0000000..66f3cb8 --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/nfc/LlcpSender.java @@ -0,0 +1,97 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp.nfc; + +import java.io.OutputStream; +import javax.microedition.io.Connector; +import net.rim.device.api.io.nfc.llcp.LLCPConnection; +import nfc.sample.llcp.ui.ActivityScreen; + +public class LlcpSender implements Runnable { + + private ActivityScreen _screen; + private String _message; + + public LlcpSender(ActivityScreen screen, String message) { + _screen = screen; + _message = message; + } + + public void run() { + _screen.logEvent("LlcpSender starting..."); + LLCPConnection llcp_conn = null; + OutputStream out = null; + boolean completed_ok = false; + try { + // note mode=client + _screen.logEvent("Obtaining connection"); + llcp_conn = (LLCPConnection) Connector.open("urn:nfc:sn:llcpdemo;mode=client"); + _screen.logEvent("Got LlcpConnection"); + out = llcp_conn.getOutputStream(); + _screen.logEvent("Got OutputStream"); + byte[] data = _message.getBytes("US-ASCII"); + out.write(data, 0, data.length); + out.flush(); + _screen.logEvent("Sent " + data.length + " bytes of data"); + completed_ok = true; + } catch(Exception e) { + _screen.logEvent(e.getClass().getName() + ":" + e.getMessage()); + _screen.logEvent("LlcpSender is exiting abnormally"); + } finally { + _screen.logEvent("Closing resources......"); + // make sure we don't close and interrupt the receiver before the data we sent has been read + delay(1000); + close(llcp_conn, out); + } + if (completed_ok) { + _screen.logEvent("LlcpSender finished OK"); + } + } + + private void delay(int delay_ms) { + try { + Thread.sleep(delay_ms); + } catch(InterruptedException e) { + } + } + + public void close(LLCPConnection llcp_conn, OutputStream out) { + try { + if(out != null) { + out.close(); + _screen.logEvent("Stream closed"); + } + } catch(Exception e) { + _screen.logEvent(e.getClass().getName() + ":" + e.getMessage()); + _screen.logEvent("LlcpSender stream close error"); + } + try { + if(llcp_conn != null) { + llcp_conn.close(); + _screen.logEvent("Connection closed"); + } + } catch(Exception e) { + _screen.logEvent(e.getClass().getName() + ":" + e.getMessage()); + _screen.logEvent("LlcpSender connection close error"); + } + } + + public void start() { + Thread thread = new Thread(this); + thread.start(); + } + +} diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/ui/ActivityScreen.java b/NFC/LLCPDemo/src/nfc/sample/llcp/ui/ActivityScreen.java new file mode 100644 index 0000000..640b42c --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/ui/ActivityScreen.java @@ -0,0 +1,112 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp.ui; + +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.ui.Color; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.Font; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.component.BitmapField; +import net.rim.device.api.ui.component.LabelField; +import net.rim.device.api.ui.component.RichTextField; +import net.rim.device.api.ui.component.SeparatorField; +import net.rim.device.api.ui.container.HorizontalFieldManager; +import net.rim.device.api.ui.container.MainScreen; +import nfc.sample.llcp.Constants; +import nfc.sample.llcp.Utilities; + +public final class ActivityScreen extends MainScreen { + + private ActivityScreen _screen; + + private HorizontalFieldManager icon_row = new HorizontalFieldManager(); + private Bitmap snd_icon = Bitmap.getBitmapResource("snd_icon.png"); + private Bitmap rcv_icon = Bitmap.getBitmapResource("rcv_icon.png"); + + private BitmapField icon; + + private String text = ""; + + private SeparatorField separator1 = new SeparatorField(Field.USE_ALL_WIDTH); + private SeparatorField separator2 = new SeparatorField(Field.USE_ALL_WIDTH); + + private RichTextField heading = new RichTextField(); + + private Font heading_font; + + private AlternatingListField _log = new AlternatingListField(Color.WHITE,Color.LIGHTGRAY,Field.USE_ALL_WIDTH); + + private int _emulation_type; + + public ActivityScreen(int role) { + super(MainScreen.HORIZONTAL_SCROLL); + Utilities.log("XXXX " + Thread.currentThread().getName() + " : " +"constructing ActivityScreen"); + this._screen = this; + _emulation_type = role; + + setTitle("LLCPDemo V" + Constants.MYAPP_VERSION); + + if(role == Constants.SND) { + indicateSender(); + } else { + indicateReceiver(); + } + + Font default_font = Font.getDefault(); + heading_font = default_font.derive(Font.BOLD, 24); + + heading.setText("Event Log (newest items first)"); + heading.setFont(heading_font); + + add(separator1); + add(heading); + add(separator2); + add(_log); + + } + + private void indicateSender() { + icon = new BitmapField(snd_icon); + icon_row.add(icon); + icon_row.add(new LabelField(" - LLCP sender")); + add(icon_row); + } + + private void indicateReceiver() { + icon = new BitmapField(rcv_icon); + icon_row.add(icon); + icon_row.add(new LabelField(" - LLCP receiver")); + add(icon_row); + } + + public void logEvent(String event_message) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " : " +event_message); + synchronized (UiApplication.getEventLock()) { + _log.insert(0, event_message); + _log.setSelectedIndex(0); + } + } + + public String getResponse_text() { + return text; + } + + public void setResponse_text(String response_text) { + this.text = response_text; + } + +} diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/ui/AlternatingListField.java b/NFC/LLCPDemo/src/nfc/sample/llcp/ui/AlternatingListField.java new file mode 100644 index 0000000..fa89109 --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/ui/AlternatingListField.java @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp.ui; + +import net.rim.device.api.ui.Graphics; +import net.rim.device.api.ui.component.ListField; +import net.rim.device.api.ui.component.ObjectListField; +import nfc.sample.llcp.Utilities; + +public class AlternatingListField extends ObjectListField { + + private int _bg_even; + private int _bg_odd; + + public AlternatingListField(int bg_even, int bg_odd, long style) { + super(style); + _bg_even = bg_even; + _bg_odd = bg_odd; + } + + public void drawListRow(ListField listField, Graphics graphics, int index, int y, int width) { + if(index != getSelectedIndex()) { + if(Utilities.isOdd(index)) { + graphics.setBackgroundColor(_bg_odd); + } else { + graphics.setBackgroundColor(_bg_even); + } + graphics.clear(); + } + super.drawListRow(listField, graphics, index, y, width); + } + +} diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/ui/ClientActivityScreen.java b/NFC/LLCPDemo/src/nfc/sample/llcp/ui/ClientActivityScreen.java new file mode 100644 index 0000000..fb9b849 --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/ui/ClientActivityScreen.java @@ -0,0 +1,107 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp.ui; + +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.ui.Color; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.Font; +import net.rim.device.api.ui.component.BitmapField; +import net.rim.device.api.ui.component.LabelField; +import net.rim.device.api.ui.component.RichTextField; +import net.rim.device.api.ui.component.SeparatorField; +import net.rim.device.api.ui.container.HorizontalFieldManager; +import net.rim.device.api.ui.container.MainScreen; +import nfc.sample.llcp.Constants; + +public final class ClientActivityScreen extends MainScreen { + + private ClientActivityScreen _screen; + + private HorizontalFieldManager icon_row = new HorizontalFieldManager(); + private Bitmap sc_icon = Bitmap.getBitmapResource("sc_icon.png"); + private Bitmap reader_icon = Bitmap.getBitmapResource("reader_icon.png"); + + private BitmapField icon; + + private String response_text = "Send to other device"; + + private SeparatorField separator1 = new SeparatorField(Field.USE_ALL_WIDTH); + private SeparatorField separator2 = new SeparatorField(Field.USE_ALL_WIDTH); + + private RichTextField heading = new RichTextField(); + + private Font heading_font; + + private AlternatingListField _log = new AlternatingListField(Color.WHITE,Color.LIGHTGRAY,Field.USE_ALL_WIDTH); + + private int _emulation_type; + + /** + * Creates a new NfcVirtTargScreen object + */ + public ClientActivityScreen(int emulation_type) { + + super(MainScreen.HORIZONTAL_SCROLL); + this._screen = this; + _emulation_type = emulation_type; + + setTitle("LLCPDemo V" + Constants.MYAPP_VERSION); + +// if(emulation_type == Constants.EMULATE_SC) { +// emulateSmartCard(); +// } else { +// } + + Font default_font = Font.getDefault(); + heading_font = default_font.derive(Font.BOLD, 24); + + heading.setText("Event Log (newest items first)"); + heading.setFont(heading_font); + + add(separator1); + add(heading); + add(separator2); + add(_log); + + } + + private void emulateSmartCard() { + icon = new BitmapField(sc_icon); + icon_row.add(icon); + icon_row.add(new LabelField(" - emulating smart card")); + add(icon_row); +// mi_response.setCommandContext(this); +// mi_response.setCommand(new Command(new ResponseTextCommand())); +// addMenuItem(mi_response); + + } + + public void logEvent(String event_message) { + _log.insert(0, event_message); + _log.setSelectedIndex(0); + } + + public String getResponse_text() { + return response_text; + } + + public void setResponse_text(String response_text) { + this.response_text = response_text; + } + + +} diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/ui/ClientTextScreen.java b/NFC/LLCPDemo/src/nfc/sample/llcp/ui/ClientTextScreen.java new file mode 100644 index 0000000..ece7abe --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/ui/ClientTextScreen.java @@ -0,0 +1,55 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp.ui; + +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.FieldChangeListener; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.component.ButtonField; +import net.rim.device.api.ui.component.EditField; +import net.rim.device.api.ui.container.MainScreen; +import nfc.sample.llcp.Constants; +import nfc.sample.llcp.nfc.LlcpSender; + +public class ClientTextScreen extends MainScreen { + + private EditField text = new EditField("Send to other device: ", "Hello! LLCP is useful!"); + private ButtonField btn_continue = new ButtonField("Continue", ButtonField.CONSUME_CLICK); + + private FieldChangeListener listener = new FieldChangeListener() { + + public void fieldChanged(Field field, int context) { + if (field == btn_continue) { + ActivityScreen screen = new ActivityScreen(Constants.SND); + LlcpSender sender = new LlcpSender(screen,text.getText()); + sender.start(); + UiApplication.getUiApplication().pushScreen(screen); + } + } + }; + + public ClientTextScreen() { + setTitle("LLCPDemo V" + Constants.MYAPP_VERSION); + add(text); + add(btn_continue); + btn_continue.setChangeListener(listener); + } + + public boolean onSavePrompt() { + return true; + } + +} diff --git a/NFC/LLCPDemo/src/nfc/sample/llcp/ui/RoleSelectionScreen.java b/NFC/LLCPDemo/src/nfc/sample/llcp/ui/RoleSelectionScreen.java new file mode 100644 index 0000000..a172eb8 --- /dev/null +++ b/NFC/LLCPDemo/src/nfc/sample/llcp/ui/RoleSelectionScreen.java @@ -0,0 +1,108 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.llcp.ui; + +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.system.Display; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.FocusChangeListener; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.component.LabelField; +import net.rim.device.api.ui.container.AbsoluteFieldManager; +import net.rim.device.api.ui.container.MainScreen; +import nfc.sample.llcp.Constants; +import nfc.sample.llcp.buttons.MsbConfig; +import nfc.sample.llcp.buttons.MsbState; +import nfc.sample.llcp.buttons.MultiStateButtonField; +import nfc.sample.llcp.commands.ReceiveCommand; +import nfc.sample.llcp.commands.SendCommand; + +public class RoleSelectionScreen extends MainScreen { + + private Bitmap rcv_focused = Bitmap.getBitmapResource("receiver_focus.png"); + private Bitmap rcv_unfocused = Bitmap.getBitmapResource("receiver_no_focus.png"); + private Bitmap rcv_clicked = Bitmap.getBitmapResource("receiver_clicked.png"); + + private Bitmap snd_focused = Bitmap.getBitmapResource("sender_focus.png"); + private Bitmap snd_unfocused = Bitmap.getBitmapResource("sender_no_focus.png"); + private Bitmap snd_clicked = Bitmap.getBitmapResource("sender_clicked.png"); + + private MultiStateButtonField msbf_rcv; + private MultiStateButtonField msbf_snd; + + private LabelField ui_msg=new LabelField("",Field.FIELD_HCENTER); + + private int focused_button = 0; + + private FocusChangeListener focus_listener = new FocusChangeListener() { + + public void focusChanged(Field field, int eventType) { + if (field == msbf_rcv) { + focused_button = 0; + } + if (field == msbf_snd) { + focused_button = 1; + } + } + }; + + public RoleSelectionScreen() { + super(USE_ALL_HEIGHT | USE_ALL_WIDTH | FIELD_HCENTER | FIELD_VCENTER | NO_VERTICAL_SCROLL); + setTitle("LLCPDemo V" + Constants.MYAPP_VERSION); + + AbsoluteFieldManager btn_row = new AbsoluteFieldManager(); + // bitmaps are 120 x 120 + int hgap = (int) ((Display.getWidth() - 240) / 3); + int vgap = (int) (Display.getHeight() - 120) / 2; + int x1= hgap; + int x2= x1 + 120 + hgap; + int y = (int) (vgap * 0.75); + + MsbConfig snd_btn_config = new MsbConfig(); + MsbState snd_btn_state = new MsbState(Constants.SND_BTN_STATE, "Send data over LLCP", "Send data over LLCP"); + snd_btn_state.setbmp_focused(snd_focused); + snd_btn_state.setbmp_unfocused(snd_unfocused); + snd_btn_state.setbmp_clicked(snd_clicked); + snd_btn_state.setbmp_unclicked(snd_focused); + snd_btn_config.addState(snd_btn_state); + msbf_snd = new MultiStateButtonField(snd_btn_config, new SendCommand(), 0, Field.FIELD_HCENTER); + btn_row.add(msbf_snd,x1,y); + + MsbConfig rcv_btn_config = new MsbConfig(); + MsbState rcv_btn_state = new MsbState(Constants.RCV_BTN_STATE, "Receive data over LLCP", "Receive data over LLCP"); + rcv_btn_state.setbmp_focused(rcv_focused); + rcv_btn_state.setbmp_unfocused(rcv_unfocused); + rcv_btn_state.setbmp_clicked(rcv_clicked); + rcv_btn_state.setbmp_unclicked(rcv_focused); + rcv_btn_config.addState(rcv_btn_state); + msbf_rcv = new MultiStateButtonField(rcv_btn_config, new ReceiveCommand(), 0, Field.FIELD_HCENTER); + btn_row.add(msbf_rcv,x2,y); + + msbf_rcv.setFocusListener(focus_listener); + msbf_snd.setFocusListener(focus_listener); + + add(btn_row); + add(ui_msg); + } + + private void setMessage(String message) { + synchronized (UiApplication.getEventLock()) { + ui_msg.setText(message); + } + + } + +} diff --git a/NFC/NfcMidlet2/.classpath b/NFC/NfcMidlet2/.classpath new file mode 100644 index 0000000..ba75cf6 --- /dev/null +++ b/NFC/NfcMidlet2/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/NFC/NfcMidlet2/.project b/NFC/NfcMidlet2/.project new file mode 100644 index 0000000..7406fb7 --- /dev/null +++ b/NFC/NfcMidlet2/.project @@ -0,0 +1,29 @@ + + + NfcMidlet2 + + + + + + net.rim.ejde.internal.builder.BlackBerryPreprocessBuilder + + + + + net.rim.ejde.internal.builder.BlackBerryResourcesBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + + net.rim.ejde.BlackBerryPreProcessNature + net.rim.ejde.BlackBerryProjectCoreNature + org.eclipse.jdt.core.javanature + + diff --git a/NFC/NfcMidlet2/.settings/net.rim.browser.tools.debug.widget.prefs b/NFC/NfcMidlet2/.settings/net.rim.browser.tools.debug.widget.prefs new file mode 100644 index 0000000..b516d21 --- /dev/null +++ b/NFC/NfcMidlet2/.settings/net.rim.browser.tools.debug.widget.prefs @@ -0,0 +1,3 @@ +#Wed Jan 04 11:49:56 GMT 2012 +eclipse.preferences.version=1 +outputfolder=build diff --git a/NFC/NfcMidlet2/.settings/org.eclipse.jdt.core.prefs b/NFC/NfcMidlet2/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..34da513 --- /dev/null +++ b/NFC/NfcMidlet2/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Wed Jan 04 11:49:27 GMT 2012 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore +org.eclipse.jdt.core.compiler.source=1.3 diff --git a/NFC/NfcMidlet2/BlackBerry_App_Descriptor.xml b/NFC/NfcMidlet2/BlackBerry_App_Descriptor.xml new file mode 100644 index 0000000..b3ffe73 --- /dev/null +++ b/NFC/NfcMidlet2/BlackBerry_App_Descriptor.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NFC/NfcMidlet2/NfcMidlet2.jad b/NFC/NfcMidlet2/NfcMidlet2.jad new file mode 100644 index 0000000..94dbb74 --- /dev/null +++ b/NFC/NfcMidlet2/NfcMidlet2.jad @@ -0,0 +1,16 @@ +MIDlet-Name: NfcMidlet2 +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: NfcMidlet2.jar +MIDlet-Jar-Size: 8925 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: NfcMidlet2,img/icon.png,nfc.sample.midlet.NfcMidlet2 +RIM-MIDlet-Flags-1: 1 +Manifest-Version: 1.0 +RIM-COD-URL: NfcMidlet2.cod +RIM-COD-Size: 11188 +RIM-COD-Creation-Time: 1330098005 +RIM-COD-Module-Name: NfcMidlet2 +RIM-COD-Module-Dependencies: net_rim_cldc,net_rim_nfc +RIM-COD-SHA1: cc 37 55 8b 13 7a 75 54 5c 21 37 9d e2 8a e6 3a b2 72 c9 c6 diff --git a/NFC/NfcMidlet2/README.md b/NFC/NfcMidlet2/README.md new file mode 100644 index 0000000..ad5ea06 --- /dev/null +++ b/NFC/NfcMidlet2/README.md @@ -0,0 +1,43 @@ +# NfcMidlet2 Sample + + +The purpose of this application is to demonstrate how to write a J2ME MIDlet for BlackBerry which can receive HCI transaction notifications relating NFC card emulation activity. + +The sample code for this application is Open Source under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0.html). + +**Applies To** + +* [BlackBerry Java SDK for Smartphones](http://us.blackberry.com/developers/javaappdev/) + + +**Author(s)** + +* [Martin Woolley](https://github.com/mdwoolley) +* [John Murray](https://github.com/jcmurray) + + +**Dependencies** + +1. BlackBerry Device Software 7.0 and above. + + +**Known Issues** + +None + +**To contribute code to this repository you must be [signed up as an official contributor](http://blackberry.github.com/howToContribute.html).** + + +## Contributing Changes + +Please see the [README](https://github.com/blackberry/BlackBerry-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. + + +## Bug Reporting and Feature Requests + +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/BlackBerry-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/BlackBerry-Java/issues). + + +## Disclaimer + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/NFC/NfcMidlet2/bin/img/icon.png b/NFC/NfcMidlet2/bin/img/icon.png new file mode 100644 index 0000000..193950c Binary files /dev/null and b/NFC/NfcMidlet2/bin/img/icon.png differ diff --git a/NFC/NfcMidlet2/bin/img/photothumb.db b/NFC/NfcMidlet2/bin/img/photothumb.db new file mode 100644 index 0000000..fa58b80 Binary files /dev/null and b/NFC/NfcMidlet2/bin/img/photothumb.db differ diff --git a/NFC/NfcMidlet2/bin/nfc/sample/midlet/NfcMidlet2$MyTransactionListener.class b/NFC/NfcMidlet2/bin/nfc/sample/midlet/NfcMidlet2$MyTransactionListener.class new file mode 100644 index 0000000..b23885f Binary files /dev/null and b/NFC/NfcMidlet2/bin/nfc/sample/midlet/NfcMidlet2$MyTransactionListener.class differ diff --git a/NFC/NfcMidlet2/bin/nfc/sample/midlet/NfcMidlet2.class b/NFC/NfcMidlet2/bin/nfc/sample/midlet/NfcMidlet2.class new file mode 100644 index 0000000..86221d6 Binary files /dev/null and b/NFC/NfcMidlet2/bin/nfc/sample/midlet/NfcMidlet2.class differ diff --git a/NFC/NfcMidlet2/bin/nfc/sample/midlet/Utilities.class b/NFC/NfcMidlet2/bin/nfc/sample/midlet/Utilities.class new file mode 100644 index 0000000..5cb9c57 Binary files /dev/null and b/NFC/NfcMidlet2/bin/nfc/sample/midlet/Utilities.class differ diff --git a/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.cod b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.cod new file mode 100644 index 0000000..77af869 Binary files /dev/null and b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.cod differ diff --git a/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.csl b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.csl new file mode 100644 index 0000000..182d9d8 --- /dev/null +++ b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.csl @@ -0,0 +1,2 @@ +52525400=RIM Runtime API +4e464352=NFCRoutingAPI diff --git a/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.cso b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.cso new file mode 100644 index 0000000..1a589a3 --- /dev/null +++ b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.cso @@ -0,0 +1,5 @@ +33000000=RIMAPPSA2 +52424200=RIM Blackberry Apps API +52434900=RIM Crypto API - Internal +52435200=RIM Crypto API - RIM +4e464352=NFCRoutingAPI diff --git a/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.debug b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.debug new file mode 100644 index 0000000..1cb1228 Binary files /dev/null and b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.debug differ diff --git a/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.jad b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.jad new file mode 100644 index 0000000..055bdb7 --- /dev/null +++ b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.jad @@ -0,0 +1,16 @@ +MIDlet-Name: NfcMidlet2 +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: NfcMidlet2.jar +MIDlet-Jar-Size: 9499 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: NfcMidlet2,img/icon.png,nfc.sample.midlet.NfcMidlet2 +RIM-MIDlet-Flags-1: 1 +Manifest-Version: 1.0 +RIM-COD-URL: NfcMidlet2.cod +RIM-COD-Size: 14668 +RIM-COD-Creation-Time: 1333461343 +RIM-COD-Module-Name: NfcMidlet2 +RIM-COD-Module-Dependencies: net_rim_cldc,net_rim_nfc +RIM-COD-SHA1: ab 2e 93 b1 99 16 04 a3 3e d5 07 47 f0 06 ef ae b5 89 68 68 diff --git a/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.jar b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.jar new file mode 100644 index 0000000..ba03065 Binary files /dev/null and b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.jar differ diff --git a/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.rapc b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.rapc new file mode 100644 index 0000000..605c7a0 --- /dev/null +++ b/NFC/NfcMidlet2/deliverables/Standard/7.0.0/NfcMidlet2.rapc @@ -0,0 +1,10 @@ +MIDlet-Name: NfcMidlet2 +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: NfcMidlet2.jar +MIDlet-Jar-Size: 0 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: ,img/icon.png,nfc.sample.midlet.NfcMidlet2 +RIM-MIDlet-Flags-1: 0 + diff --git a/NFC/NfcMidlet2/deliverables/Standard/NfcMidlet2.alx b/NFC/NfcMidlet2/deliverables/Standard/NfcMidlet2.alx new file mode 100644 index 0000000..7a96be3 --- /dev/null +++ b/NFC/NfcMidlet2/deliverables/Standard/NfcMidlet2.alx @@ -0,0 +1,31 @@ + + + + + + + + + + 1.0.0 + + + BlackBerry Developer + + + Copyright (c) 2012 BlackBerry Developer + + + + 7.0.0 + + + NfcMidlet2.cod + + + + + + + + diff --git a/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.cod b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.cod new file mode 100644 index 0000000..77af869 Binary files /dev/null and b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.cod differ diff --git a/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.csl b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.csl new file mode 100644 index 0000000..182d9d8 --- /dev/null +++ b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.csl @@ -0,0 +1,2 @@ +52525400=RIM Runtime API +4e464352=NFCRoutingAPI diff --git a/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.cso b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.cso new file mode 100644 index 0000000..1a589a3 --- /dev/null +++ b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.cso @@ -0,0 +1,5 @@ +33000000=RIMAPPSA2 +52424200=RIM Blackberry Apps API +52434900=RIM Crypto API - Internal +52435200=RIM Crypto API - RIM +4e464352=NFCRoutingAPI diff --git a/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.debug b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.debug new file mode 100644 index 0000000..1cb1228 Binary files /dev/null and b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.debug differ diff --git a/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.jad b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.jad new file mode 100644 index 0000000..055bdb7 --- /dev/null +++ b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.jad @@ -0,0 +1,16 @@ +MIDlet-Name: NfcMidlet2 +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: NfcMidlet2.jar +MIDlet-Jar-Size: 9499 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: NfcMidlet2,img/icon.png,nfc.sample.midlet.NfcMidlet2 +RIM-MIDlet-Flags-1: 1 +Manifest-Version: 1.0 +RIM-COD-URL: NfcMidlet2.cod +RIM-COD-Size: 14668 +RIM-COD-Creation-Time: 1333461343 +RIM-COD-Module-Name: NfcMidlet2 +RIM-COD-Module-Dependencies: net_rim_cldc,net_rim_nfc +RIM-COD-SHA1: ab 2e 93 b1 99 16 04 a3 3e d5 07 47 f0 06 ef ae b5 89 68 68 diff --git a/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.jar b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.jar new file mode 100644 index 0000000..ba03065 Binary files /dev/null and b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.jar differ diff --git a/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.rapc b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.rapc new file mode 100644 index 0000000..605c7a0 --- /dev/null +++ b/NFC/NfcMidlet2/deliverables/Web/7.0.0/NfcMidlet2.rapc @@ -0,0 +1,10 @@ +MIDlet-Name: NfcMidlet2 +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: NfcMidlet2.jar +MIDlet-Jar-Size: 0 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: ,img/icon.png,nfc.sample.midlet.NfcMidlet2 +RIM-MIDlet-Flags-1: 0 + diff --git a/NFC/NfcMidlet2/res/img/icon.png b/NFC/NfcMidlet2/res/img/icon.png new file mode 100644 index 0000000..193950c Binary files /dev/null and b/NFC/NfcMidlet2/res/img/icon.png differ diff --git a/NFC/NfcMidlet2/res/img/photothumb.db b/NFC/NfcMidlet2/res/img/photothumb.db new file mode 100644 index 0000000..fa58b80 Binary files /dev/null and b/NFC/NfcMidlet2/res/img/photothumb.db differ diff --git a/NFC/NfcMidlet2/src/nfc/sample/midlet/NfcMidlet2.java b/NFC/NfcMidlet2/src/nfc/sample/midlet/NfcMidlet2.java new file mode 100644 index 0000000..4441e37 --- /dev/null +++ b/NFC/NfcMidlet2/src/nfc/sample/midlet/NfcMidlet2.java @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2012 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + * This sample application illustrates various aspects of NFC card emulation. + * + * Authors: John Murray and Martin Woolley + * + */ + +package nfc.sample.midlet; + +/** + * Shows PushRegistry being used by a MIDlet for NFC transactions. + * + * Register with the PushRegistry so that the MIDlet is launched automatically when not running + * in startApp add a transaction listener so that it can receive callbacks when already running (push registry will not launch already running applications) + * in destroyApp remove the transaction listener + * + * In the jad file, ensure the MIDlet is automatically launched on device reset so that the TransactionListener can be registered + * RIM-MIDlet-Flags-1: 1 + * + * Updated from original (unreleased) sample app "NfcMidlet" to exploit improvements made in Apollo build 7.0 bundle 2414) such that there is no need to + * + * - To unregister from the push registry on your MIDlet startup as you can now be registered in the PushRegistry and as a TransactionListener + * - To background/foreground your MIDlet at startup + * + * If you experience issues whereby the system reports the AID is already registered when attempting to add your TransactionListener then you need to + * upgrade your device. See NFC Developer FAQ item 4: + * + * http://supportforums.blackberry.com/t5/Java-Development/NFC-Developer-FAQ/ta-p/1634793 + * + */ + +import java.io.IOException; +import java.util.Date; + +import javax.microedition.io.PushRegistry; +import javax.microedition.lcdui.Alert; +import javax.microedition.lcdui.Command; +import javax.microedition.lcdui.CommandListener; +import javax.microedition.lcdui.Displayable; +import javax.microedition.lcdui.TextBox; +import javax.microedition.midlet.*; + +import net.rim.device.api.io.nfc.NFCException; +import net.rim.device.api.io.nfc.emulation.TechnologyType; +import net.rim.device.api.io.nfc.se.SecureElement; +import net.rim.device.api.io.nfc.se.SecureElementManager; +import net.rim.device.api.io.nfc.se.TransactionListener; +import net.rim.device.api.system.Backlight; +import net.rim.device.api.system.RuntimeStore; + +public class NfcMidlet2 extends MIDlet implements CommandListener { + + public static final long TRANSACTION_LISTENER = 0xf435b57918ee015eL; + private static final long RUN_PREVIOUSLY_TOKEN = 0xc8c9f2bf4c371254L; + private static final String CONNECTION_STRING = "apdu:0;target=6E.66.63.74.65.73.74.30.31"; + private Command exitCommand; + private static TextBox tb; + String connections[]; + + MyTransactionListener myListener; + + private RuntimeStore runtimeStore = RuntimeStore.getRuntimeStore(); + + public static byte[][] MY_AID = { { 0x6E, 0x66, 0x63, 0x74, 0x65, 0x73, 0x74, 0x30, 0x31 } }; + + private static javax.microedition.lcdui.Display display; + + private static MIDlet midlet; + + private static int midlet_state; + private static final int MIDLET_PAUSED = 0; + private static final int MIDLET_ACTIVE = 1; + private static final int MIDLET_DESTROYED = 2; + + private static String alert_message = ""; + private static boolean alert_pending = false; + private static boolean terminate = false; + + public NfcMidlet2() { + Utilities.initLogging(); + + Utilities.log("XXXX " + Thread.currentThread().getName() + " MIDlet constructed"); + + display = javax.microedition.lcdui.Display.getDisplay(this); + exitCommand = new Command("Exit", Command.EXIT, 1); + tb = new TextBox("NfcMidlet2 V1.14", "MIDlet awaiting NFC transaction", 50, 0); + + addToPushRegistryIfNecessary(); + + // register as a TransactionListener too so we can receive NFC events when in foreground. + addTransactionListener(); + + midlet = this; + midlet_state = MIDLET_PAUSED; + // reset statics + alert_message = ""; + alert_pending = false; + } + + public void addToPushRegistryIfNecessary() { + String registered_midlet = PushRegistry.getMIDlet(CONNECTION_STRING); + Utilities.log("XXXX " + Thread.currentThread().getName() + " MIDlet registered for " + CONNECTION_STRING + "=" + registered_midlet); + if(registered_midlet == null) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " first time so registering with push registry"); + addToPushRegistry(); + } + } + + public void startApp() { + Utilities.log("XXXX " + Thread.currentThread().getName() + " startApp"); + + if(hasRunPreviously()) { + String[] availableConnections = PushRegistry.listConnections(true); + if(availableConnections.length > 0) { + getTransactionFromPushRegistry(availableConnections); + } + + midlet_state = MIDLET_ACTIVE; + + Backlight.enable(true); + + tb.addCommand(exitCommand); + tb.setCommandListener(this); + if(!alert_pending) { + display.setCurrent(tb); + } else { + doAlert(alert_message); + alert_pending = false; + } + } else { + Utilities.log("XXXX " + Thread.currentThread().getName() + " MIDlet running for first time so assuming we're auto-running"); + setRunPreviously(); + destroyApp(true); + notifyDestroyed(); + } + } + + public void pauseApp() { + Utilities.log("XXXX " + Thread.currentThread().getName() + " pauseApp"); + midlet_state = MIDLET_PAUSED; + } + + public void destroyApp(boolean ignore) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " destroyApp"); + + // reset statics + alert_message = ""; + alert_pending = false; + + // transaction listener can now be removed + removeTransactionListener(); + + midlet_state = MIDLET_DESTROYED; + } + + public void addTransactionListener() { + SecureElementManager sem = SecureElementManager.getInstance(); + if(sem == null) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " addTransactionListener:SecureElementManager instance is null - exiting"); + return; + } + + Utilities.log("XXXX " + Thread.currentThread().getName() + " addTransactionListener:getting SecureElement instance of type SIM"); + SecureElement se = null; + try { + se = sem.getSecureElement(SecureElement.SIM); + } catch(Exception e1) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " addTransactionListener:exception when getting SE: " + e1.getClass().getName() + ":" + e1.getMessage()); + } + + if(se == null) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " addTransactionListener:SecureElement(SIM) is null - exiting"); + return; + } + + myListener = getTransactionListener(); + + try { + Utilities.log("XXXX " + Thread.currentThread().getName() + " addTransactionListener:adding transaction listener"); + + try { + se.addTransactionListener(myListener, MY_AID); + } catch(NFCException e) { + if(e.getMessage().startsWith("TransactionListener has already been added") || e.getMessage().startsWith("AID has already been registered")) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " addTransactionListener:already registered - ignoring"); + } + } + Utilities.log("XXXX " + Thread.currentThread().getName() + " addTransactionListener:added transaction listener OK"); + } catch(Exception e) { + if(!e.getMessage().startsWith("TransactionListener has already been added") && !e.getMessage().startsWith("AID has already been registered")) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " addTransactionListener:exception when adding transaction listener: " + e.getClass().getName() + ":" + e.getMessage()); + return; + } else { + Utilities.log("XXXX " + Thread.currentThread().getName() + " addTransactionListener:exception when adding transaction listener: " + e.getClass().getName() + ":" + e.getMessage()); + return; + } + } + + try { + se.setTechnologyTypes(SecureElement.BATTERY_ON_MODE, TechnologyType.ISO14443B); + Utilities.log("XXXX " + Thread.currentThread().getName() + " addTransactionListener:NFC routing established OK"); + } catch(NFCException e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " addTransactionListener:exception when setting technology types: " + e.getClass().getName() + ":" + e.getMessage()); + } + + try { + runtimeStore.replace(TRANSACTION_LISTENER, myListener); + } catch(IllegalArgumentException e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " RuntimeStore.replace exception: " + e.getClass().getName() + ":" + e.getMessage()); + } + } + + private boolean hasRunPreviously() { + Object prev_run_token = runtimeStore.get(RUN_PREVIOUSLY_TOKEN); + return(prev_run_token != null); + } + + private void setRunPreviously() { + Object prev_run_token = new Object(); + runtimeStore.replace(RUN_PREVIOUSLY_TOKEN, prev_run_token); + } + + public MyTransactionListener getTransactionListener() { + MyTransactionListener tl = (MyTransactionListener) runtimeStore.get(TRANSACTION_LISTENER); + if(tl == null) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " allocating new TransactionListener"); + tl = new MyTransactionListener(); + Utilities.log("XXXX " + Thread.currentThread().getName() + " new TransactionListener=" + tl); + runtimeStore.replace(TRANSACTION_LISTENER, tl); + } + return tl; + } + + public void removeTransactionListener() { + SecureElementManager sem = SecureElementManager.getInstance(); + if(sem == null) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " removeTransactionListener instance is null - exiting"); + return; + } + + Utilities.log("XXXX " + Thread.currentThread().getName() + " removeTransactionListener SecureElement instance of type SIM"); + SecureElement se = null; + try { + se = sem.getSecureElement(SecureElement.SIM); + } catch(Exception e1) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " removeTransactionListener when getting SE: " + e1.getClass().getName() + ":" + e1.getMessage()); + } + + if(se == null) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " removeTransactionListener(SIM) is null - exiting"); + return; + } + try { + myListener = getTransactionListener(); + Utilities.log("XXXX " + Thread.currentThread().getName() + " TransactionListener=" + myListener); + if(myListener != null) { + se.removeTransactionListener(myListener); + Utilities.log("XXXX " + Thread.currentThread().getName() + " removeTransactionListener listener OK"); + } + } catch(Exception e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " removeTransactionListener when removing TransactionListener:" + e.getClass().getName() + ":" + e.getMessage()); + } + + Utilities.log("XXXX " + Thread.currentThread().getName() + " removed TransactionListener from RuntimeStore"); + runtimeStore.remove(TRANSACTION_LISTENER); + + } + + private static void foreground() { + Utilities.log("XXXX " + Thread.currentThread().getName() + " switching screen to foreground"); + midlet.resumeRequest(); + } + + private static void queueAlert(String message) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " queueing alert for when MIDlet is next active"); + alert_message = message; + alert_pending = true; + } + + public static void alertTransaction(String message) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " displaying alert"); + Alert alert = new Alert(message); + display.setCurrent(alert, tb); + } + + public static void doAlert(String message) { + switch(midlet_state) { + case MIDLET_ACTIVE: + alertTransaction(message); + break; + case MIDLET_PAUSED: + queueAlert(message); + foreground(); + break; + } + } + + private void getTransactionFromPushRegistry(String[] availableConnections) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " checking for waiting message from PushRegistry"); + if(availableConnections != null && availableConnections.length > 0) { + // I'm assuming there's only ever one I care about and all I need is the AID just like in a TransactionListener call + // back + // apdu:0;target=4e.46.43.54.65.73.74.65.72.20.31.2e.30 + int index = availableConnections[0].indexOf("target="); + if(index > -1) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " got message from PushRegistry:" + availableConnections[0]); + String aid = availableConnections[0].substring(index + 7); + String message = new Date() + " - transaction from AID " + aid; + doAlert(message); + } + } + } + + public void commandAction(Command cmd, Displayable arg1) { + if(cmd == exitCommand) { + exitApp(); + } + } + + public void exitApp() { + destroyApp(false); + notifyDestroyed(); + } + + public void addToPushRegistry() { + try { + PushRegistry.registerConnection(CONNECTION_STRING, this.getClass().getName(), "*"); + Utilities.log("XXXX " + Thread.currentThread().getName() + " addToPushRegistry:registered ok"); + } catch(ClassNotFoundException e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " addToPushRegistry:exception registering connection: " + e.getClass().getName() + ":" + e.getMessage()); + } catch(IOException e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " addToPushRegistry:exception registering connection: " + e.getClass().getName() + ":" + e.getMessage()); + } + } + + public void listConnectionStrings(String[] conns) { + if(conns != null) { + for(int i = 0; i < conns.length; i++) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " connection:" + conns[i]); + } + } else { + Utilities.log("XXXX " + Thread.currentThread().getName() + " no connections"); + } + } + + private static class MyTransactionListener implements TransactionListener { + + public void onTransactionDetected(byte[][] aids) { + String aid = new String(aids[0]); + Utilities.log("XXXX " + Thread.currentThread().getName() + " onTransactionDetected:" + aid); + + // switch on the backlight. If device is locked it will be automatically unlocked. + Backlight.enable(true); + + String message = new Date() + " - transaction from AID " + aid; + doAlert(message); + } + } +} diff --git a/NFC/NfcMidlet2/src/nfc/sample/midlet/Utilities.java b/NFC/NfcMidlet2/src/nfc/sample/midlet/Utilities.java new file mode 100644 index 0000000..1aa028c --- /dev/null +++ b/NFC/NfcMidlet2/src/nfc/sample/midlet/Utilities.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + * This sample application illustrates various aspects of NFC card emulation. + * + * Authors: John Murray and Martin Woolley + * + */ +package nfc.sample.midlet; + +import net.rim.device.api.system.EventLogger; + +public class Utilities { + + static final long MYAPP_ID = 0x3f0ac1041e84838L; + + public static void initLogging() { + EventLogger.register(MYAPP_ID, "NfcMidlet2", EventLogger.VIEWER_STRING); + } + + public static void log(String log_msg) { + System.out.println(log_msg); + boolean ok = EventLogger.logEvent(MYAPP_ID, log_msg.getBytes(), EventLogger.INFORMATION); + } + + +} diff --git a/NFC/NfcRaceTime7/BlackBerry_App_Descriptor.xml b/NFC/NfcRaceTime7/BlackBerry_App_Descriptor.xml new file mode 100644 index 0000000..9cfd4ad --- /dev/null +++ b/NFC/NfcRaceTime7/BlackBerry_App_Descriptor.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NFC/NfcRaceTime7/LICENSE b/NFC/NfcRaceTime7/LICENSE new file mode 100644 index 0000000..5627d5e --- /dev/null +++ b/NFC/NfcRaceTime7/LICENSE @@ -0,0 +1,204 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +------------------------------------------------------- +Copyright 2012 Research In Motion Limited. diff --git a/NFC/NfcRaceTime7/README.md b/NFC/NfcRaceTime7/README.md new file mode 100644 index 0000000..e86b326 --- /dev/null +++ b/NFC/NfcRaceTime7/README.md @@ -0,0 +1,87 @@ +# NfcRaceTime7 + +The purpose of this application is to demonstrate how NFC tags can be used to trigger actions. + +The use case examines how to use an NFC Tag to trigger the starting and stopping of a timer in the application that could be used in the context of an event like a "fun run". + +The sample code for this application is Open Source under the Apache 2.0 License. + +Note that there is also a BlackBerry 10 Cascades version of this application. https://github.com/blackberry/Cascades-Community-Samples/tree/master/NfcRaceTimeWay + +To create tags for use with this application, use the NfcWriteNdefSmartTag application: + + https://github.com/blackberry/Samples-for-Java/tree/master/NFC/NfcWriteNdefSmartTag + +Write two "custom" tags, with the following values: + +Start Tag: + Domain: my.rim.com + Type: myrecordtype + Content: start + +Stop Tag: + Domain: my.rim.com + Type: myrecordtype + Content: stop + + +The sample code for this application is Open Source under +the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0.html). + +**Applies To** + +* [Cascades for BlackBerry 10](https://bdsc.webapps.blackberry.com/cascades/) +* [BlackBerry Native SDK for Tablet OS](https://bdsc.webapps.blackberry.com/native/) + +**Author(s)** + +* [John Murray](https://github.com/jcmurray) +* [Martin Woolley](https://github.com/mdwoolley) + + +**Release History** +* **V1** - Initial release + +**Known Issues** +1. To start a new game it may be necessary to exit and then start again + +**Dependencies** + +1. BlackBerry Dev Alpha Device Software **10.0.9** +2. BlackBerry 10 Native SDK **10.0.9** + + +**I don't want to build it myself** + +If you don't want to build this sample application yourself we've included a +pre-build and signed BAR files for each version. You can find them in the +folder "installable-bar-files": + + +**To contribute code to this repository you must be [signed up as an +official contributor](http://blackberry.github.com/howToContribute.html).** + + +## Contributing Changes + +Please see the [README](https://github.com/blackberry/Cascades-Community-Samples/blob/master/README.md) +of the Cascades-Community-Samples repository for instructions on how to add new Samples or +make modifications to existing Samples. + + +## Bug Reporting and Feature Requests + +If you find a bug in a Sample, or have an enhancement request, simply file +an [Issue](https://github.com/blackberry/Cascades-Community-Samples/issues) for +the Sample and send a message (via github messages) to the Sample Author(s) to let +them know that you have filed an [Issue](https://github.com/blackberry/Cascades-Community-Samples/issues). + + +## Disclaimer + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE +AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.cod b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.cod new file mode 100644 index 0000000..d3eb108 Binary files /dev/null and b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.cod differ diff --git a/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.csl b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.csl new file mode 100644 index 0000000..725a93b --- /dev/null +++ b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.csl @@ -0,0 +1 @@ +52525400=RIM Runtime API diff --git a/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.cso b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.cso new file mode 100644 index 0000000..1a589a3 --- /dev/null +++ b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.cso @@ -0,0 +1,5 @@ +33000000=RIMAPPSA2 +52424200=RIM Blackberry Apps API +52434900=RIM Crypto API - Internal +52435200=RIM Crypto API - RIM +4e464352=NFCRoutingAPI diff --git a/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.debug b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.debug new file mode 100644 index 0000000..fe8617d Binary files /dev/null and b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.debug differ diff --git a/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.jad b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.jad new file mode 100644 index 0000000..75ec933 --- /dev/null +++ b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.jad @@ -0,0 +1,18 @@ +MIDlet-Name: NfcRaceTime7 +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: NfcRaceTime7.jar +MIDlet-Jar-Size: 49188 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: ,img/icon.png, +RIM-MIDlet-Flags-1: 0 +MIDlet-2: auto,,auto +RIM-MIDlet-Flags-2: 3 +Manifest-Version: 1.0 +RIM-COD-URL: NfcRaceTime7.cod +RIM-COD-Size: 29132 +RIM-COD-Creation-Time: 1349091932 +RIM-COD-Module-Name: NfcRaceTime7 +RIM-COD-Module-Dependencies: net_rim_cldc,net_rim_nfc +RIM-COD-SHA1: 23 9d 48 1d 07 55 e1 20 ed aa c9 7c 47 6f 92 e8 9c 4c 24 e4 diff --git a/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.jar b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.jar new file mode 100644 index 0000000..1b5ef1d Binary files /dev/null and b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.jar differ diff --git a/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.rapc b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.rapc new file mode 100644 index 0000000..34ba292 --- /dev/null +++ b/NFC/NfcRaceTime7/deliverables/Standard/7.0.0/NfcRaceTime7.rapc @@ -0,0 +1,12 @@ +MIDlet-Name: NfcRaceTime7 +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: NfcRaceTime7.jar +MIDlet-Jar-Size: 0 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: ,img/icon.png, +RIM-MIDlet-Flags-1: 0 +MIDlet-2: auto,,auto +RIM-MIDlet-Flags-2: 3 + diff --git a/NFC/NfcRaceTime7/deliverables/Standard/NfcRaceTime7.alx b/NFC/NfcRaceTime7/deliverables/Standard/NfcRaceTime7.alx new file mode 100644 index 0000000..a6d52b3 --- /dev/null +++ b/NFC/NfcRaceTime7/deliverables/Standard/NfcRaceTime7.alx @@ -0,0 +1,31 @@ + + + + + + + + + + 1.0.0 + + + BlackBerry Developer + + + Copyright (c) 2012 BlackBerry Developer + + + + 7.0.0 + + + NfcRaceTime7.cod + + + + + + + + diff --git a/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.cod b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.cod new file mode 100644 index 0000000..d3eb108 Binary files /dev/null and b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.cod differ diff --git a/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.csl b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.csl new file mode 100644 index 0000000..725a93b --- /dev/null +++ b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.csl @@ -0,0 +1 @@ +52525400=RIM Runtime API diff --git a/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.cso b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.cso new file mode 100644 index 0000000..1a589a3 --- /dev/null +++ b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.cso @@ -0,0 +1,5 @@ +33000000=RIMAPPSA2 +52424200=RIM Blackberry Apps API +52434900=RIM Crypto API - Internal +52435200=RIM Crypto API - RIM +4e464352=NFCRoutingAPI diff --git a/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.debug b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.debug new file mode 100644 index 0000000..fe8617d Binary files /dev/null and b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.debug differ diff --git a/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.jad b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.jad new file mode 100644 index 0000000..75ec933 --- /dev/null +++ b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.jad @@ -0,0 +1,18 @@ +MIDlet-Name: NfcRaceTime7 +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: NfcRaceTime7.jar +MIDlet-Jar-Size: 49188 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: ,img/icon.png, +RIM-MIDlet-Flags-1: 0 +MIDlet-2: auto,,auto +RIM-MIDlet-Flags-2: 3 +Manifest-Version: 1.0 +RIM-COD-URL: NfcRaceTime7.cod +RIM-COD-Size: 29132 +RIM-COD-Creation-Time: 1349091932 +RIM-COD-Module-Name: NfcRaceTime7 +RIM-COD-Module-Dependencies: net_rim_cldc,net_rim_nfc +RIM-COD-SHA1: 23 9d 48 1d 07 55 e1 20 ed aa c9 7c 47 6f 92 e8 9c 4c 24 e4 diff --git a/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.jar b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.jar new file mode 100644 index 0000000..1b5ef1d Binary files /dev/null and b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.jar differ diff --git a/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.rapc b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.rapc new file mode 100644 index 0000000..34ba292 --- /dev/null +++ b/NFC/NfcRaceTime7/deliverables/Web/7.0.0/NfcRaceTime7.rapc @@ -0,0 +1,12 @@ +MIDlet-Name: NfcRaceTime7 +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: NfcRaceTime7.jar +MIDlet-Jar-Size: 0 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: ,img/icon.png, +RIM-MIDlet-Flags-1: 0 +MIDlet-2: auto,,auto +RIM-MIDlet-Flags-2: 3 + diff --git a/NFC/NfcRaceTime7/res/img/60px-Seven-segment_0.png b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_0.png new file mode 100644 index 0000000..da07953 Binary files /dev/null and b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_0.png differ diff --git a/NFC/NfcRaceTime7/res/img/60px-Seven-segment_1.png b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_1.png new file mode 100644 index 0000000..010d6c5 Binary files /dev/null and b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_1.png differ diff --git a/NFC/NfcRaceTime7/res/img/60px-Seven-segment_2.png b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_2.png new file mode 100644 index 0000000..96ceee1 Binary files /dev/null and b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_2.png differ diff --git a/NFC/NfcRaceTime7/res/img/60px-Seven-segment_3.png b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_3.png new file mode 100644 index 0000000..e57f608 Binary files /dev/null and b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_3.png differ diff --git a/NFC/NfcRaceTime7/res/img/60px-Seven-segment_4.png b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_4.png new file mode 100644 index 0000000..4f01b48 Binary files /dev/null and b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_4.png differ diff --git a/NFC/NfcRaceTime7/res/img/60px-Seven-segment_5.png b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_5.png new file mode 100644 index 0000000..8c1e122 Binary files /dev/null and b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_5.png differ diff --git a/NFC/NfcRaceTime7/res/img/60px-Seven-segment_6.png b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_6.png new file mode 100644 index 0000000..a393fc2 Binary files /dev/null and b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_6.png differ diff --git a/NFC/NfcRaceTime7/res/img/60px-Seven-segment_7.png b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_7.png new file mode 100644 index 0000000..f88ce99 Binary files /dev/null and b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_7.png differ diff --git a/NFC/NfcRaceTime7/res/img/60px-Seven-segment_8.png b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_8.png new file mode 100644 index 0000000..6021d95 Binary files /dev/null and b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_8.png differ diff --git a/NFC/NfcRaceTime7/res/img/60px-Seven-segment_9.png b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_9.png new file mode 100644 index 0000000..10c34df Binary files /dev/null and b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_9.png differ diff --git a/NFC/NfcRaceTime7/res/img/60px-Seven-segment_colon.png b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_colon.png new file mode 100644 index 0000000..fad38c8 Binary files /dev/null and b/NFC/NfcRaceTime7/res/img/60px-Seven-segment_colon.png differ diff --git a/NFC/NfcRaceTime7/res/img/icon.png b/NFC/NfcRaceTime7/res/img/icon.png new file mode 100644 index 0000000..561ad1d Binary files /dev/null and b/NFC/NfcRaceTime7/res/img/icon.png differ diff --git a/NFC/NfcRaceTime7/res/img/photothumb.db b/NFC/NfcRaceTime7/res/img/photothumb.db new file mode 100644 index 0000000..fa58b80 Binary files /dev/null and b/NFC/NfcRaceTime7/res/img/photothumb.db differ diff --git a/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/ColouredBackground.java b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/ColouredBackground.java new file mode 100644 index 0000000..ce0201e --- /dev/null +++ b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/ColouredBackground.java @@ -0,0 +1,31 @@ +package nfc.sample.racetimebb7; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.ui.container.HorizontalFieldManager; +import net.rim.device.api.ui.decor.Background; +import net.rim.device.api.ui.decor.BackgroundFactory; + +public class ColouredBackground extends HorizontalFieldManager { + + Background background; + + public ColouredBackground(int colour, long style) { + super(style); + background = BackgroundFactory.createSolidBackground(colour); + setBackground(background); + } + +} diff --git a/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/Constants.java b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/Constants.java new file mode 100644 index 0000000..3fb4f6f --- /dev/null +++ b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/Constants.java @@ -0,0 +1,27 @@ +package nfc.sample.racetimebb7; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +public interface Constants { + + public static final String MYAPP_VERSION = "1.0.0"; + + public static final long LISTENER_STATE_TOKEN = 0xbceb71d8f675e991L; + + public static final int REGISTER=0; + public static final int UNREGISTER=1; + + +} \ No newline at end of file diff --git a/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/Listener.java b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/Listener.java new file mode 100644 index 0000000..3d951ab --- /dev/null +++ b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/Listener.java @@ -0,0 +1,60 @@ +package nfc.sample.racetimebb7; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import java.io.UnsupportedEncodingException; +import java.util.Timer; + +import net.rim.device.api.io.nfc.ndef.NDEFMessage; +import net.rim.device.api.io.nfc.ndef.NDEFMessageListener; +import net.rim.device.api.io.nfc.ndef.NDEFRecord; + +public class Listener implements NDEFMessageListener { + + Timer timer; + + public void onNDEFMessageDetected(NDEFMessage msg) { + Utilities.log("XXXX onNDEFMessageDetected"); + NDEFRecord[] records = msg.getRecords(); + int numRecords = records.length; + if(numRecords > 0) { + byte[] payloadBytes = records[0].getPayload(); + try { + String ascii_payload = new String(payloadBytes,"US-ASCII"); + Utilities.log("XXXX payload="+ascii_payload); + if (ascii_payload.equals("start")) { + startTimer(); + } + if (ascii_payload.equals("stop")) { + stopTimer(); + } + } catch(UnsupportedEncodingException e) { + Utilities.log("XXXX "+e.getClass().getName()+":"+e.getMessage()); + } + } + + } + + private void startTimer() { + RaceTimer race_timer = new RaceTimer(); + timer = new Timer(); + timer.scheduleAtFixedRate(race_timer, 1000, 1000); + } + + private void stopTimer() { + timer.cancel(); + } + +} diff --git a/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/MyApp.java b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/MyApp.java new file mode 100644 index 0000000..0d530bc --- /dev/null +++ b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/MyApp.java @@ -0,0 +1,42 @@ +package nfc.sample.racetimebb7; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.ui.UiApplication; + +public class MyApp extends UiApplication { + + public static void main(String[] args) { + MyApp app = new MyApp(); + NdefListenerManager ndef_mgr = NdefListenerManager.getInstance(); + Utilities.initLogging(); + if (args.length > 0) { + if (args[0].equals("auto")) { + Listener listener = new Listener(); + ndef_mgr.registerListener(listener); + } + } else { + Listener listener = new Listener(); + ndef_mgr.registerListener(listener); + app.pushScreen(TimerScreen.getTimerScreen()); + app.enterEventDispatcher(); + } + Utilities.log("XXXX exiting"); + } + + public MyApp() { + } + +} diff --git a/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/NdefListenerManager.java b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/NdefListenerManager.java new file mode 100644 index 0000000..bcc4ced --- /dev/null +++ b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/NdefListenerManager.java @@ -0,0 +1,74 @@ +package nfc.sample.racetimebb7; + +/* + * Copyright (c) 2012 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import net.rim.device.api.io.nfc.NFCException; +import net.rim.device.api.io.nfc.ndef.NDEFRecord; +import net.rim.device.api.io.nfc.readerwriter.ReaderWriterManager; +import net.rim.device.api.system.RuntimeStore; + +public class NdefListenerManager { + + private static NdefListenerManager _mgr; + + private RuntimeStore rts = RuntimeStore.getRuntimeStore(); + + private NdefListenerManager() { + } + + public synchronized static NdefListenerManager getInstance() { + if(_mgr == null) { + _mgr = new NdefListenerManager(); + } + return _mgr; + } + + public void registerListener(Listener listener) { +// unRegisterListener(); // just in case already registered + ReaderWriterManager nfcManager; + try { + nfcManager = ReaderWriterManager.getInstance(); + nfcManager.addNDEFMessageListener(listener, NDEFRecord.TNF_EXTERNAL, "my.rim.com:myrecordtype", true); + rts.replace(Constants.LISTENER_STATE_TOKEN, new Boolean(true)); + Utilities.log("XXXX listener registered"); + } catch(NFCException e) { + Utilities.log("XXXX "+e.getClass().getName()+":"+e.getMessage()); + } + } + + public void unRegisterListener() { + ReaderWriterManager nfcManager; + try { + nfcManager = ReaderWriterManager.getInstance(); + nfcManager.removeNDEFMessageListener(NDEFRecord.TNF_EXTERNAL, "my.rim.com:myrecordtype"); + Utilities.log("XXXX NfcReadNdefSmartTag remove NDEF Message Listener success"); + rts.replace(Constants.LISTENER_STATE_TOKEN, new Boolean(false)); + } catch(NFCException e) { + Utilities.log("XXXX "+e.getClass().getName()+":"+e.getMessage()); + } + } + + public boolean is_listening() { + Boolean state = (Boolean) rts.get(Constants.LISTENER_STATE_TOKEN); + if(state != null) { + return state.booleanValue(); + } else { + rts.replace(Constants.LISTENER_STATE_TOKEN, new Boolean(false)); + return false; + } + } + +} diff --git a/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/RaceTimer.java b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/RaceTimer.java new file mode 100644 index 0000000..3654b08 --- /dev/null +++ b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/RaceTimer.java @@ -0,0 +1,33 @@ +package nfc.sample.racetimebb7; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import java.util.TimerTask; + +public class RaceTimer extends TimerTask { + + private Time time = Time.getInstance(); + + public RaceTimer() { + time.start(); + } + + public void run() { + TimerScreen screen = TimerScreen.getTimerScreen(); + time.setNow(); + screen.updateTime(time); + } + +} diff --git a/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/Time.java b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/Time.java new file mode 100644 index 0000000..aed2e76 --- /dev/null +++ b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/Time.java @@ -0,0 +1,117 @@ +package nfc.sample.racetimebb7; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import java.util.Calendar; +import java.util.Date; + +public class Time { + + private static Time time; + +// private Calendar cal = Calendar.getInstance(); + private long started_at_ms=0; + private long now=0; + private long elapsed=0; + + private int hour1; + private int hour2; + private int minute1; + private int minute2; + private int second1; + private int second2; + + private long MS_HOUR=3600000; + private long MS_MINUTE=60000; + private long MS_SECOND=1000; + + public static Time getInstance() { + if (time == null) { + time = new Time(); + } + return time; + } + + private Time() { + } + + public void start() { + started_at_ms = System.currentTimeMillis(); + Utilities.log("XXXX started_at_ms set to:"+started_at_ms); + } + + public void setNow() { + now = System.currentTimeMillis(); + Utilities.log("XXXX started_at_ms:"+started_at_ms); + Utilities.log("XXXX now:"+now); + elapsed = now - started_at_ms; + Utilities.log("XXXX elapsed:"+elapsed); +// cal.setTime(new Date(elapsed)); + +// int hours = cal.get(Calendar.HOUR_OF_DAY); +// int minutes = cal.get(Calendar.MINUTE); +// int seconds = cal.get(Calendar.SECOND); + + int hours = (int) (elapsed / MS_HOUR); + int remainder = (int) (elapsed - (hours * MS_HOUR)); + int minutes = (int) (remainder / MS_MINUTE); + remainder = (int) (remainder - (minutes * MS_MINUTE)); + int seconds = (int) (remainder / MS_SECOND); + + Utilities.log("XXXX hours="+hours+",minutes="+minutes+",seconds="+seconds); + + hour1 = hours / 10; + hour2 = hours % 10; + minute1 = minutes / 10; + minute2 = minutes % 10; + second1 = seconds / 10; + second2 = seconds % 10; + + Utilities.log("XXXX hour1="+hour1+",hour2="+hour2+",minute1="+minute1+",minute2="+minute2+",second1="+second1+",second2="+second2); + } + + public long getStarted_at_ms() { + return started_at_ms; + } + + public void setStarted_at_ms(long started_at_ms) { + this.started_at_ms = started_at_ms; + } + + public int getHour1() { + return hour1; + } + + public int getHour2() { + return hour2; + } + + public int getMinute1() { + return minute1; + } + + public int getMinute2() { + return minute2; + } + + public int getSecond1() { + return second1; + } + + public int getSecond2() { + return second2; + } + +} diff --git a/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/TimerScreen.java b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/TimerScreen.java new file mode 100644 index 0000000..fdb4125 --- /dev/null +++ b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/TimerScreen.java @@ -0,0 +1,100 @@ +package nfc.sample.racetimebb7; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.system.Display; +import net.rim.device.api.ui.Color; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.Screen; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.component.BitmapField; +import net.rim.device.api.ui.container.AbsoluteFieldManager; +import net.rim.device.api.ui.container.MainScreen; + +public final class TimerScreen extends MainScreen { + + public static TimerScreen screen; + + Bitmap[] digits = { Bitmap.getBitmapResource("60px-Seven-segment_0.png"), Bitmap.getBitmapResource("60px-Seven-segment_1.png"), Bitmap.getBitmapResource("60px-Seven-segment_2.png"), + Bitmap.getBitmapResource("60px-Seven-segment_3.png"), Bitmap.getBitmapResource("60px-Seven-segment_4.png"), Bitmap.getBitmapResource("60px-Seven-segment_5.png"), + Bitmap.getBitmapResource("60px-Seven-segment_6.png"), Bitmap.getBitmapResource("60px-Seven-segment_7.png"), Bitmap.getBitmapResource("60px-Seven-segment_8.png"), + Bitmap.getBitmapResource("60px-Seven-segment_9.png") }; + + Bitmap colon = Bitmap.getBitmapResource("60px-Seven-segment_colon.png"); + + BitmapField hour1; + BitmapField hour2; + BitmapField colon1; + BitmapField minute1; + BitmapField minute2; + BitmapField colon2; + BitmapField second1; + BitmapField second2; + + public synchronized static TimerScreen getTimerScreen() { + if(screen == null) { + screen = new TimerScreen(); + } + return screen; + } + + private TimerScreen() { + super(Field.USE_ALL_HEIGHT | Field.USE_ALL_WIDTH | Screen.NO_VERTICAL_SCROLL); + ColouredBackground bg = new ColouredBackground(Color.WHITE, Field.USE_ALL_HEIGHT | Field.USE_ALL_WIDTH | Screen.NO_VERTICAL_SCROLL); + AbsoluteFieldManager ab_mgr = new AbsoluteFieldManager(); + hour1 = new BitmapField(digits[0]); + hour2 = new BitmapField(digits[0]); + minute1 = new BitmapField(digits[0]); + minute2 = new BitmapField(digits[0]); + second1 = new BitmapField(digits[0]); + second2 = new BitmapField(digits[0]); + colon1 = new BitmapField(colon); + colon2 = new BitmapField(colon); + bg.add(ab_mgr); + + int y = (Display.getHeight() - 112) / 2; // images are 112 pixels high + int x = (Display.getWidth() - (8 * 60)) / 2; // and 60 pixels wide + + ab_mgr.add(hour1, x, y); + x = x + 60; + ab_mgr.add(hour2, x, y); + x = x + 60; + ab_mgr.add(colon1, x, y); + x = x + 60; + ab_mgr.add(minute1, x, y); + x = x + 60; + ab_mgr.add(minute2, x, y); + x = x + 60; + ab_mgr.add(colon2, x, y); + x = x + 60; + ab_mgr.add(second1, x, y); + x = x + 60; + ab_mgr.add(second2, x, y); + add(bg); + } + + public void updateTime(Time time) { + synchronized(UiApplication.getEventLock()) { + hour1.setBitmap(digits[time.getHour1()]); + hour2.setBitmap(digits[time.getHour2()]); + minute1.setBitmap(digits[time.getMinute1()]); + minute2.setBitmap(digits[time.getMinute2()]); + second1.setBitmap(digits[time.getSecond1()]); + second2.setBitmap(digits[time.getSecond2()]); + invalidate(); + } + } +} diff --git a/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/Utilities.java b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/Utilities.java new file mode 100644 index 0000000..4a86455 --- /dev/null +++ b/NFC/NfcRaceTime7/src/nfc/sample/racetimebb7/Utilities.java @@ -0,0 +1,31 @@ +package nfc.sample.racetimebb7; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.system.EventLogger; + +public class Utilities { + + private static final long MYAPP_ID = 0x54817ed4771a5343L; + + public static void log(String logMessage) { + boolean ok = EventLogger.logEvent(MYAPP_ID, logMessage.getBytes(), EventLogger.INFORMATION); + } + + public static void initLogging() { + EventLogger.register(MYAPP_ID, "NfcRaceTimeBB7", EventLogger.VIEWER_STRING); + } + +} diff --git a/NFC/NfcReadNdefSmartTag/README.md b/NFC/NfcReadNdefSmartTag/README.md index 6e8678e..07da287 100644 --- a/NFC/NfcReadNdefSmartTag/README.md +++ b/NFC/NfcReadNdefSmartTag/README.md @@ -32,12 +32,12 @@ None ## Contributing Changes -Please see the [README](https://github.com/blackberry/BlackBerry-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. +Please see the [README](https://github.com/blackberry/Samples-For-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. ## Bug Reporting and Feature Requests -If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/BlackBerry-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/BlackBerry-Java/issues). +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-For-Java/issues) for the Sample. ## Disclaimer diff --git a/NFC/NfcSnepResponder/README.md b/NFC/NfcSnepResponder/README.md index 42f29f0..b3986cd 100644 --- a/NFC/NfcSnepResponder/README.md +++ b/NFC/NfcSnepResponder/README.md @@ -34,12 +34,12 @@ None ## Contributing Changes -Please see the [README](https://github.com/blackberry/BlackBerry-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. +Please see the [README](https://github.com/blackberry/Samples-For-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. ## Bug Reporting and Feature Requests -If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/BlackBerry-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/BlackBerry-Java/issues). +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-For-Java/issues) for the Sample. ## Disclaimer diff --git a/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.cod b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.cod new file mode 100644 index 0000000..883eb2f Binary files /dev/null and b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.cod differ diff --git a/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.csl b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.csl new file mode 100644 index 0000000..725a93b --- /dev/null +++ b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.csl @@ -0,0 +1 @@ +52525400=RIM Runtime API diff --git a/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.cso b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.cso new file mode 100644 index 0000000..1a589a3 --- /dev/null +++ b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.cso @@ -0,0 +1,5 @@ +33000000=RIMAPPSA2 +52424200=RIM Blackberry Apps API +52434900=RIM Crypto API - Internal +52435200=RIM Crypto API - RIM +4e464352=NFCRoutingAPI diff --git a/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.debug b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.debug new file mode 100644 index 0000000..3d09738 Binary files /dev/null and b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.debug differ diff --git a/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.jad b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.jad new file mode 100644 index 0000000..ff87413 --- /dev/null +++ b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.jad @@ -0,0 +1,17 @@ +MIDlet-Name: NfcSnepResponder +MIDlet-Version: 1.0.1 +MIDlet-Vendor: John Murray +MIDlet-Jar-URL: NfcSnepResponder.jar +MIDlet-Jar-Size: 167328 +MIDlet-Description: vCard Responder using the SNEP protocol +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: NFC vCard Responder,img/SmartTag_Logo.png, +RIM-MIDlet-Flags-1: 0 +Manifest-Version: 1.0 +RIM-COD-URL: NfcSnepResponder.cod +RIM-COD-Size: 22560 +RIM-COD-Creation-Time: 1328280624 +RIM-COD-Module-Name: NfcSnepResponder +RIM-COD-Module-Dependencies: net_rim_cldc,net_rim_nfc +RIM-COD-SHA1: 8e 2d d8 9d b4 bf 18 61 a0 55 08 84 58 03 a3 70 d0 57 e8 99 diff --git a/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.jar b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.jar new file mode 100644 index 0000000..753a02b Binary files /dev/null and b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.jar differ diff --git a/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.rapc b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.rapc new file mode 100644 index 0000000..a24492a --- /dev/null +++ b/NFC/NfcSnepResponder/deliverables/Standard/7.1.0/NfcSnepResponder.rapc @@ -0,0 +1,11 @@ +MIDlet-Name: NfcSnepResponder +MIDlet-Version: 1.0.1 +MIDlet-Vendor: John Murray +MIDlet-Description: vCard Responder using the SNEP protocol +MIDlet-Jar-URL: NfcSnepResponder.jar +MIDlet-Jar-Size: 0 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: NFC vCard Responder,img/SmartTag_Logo.png, +RIM-MIDlet-Flags-1: 0 + diff --git a/NFC/NfcTransactionHandler/.classpath b/NFC/NfcTransactionHandler/.classpath new file mode 100644 index 0000000..ba75cf6 --- /dev/null +++ b/NFC/NfcTransactionHandler/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/NFC/NfcTransactionHandler/.project b/NFC/NfcTransactionHandler/.project new file mode 100644 index 0000000..1c1fd15 --- /dev/null +++ b/NFC/NfcTransactionHandler/.project @@ -0,0 +1,29 @@ + + + NfcTransactionHandler + + + + + + net.rim.ejde.internal.builder.BlackBerryPreprocessBuilder + + + + + net.rim.ejde.internal.builder.BlackBerryResourcesBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + + net.rim.ejde.BlackBerryPreProcessNature + net.rim.ejde.BlackBerryProjectCoreNature + org.eclipse.jdt.core.javanature + + diff --git a/NFC/NfcTransactionHandler/.settings/net.rim.browser.tools.debug.widget.prefs b/NFC/NfcTransactionHandler/.settings/net.rim.browser.tools.debug.widget.prefs new file mode 100644 index 0000000..4489c8b --- /dev/null +++ b/NFC/NfcTransactionHandler/.settings/net.rim.browser.tools.debug.widget.prefs @@ -0,0 +1,3 @@ +#Wed Oct 26 08:55:53 BST 2011 +eclipse.preferences.version=1 +outputfolder=build diff --git a/NFC/NfcTransactionHandler/.settings/org.eclipse.jdt.core.prefs b/NFC/NfcTransactionHandler/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..23b92c2 --- /dev/null +++ b/NFC/NfcTransactionHandler/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Wed Oct 26 09:26:47 BST 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore +org.eclipse.jdt.core.compiler.source=1.3 diff --git a/NFC/NfcTransactionHandler/BlackBerry_App_Descriptor.xml b/NFC/NfcTransactionHandler/BlackBerry_App_Descriptor.xml new file mode 100644 index 0000000..6e51ef9 --- /dev/null +++ b/NFC/NfcTransactionHandler/BlackBerry_App_Descriptor.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NFC/NfcTransactionHandler/README.md b/NFC/NfcTransactionHandler/README.md new file mode 100644 index 0000000..231de3d --- /dev/null +++ b/NFC/NfcTransactionHandler/README.md @@ -0,0 +1,47 @@ +# NFCTransactionHandler Sample + + +The purpose of this application is to demonstrate key aspects of an application working in NFC card emulation mode. It is accompanied by article "NFC Card Emulation Primer" which can be found in the BlackBerry developer resource centre and is linked off the following index page: + +http://supportforums.blackberry.com/t5/Java-Development/NFC-Article-Index/ta-p/1538775 + +The application is liberally instrumented with EventLogger Informational messages using the label "NfcTransactionHandler" that can be examined in the event log of a device. Use Alt-LGLG to set the log level to Information and to examine the event log or use javaloader -u eventlog>eventlog.txt to extract the log to your PC over USB. + +The sample code for this application is Open Source under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0.html). + +**Applies To** + +* [BlackBerry Java SDK for Smartphones](http://us.blackberry.com/developers/javaappdev/) + + +**Author(s)** + +* [Martin Woolley](https://github.com/mdwoolley) +* [John Murray](https://github.com/jcmurray) + + +**Dependencies** + +1. BlackBerry Device Software 7.1 and above. + + +**Known Issues** + +None + +**To contribute code to this repository you must be [signed up as an official contributor](http://blackberry.github.com/howToContribute.html).** + + +## Contributing Changes + +Please see the [README](https://github.com/blackberry/Samples-For-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. + + +## Bug Reporting and Feature Requests + +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-For-Java/issues) for the Sample. + + +## Disclaimer + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/NFC/NfcTransactionHandler/res/img/ce_led_err.png b/NFC/NfcTransactionHandler/res/img/ce_led_err.png new file mode 100644 index 0000000..625efd3 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/ce_led_err.png differ diff --git a/NFC/NfcTransactionHandler/res/img/ce_led_off.png b/NFC/NfcTransactionHandler/res/img/ce_led_off.png new file mode 100644 index 0000000..2bb7adb Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/ce_led_off.png differ diff --git a/NFC/NfcTransactionHandler/res/img/ce_led_on.png b/NFC/NfcTransactionHandler/res/img/ce_led_on.png new file mode 100644 index 0000000..bf4ecef Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/ce_led_on.png differ diff --git a/NFC/NfcTransactionHandler/res/img/ce_off_clicked.png b/NFC/NfcTransactionHandler/res/img/ce_off_clicked.png new file mode 100644 index 0000000..c5e0044 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/ce_off_clicked.png differ diff --git a/NFC/NfcTransactionHandler/res/img/ce_off_focused.png b/NFC/NfcTransactionHandler/res/img/ce_off_focused.png new file mode 100644 index 0000000..7547ba1 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/ce_off_focused.png differ diff --git a/NFC/NfcTransactionHandler/res/img/ce_off_unfocused.png b/NFC/NfcTransactionHandler/res/img/ce_off_unfocused.png new file mode 100644 index 0000000..9280ed0 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/ce_off_unfocused.png differ diff --git a/NFC/NfcTransactionHandler/res/img/ce_on_clicked.png b/NFC/NfcTransactionHandler/res/img/ce_on_clicked.png new file mode 100644 index 0000000..512215a Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/ce_on_clicked.png differ diff --git a/NFC/NfcTransactionHandler/res/img/ce_on_focused.png b/NFC/NfcTransactionHandler/res/img/ce_on_focused.png new file mode 100644 index 0000000..f26c51e Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/ce_on_focused.png differ diff --git a/NFC/NfcTransactionHandler/res/img/ce_on_unfocused.png b/NFC/NfcTransactionHandler/res/img/ce_on_unfocused.png new file mode 100644 index 0000000..868a7cc Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/ce_on_unfocused.png differ diff --git a/NFC/NfcTransactionHandler/res/img/clear_clicked.png b/NFC/NfcTransactionHandler/res/img/clear_clicked.png new file mode 100644 index 0000000..114a91f Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/clear_clicked.png differ diff --git a/NFC/NfcTransactionHandler/res/img/clear_focused.png b/NFC/NfcTransactionHandler/res/img/clear_focused.png new file mode 100644 index 0000000..f29a30e Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/clear_focused.png differ diff --git a/NFC/NfcTransactionHandler/res/img/clear_unfocused.png b/NFC/NfcTransactionHandler/res/img/clear_unfocused.png new file mode 100644 index 0000000..f6c2403 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/clear_unfocused.png differ diff --git a/NFC/NfcTransactionHandler/res/img/close_clicked.png b/NFC/NfcTransactionHandler/res/img/close_clicked.png new file mode 100644 index 0000000..3cbe55a Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/close_clicked.png differ diff --git a/NFC/NfcTransactionHandler/res/img/close_focused.png b/NFC/NfcTransactionHandler/res/img/close_focused.png new file mode 100644 index 0000000..7587b21 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/close_focused.png differ diff --git a/NFC/NfcTransactionHandler/res/img/close_unfocused.png b/NFC/NfcTransactionHandler/res/img/close_unfocused.png new file mode 100644 index 0000000..feec44f Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/close_unfocused.png differ diff --git a/NFC/NfcTransactionHandler/res/img/icon.png b/NFC/NfcTransactionHandler/res/img/icon.png new file mode 100644 index 0000000..193950c Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/icon.png differ diff --git a/NFC/NfcTransactionHandler/res/img/icon2.png b/NFC/NfcTransactionHandler/res/img/icon2.png new file mode 100644 index 0000000..755cc13 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/icon2.png differ diff --git a/NFC/NfcTransactionHandler/res/img/led_err.png b/NFC/NfcTransactionHandler/res/img/led_err.png new file mode 100644 index 0000000..d5f0ca9 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/led_err.png differ diff --git a/NFC/NfcTransactionHandler/res/img/led_off.png b/NFC/NfcTransactionHandler/res/img/led_off.png new file mode 100644 index 0000000..86426e0 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/led_off.png differ diff --git a/NFC/NfcTransactionHandler/res/img/led_on.png b/NFC/NfcTransactionHandler/res/img/led_on.png new file mode 100644 index 0000000..bfd3ad0 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/led_on.png differ diff --git a/NFC/NfcTransactionHandler/res/img/nfc_led_err.png b/NFC/NfcTransactionHandler/res/img/nfc_led_err.png new file mode 100644 index 0000000..76a03ce Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/nfc_led_err.png differ diff --git a/NFC/NfcTransactionHandler/res/img/nfc_led_off.png b/NFC/NfcTransactionHandler/res/img/nfc_led_off.png new file mode 100644 index 0000000..11eab25 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/nfc_led_off.png differ diff --git a/NFC/NfcTransactionHandler/res/img/nfc_led_on.png b/NFC/NfcTransactionHandler/res/img/nfc_led_on.png new file mode 100644 index 0000000..7995400 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/nfc_led_on.png differ diff --git a/NFC/NfcTransactionHandler/res/img/select_clicked.png b/NFC/NfcTransactionHandler/res/img/select_clicked.png new file mode 100644 index 0000000..8eaaa27 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/select_clicked.png differ diff --git a/NFC/NfcTransactionHandler/res/img/select_disabled.png b/NFC/NfcTransactionHandler/res/img/select_disabled.png new file mode 100644 index 0000000..05616e3 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/select_disabled.png differ diff --git a/NFC/NfcTransactionHandler/res/img/select_disabled_focused.png b/NFC/NfcTransactionHandler/res/img/select_disabled_focused.png new file mode 100644 index 0000000..494e989 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/select_disabled_focused.png differ diff --git a/NFC/NfcTransactionHandler/res/img/select_focused.png b/NFC/NfcTransactionHandler/res/img/select_focused.png new file mode 100644 index 0000000..d9f5e9f Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/select_focused.png differ diff --git a/NFC/NfcTransactionHandler/res/img/select_unfocused.png b/NFC/NfcTransactionHandler/res/img/select_unfocused.png new file mode 100644 index 0000000..b4f216c Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/select_unfocused.png differ diff --git a/NFC/NfcTransactionHandler/res/img/settings_clicked.png b/NFC/NfcTransactionHandler/res/img/settings_clicked.png new file mode 100644 index 0000000..188e0ed Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/settings_clicked.png differ diff --git a/NFC/NfcTransactionHandler/res/img/settings_focused.png b/NFC/NfcTransactionHandler/res/img/settings_focused.png new file mode 100644 index 0000000..40a20b3 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/settings_focused.png differ diff --git a/NFC/NfcTransactionHandler/res/img/settings_unfocused.png b/NFC/NfcTransactionHandler/res/img/settings_unfocused.png new file mode 100644 index 0000000..4801a60 Binary files /dev/null and b/NFC/NfcTransactionHandler/res/img/settings_unfocused.png differ diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/Constants.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/Constants.java new file mode 100755 index 0000000..c76d7ff --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/Constants.java @@ -0,0 +1,55 @@ +package nfc.sample.nfctransaction; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.ui.Color; + +public class Constants { + public static String VERSION = "1.2.1"; + + public static final int SE_SIM=0; + public static final int SE_EMB=1; + public static String [] SE_NAMES = {"SIM","EMBEDDED"}; + + public static final byte[] DEFAULT_AID = { 0x6E, 0x66, 0x63, 0x74, 0x65, 0x73, 0x74, 0x30, 0x31 }; + public static final byte[] DEFAULT_APDU = { (byte)0x80, 1, 0, 0}; + + public static long UI_IS_RUNNING = 0xcb4b95cab37dbc72L; + + public static final int BACKGROUND_COLOUR = Color.BLACK; + + // navigation + public static final int INDEX_CE = 0; + public static final int INDEX_CLEAR = 1; + public static final int INDEX_CLOSE = 2; + public static final int INDEX_STATUS = 3; + public static final int INDEX_KILL = 4; + + // LEDs + public static final int LED_OFF = 0; + public static final int LED_ON = 1; + public static final int LED_ERR = 2; + + // buttons + public static final int BTN_DEFAULT = 0; + public static final int BTN_CE_ON = 0; + public static final int BTN_CE_OFF = 1; + public static final int BTN_SELECT_OFF = 1; + public static final int BTN_SELECT_ON = 0; + + public static final String AID_SPACE = "--.--.--.--.--.--.--.--.--"; + + public static final String READY = "Ready"; +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/NfcTransHandlerApp.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/NfcTransHandlerApp.java new file mode 100644 index 0000000..b7d90f5 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/NfcTransHandlerApp.java @@ -0,0 +1,178 @@ +package nfc.sample.nfctransaction; + +/* + * Copyright (c) 2012 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + * This sample application illustrates various aspects of NFC card emulation. + * + * Authors: John Murray and Martin Woolley + * + */ + +import net.rim.device.api.io.nfc.se.TransactionListener; +import net.rim.device.api.system.ApplicationDescriptor; +import net.rim.device.api.system.ApplicationManager; +import net.rim.device.api.system.ApplicationManagerException; +import net.rim.device.api.system.Backlight; +import net.rim.device.api.system.GPRSInfo; +import net.rim.device.api.system.RuntimeStore; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.util.ByteArrayUtilities; +import nfc.sample.nfctransaction.Utilities; +import nfc.sample.nfctransaction.nfc.CardEmulation; +import nfc.sample.nfctransaction.ui.NfcTransScreen; + +public class NfcTransHandlerApp extends UiApplication implements TransactionListener { + + private static TransactionListener _tl; + private static boolean transactionLaunch = false; + private static int pid; + + public static final long PASSED_TO_UI_DATA_ID = 0xa2051c199827fc7eL; + private static NfcTransScreen screen; + private boolean running_in_background = true; + + public static void main(String[] args) { + NfcTransHandlerApp app = new NfcTransHandlerApp(); + Utilities.initLogging(); + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " NfcTransactionHandler V" + Constants.VERSION + " has registered with EventLogger"); + pid = ApplicationManager.getApplicationManager().getProcessId(ApplicationDescriptor.currentApplicationDescriptor()); + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " Launching with PID = " + pid); + + Settings settings = Settings.getInstance(); + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " Initial settings:" + settings.toString()); + + if(args.length > 0) { + dumpArgs(args); + if(args[0].equals("auto")) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " auto starting NfcTransactionHandler"); + + Utilities.setUiNotRunningIndication(); + + // switch on the backlight purely to ensure that the application permissions check/prompt associated with this API + // occurs during automatic start up rather than the first time an NFC transaction is handled as this would disrupt the + // user experience. + + Backlight.enable(true, 10); + + // Essential that the SIM is unlocked (PIN) and initialised before we can proceed to use JSR177 + waitForSimInitialisation(); + + CardEmulation.registerTransactionListener(app); + + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " TransactionListener is exiting and will be restarted when a transaction occurs"); + + } else { + if(args[0].equals("seTransactionListener")) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " launched by system to handle NFC transaction"); + transactionLaunch = true; + app.enterEventDispatcher(); + } + } + } else { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " launched with no arguments"); + app.setRunning_in_background(false); + NfcTransScreen screen = NfcTransScreen.getInstance(); + app.pushScreen(screen); + screen.startRtsMonitorThread(); + screen.init(); + UiApplication.getApplication().requestForeground(); + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " entering event dispatcher"); + app.enterEventDispatcher(); + } + } + + private static void waitForSimInitialisation() { + + int mcc = GPRSInfo.getHomeMCC(); + int mnc = GPRSInfo.getHomeMNC(); + Utilities.log("XXXX MCC="+mcc+",MNC="+mnc); + while (mcc == -1) { + try { + Thread.sleep(3000); + } catch(InterruptedException e) { + } + mcc = GPRSInfo.getHomeMCC(); + mnc = GPRSInfo.getHomeMNC(); + Utilities.log("XXXX MCC="+mcc+",MNC="+mnc); + } + Utilities.log("XXXX SIM initialised.... proceeding"); + } + + private static void dumpArgs(String[] args) { + for(int i = 0; i < args.length; i++) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " args[" + i + "]=" + args[i]); + } + } + + private NfcTransHandlerApp() { + _tl = this; + } + + public static TransactionListener getTransactionListener() { + return _tl; + } + + public void onTransactionDetected(byte[][] aids) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " onTransactionDetected received call"); + int num_aids = aids.length; + String aids_as_string = ""; + for(int i = 0; i < num_aids; i++) { + String aid = ByteArrayUtilities.byteArrayToHex(aids[i]); + aids_as_string = aids_as_string + "," + aid; + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " aid=" + aid); + } + aids_as_string = aids_as_string.substring(1, aids_as_string.length()); + + showDetailsScreen(aids_as_string); + // exit because we'll be launched afresh when the next transaction occurs so no need to linger in the background + if(transactionLaunch) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " onTransactionDetected: application is exiting"); + transactionLaunch = false; + System.exit(0); + } + } + + private void showDetailsScreen(final String aids) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " showDetailsScreen..."); + Backlight.enable(true, 10); + RuntimeStore store = RuntimeStore.getRuntimeStore(); + try { + if(!Utilities.isUiRunning()) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " UI not running"); + int pid = ApplicationManager.getApplicationManager().launchApplication("NfcTransactionHandler"); + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " PID = " + pid); + } else { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " UI already running"); + } + } catch(final ApplicationManagerException e) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " Error:" + e.getMessage()); + } + store.put(PASSED_TO_UI_DATA_ID, aids); + } + + protected boolean acceptsForeground() { + return !running_in_background; + } + + public boolean isRunning_in_background() { + return running_in_background; + } + + public void setRunning_in_background(boolean running_in_background) { + this.running_in_background = running_in_background; + } +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/Settings.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/Settings.java new file mode 100644 index 0000000..b16ce23 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/Settings.java @@ -0,0 +1,167 @@ +package nfc.sample.nfctransaction; +/* + * Copyright (c) 2012 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + * A singleton which holds application settings + * + */ + +import net.rim.device.api.system.PersistentObject; +import net.rim.device.api.system.PersistentStore; +import net.rim.device.api.util.ByteArrayUtilities; +import net.rim.device.api.util.Persistable; + +public class Settings implements Persistable { + + private static final long SETTINGS_ID = 0x8a75c361cc97f9d8L; + + private static Settings _settings; + + private int _secure_element; // 0=SIM, 1=eSE + private boolean _ISO14443A; + private boolean _ISO14443B; + private boolean _ISO14443B_PRIME; + private String _registered_aid=""; + private String _apdu; + + private Settings() { + } + + public static synchronized Settings getInstance() { + if (_settings == null) { + _settings = new Settings(); + loadSettings(); + } + return _settings; + } + + public String toString() { + return + "SE="+Constants.SE_NAMES[_secure_element]+ + ",ISO14443A="+_ISO14443A+ + ",ISO14443B="+_ISO14443B+ + ",ISO14443B_PRIME="+_ISO14443B_PRIME+ + ",AID="+_registered_aid; + + } + + private static void loadSettings() { + synchronized(PersistentStore.getSynchObject()) { + PersistentObject po = PersistentStore.getPersistentObject(SETTINGS_ID); + Object obj = po.getContents(); + if (obj != null) { + _settings = (Settings) obj; + } else { + _settings.setISO14443A(false); + _settings.setISO14443B(true); + _settings.setISO14443B_PRIME(false); + _settings.setSecure_element(Constants.SE_SIM); + _settings.setRegisteredAID(Constants.DEFAULT_AID); + _settings.setAPDU(Constants.DEFAULT_APDU); + } + } + } + + public void saveSettings() { + Utilities.log("XXXX " + Thread.currentThread().getName() + " Saving settings"); + synchronized(PersistentStore.getSynchObject()) { + PersistentObject po = PersistentStore.getPersistentObject(SETTINGS_ID); + po.setContents(_settings); + po.commit(); + Utilities.log("XXXX " + Thread.currentThread().getName() + " Saved settings:" + _settings.toString()); + } + } + + public int getSecure_element() { + return _secure_element; + } + + public void setSecure_element(int secure_element) { + _secure_element = secure_element; + } + + public void setSeSIM() { + _secure_element = Constants.SE_SIM; + } + + public void setSeEmbedded() { + _secure_element = Constants.SE_EMB; + } + + public boolean isSimSeSelected() { + return (_secure_element == Constants.SE_SIM); + } + + public boolean isEmbeddedSeSelected() { + return (_secure_element == Constants.SE_EMB); + } + + public boolean isISO14443A() { + return _ISO14443A; + } + + public void setISO14443A(boolean iSO14443A) { + _ISO14443A = iSO14443A; + } + + public boolean isISO14443B() { + return _ISO14443B; + } + + public void setISO14443B(boolean iSO14443B) { + _ISO14443B = iSO14443B; + } + + public boolean isISO14443B_PRIME() { + return _ISO14443B_PRIME; + } + + public void setISO14443B_PRIME(boolean iSO14443B_PRIME) { + _ISO14443B_PRIME = iSO14443B_PRIME; + } + + public String getRegisteredAIDAsString() { + return _registered_aid; + } + + public byte [] getRegisteredAID() { + return ByteArrayUtilities.hexToByteArray(_registered_aid); + } + + public void setRegisteredAID(String registered_aid) { + _registered_aid = registered_aid; + } + + public void setRegisteredAID(byte [] registered_aid) { + _registered_aid = ByteArrayUtilities.byteArrayToHex(registered_aid); + } + + public byte [] getAPDU() { + return ByteArrayUtilities.hexToByteArray(_apdu); + } + + public String getAPDUAsString() { + return _apdu; + } + + public void setAPDU(String apdu) { + _apdu = apdu; + } + + public void setAPDU(byte [] apdu) { + _apdu = ByteArrayUtilities.byteArrayToHex(apdu); + } +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/Utilities.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/Utilities.java new file mode 100644 index 0000000..1f000e4 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/Utilities.java @@ -0,0 +1,318 @@ +package nfc.sample.nfctransaction; + +/* + * Copyright (c) 2012 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.util.Vector; + +import net.rim.device.api.io.nfc.NFCException; +import net.rim.device.api.io.nfc.NFCManager; +import net.rim.device.api.io.nfc.emulation.TechnologyType; +import net.rim.device.api.system.EventLogger; +import net.rim.device.api.system.RuntimeStore; +import net.rim.device.api.ui.Font; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.component.Dialog; +import nfc.sample.nfctransaction.nfc.CardEmulation; + +public class Utilities { + + static final long MYAPP_ID = 0x8172320e10e61b12L; + + private static Font system_font = Font.getDefault(); + + public static void initLogging() { + EventLogger.register(MYAPP_ID, "NfcTransactionHandler", EventLogger.VIEWER_STRING); + } + + public static void log(String log_msg) { + System.out.println(log_msg); + boolean ok = EventLogger.logEvent(MYAPP_ID, log_msg.getBytes(), EventLogger.INFORMATION); + } + + public static String[] split(String whole_string, char delimiter) { + String delim = String.valueOf(delimiter); + Vector parts = new Vector(); + String part = ""; + int end = whole_string.length(); + for(int i = 0; i < end; i++) { + String one_char = whole_string.substring(i, i + 1); + if(!one_char.equals(delim)) { + part = part + one_char; + } else { + parts.addElement(part); + part = new String(); + } + } + parts.addElement(part); + String[] string_parts = new String[parts.size()]; + int size = parts.size(); + for(int i = 0; i < size; i++) { + string_parts[i] = (String) parts.elementAt(i); + } + return string_parts; + } + + public static String hexPresentation(String aids_received) { + // assumes a valid series of 1 or more hex strings, separated by commas + // e.g. 999999,111111 + String hexified = "0x"; + int len = aids_received.length(); + int i = 0; + while(i < len) { + if(aids_received.charAt(i) != ',') { + hexified = hexified + aids_received.charAt(i); + i++; + hexified = hexified + aids_received.charAt(i); + if(i < (len - 1)) { + hexified = hexified + ":"; + } + } else { + hexified = hexified + aids_received.charAt(i); + } + i++; + } + return hexified; + } + + public static String getNfcStatusDescription(int service_status) { + boolean unknown = true; + String status = ""; + if(service_status == NFCManager.NFC_NONE) { + status = status + "NFC_NONE (" + NFCManager.NFC_NONE + ")\n"; + unknown = false; + } + if((service_status & NFCManager.NFC_ALL) == NFCManager.NFC_ALL) { + status = status + "NFC_ALL (" + NFCManager.NFC_ALL + ")\n"; + unknown = false; + } + + if((service_status & NFCManager.NFC_EMBEDDED_SECURE_ELEMENT_CARD_EMULATION) == NFCManager.NFC_EMBEDDED_SECURE_ELEMENT_CARD_EMULATION) { + status = status + "NFC_EMBEDDED_SECURE_ELEMENT_CARD_EMULATION (" + + NFCManager.NFC_EMBEDDED_SECURE_ELEMENT_CARD_EMULATION + ")\n"; + unknown = false; + } + + if((service_status & NFCManager.NFC_TAG_CARD_EMULATION) == NFCManager.NFC_TAG_CARD_EMULATION) { + status = status + "NFC_TAG_CARD_EMULATION (" + NFCManager.NFC_TAG_CARD_EMULATION + ")\n"; + unknown = false; + } + + if((service_status & NFCManager.NFC_TAG_CARD_READER_WRITER) == NFCManager.NFC_TAG_CARD_READER_WRITER) { + status = status + "NFC_TAG_CARD_READER_WRITER (" + NFCManager.NFC_TAG_CARD_READER_WRITER + ")"; + unknown = false; + } + + if((service_status & NFCManager.NFC_UICC_CARD_EMULATION) == NFCManager.NFC_UICC_CARD_EMULATION) { + status = status + "NFC_UICC_CARD_EMULATION (" + NFCManager.NFC_UICC_CARD_EMULATION + ")"; + unknown = false; + } + + if((service_status & NFCManager.NFC_UICC_CARD_EMULATION_PERSISTENT) == NFCManager.NFC_UICC_CARD_EMULATION_PERSISTENT) { + status = status + "NFC_UICC_CARD_EMULATION_PERSISTENT (" + NFCManager.NFC_UICC_CARD_EMULATION_PERSISTENT + ")\n"; + unknown = false; + } + + if(unknown) { + status = status + "Unknown code (" + service_status + ")\n"; + } + + return status; + } + + public static String getTechnologyTypesNames(int types) { + boolean unknown = true; + String type_names = "NFC technology types: "; + if((types & TechnologyType.FELICA) == TechnologyType.FELICA) { + type_names = type_names + "FELICA (" + TechnologyType.FELICA + "),"; + unknown = false; + } + if((types & TechnologyType.ISO14443A) == TechnologyType.ISO14443A) { + type_names = type_names + "ISO14443A (" + TechnologyType.ISO14443A + "),"; + unknown = false; + } + if((types & TechnologyType.ISO14443A_MIFARE) == TechnologyType.ISO14443A_MIFARE) { + type_names = type_names + "ISO14443A_MIFARE (" + TechnologyType.ISO14443A_MIFARE + "),"; + unknown = false; + } + if((types & TechnologyType.ISO14443B) == TechnologyType.ISO14443B) { + type_names = type_names + "ISO14443B (" + TechnologyType.ISO14443B + "),"; + unknown = false; + } + if((types & TechnologyType.ISO14443B_PRIME) == TechnologyType.ISO14443B_PRIME) { + type_names = type_names + "ISO14443B_PRIME (" + TechnologyType.ISO14443B_PRIME + "),"; + unknown = false; + } + if((types & TechnologyType.ISO15693) == TechnologyType.ISO15693) { + type_names = type_names + "ISO15693 (" + TechnologyType.ISO15693 + "),"; + unknown = false; + } + if((types & TechnologyType.NONE) == TechnologyType.NONE) { + type_names = type_names + "NONE (" + TechnologyType.NONE + "),"; + unknown = false; + } + if(unknown) { + type_names = type_names + "Unknown technology types (" + types + "),"; + } + + return type_names.substring(0, type_names.length() - 1); + } + + public static String makeApduConnectionString(String AID) { + String connection_string = "apdu:0;target="; + boolean done=false; + int i=0; + while (!done) { + connection_string = connection_string + AID.substring(i, i+2); + i = i + 2; + if (i < (AID.length() - 1)) { + connection_string = connection_string + "."; + } else { + done = true; + } + } + return connection_string; + } + + public static String onOrOff(boolean state) { + if(state == true) { + return "ON"; + } else { + return "OFF"; + } + } + + public static boolean isUiRunning() { + RuntimeStore rts = RuntimeStore.getRuntimeStore(); + Utilities.log("XXXX isUiRunning()"); + Object ui_running_token = rts.get(Constants.UI_IS_RUNNING); + if(ui_running_token != null) { + return true; + } else { + return false; + } + } + + public static void setUiNotRunningIndication() { + RuntimeStore rts = RuntimeStore.getRuntimeStore(); + rts.remove(Constants.UI_IS_RUNNING); + } + + public static String getNFCServicesSummary() { + String summary = ","; + try { + int service_status = NFCManager.getInstance().getAvailableNFCServices(); + if(service_status == NFCManager.NFC_NONE) { + summary = "NFC OFF"; + return summary; + } + summary = "NFC ON: "; + if((service_status & NFCManager.NFC_EMBEDDED_SECURE_ELEMENT_CARD_EMULATION) == NFCManager.NFC_EMBEDDED_SECURE_ELEMENT_CARD_EMULATION) { + summary = summary + "eSE CE,"; + } + + if((service_status & NFCManager.NFC_TAG_CARD_EMULATION) == NFCManager.NFC_TAG_CARD_EMULATION) { + summary = summary + "VIRTUAL TAG,"; + } + + if((service_status & NFCManager.NFC_TAG_CARD_READER_WRITER) == NFCManager.NFC_TAG_CARD_READER_WRITER) { + summary = summary + "TAG R/W,"; + } + + if((service_status & NFCManager.NFC_UICC_CARD_EMULATION) == NFCManager.NFC_UICC_CARD_EMULATION) { + summary = summary + "UICC CE,"; + } + + if((service_status & NFCManager.NFC_UICC_CARD_EMULATION_PERSISTENT) == NFCManager.NFC_UICC_CARD_EMULATION_PERSISTENT) { + summary = summary + "UICC CE PERS,"; + } + summary = summary.substring(0, summary.length() - 1); + return summary; + } catch(NFCException e) { + return "Error establishing status"; + } + } + + public static String getCeStatusSummary() { + boolean unknown = true; + int types; + try { + types = CardEmulation.getInstance().getTechnologyTypes(); + } catch(NFCException e) { + return "Error establishing status"; + } + String type_names = ""; + if((types & TechnologyType.FELICA) == TechnologyType.FELICA) { + type_names = type_names + "FELICA,"; + unknown = false; + } + if((types & TechnologyType.ISO14443A) == TechnologyType.ISO14443A) { + type_names = type_names + "ISO14443A,"; + unknown = false; + } + if((types & TechnologyType.ISO14443A_MIFARE) == TechnologyType.ISO14443A_MIFARE) { + type_names = type_names + "ISO14443A_MIFARE,"; + unknown = false; + } + if((types & TechnologyType.ISO14443B) == TechnologyType.ISO14443B) { + type_names = type_names + "ISO14443B,"; + unknown = false; + } + if((types & TechnologyType.ISO14443B_PRIME) == TechnologyType.ISO14443B_PRIME) { + type_names = type_names + "ISO14443B_PRIME,"; + unknown = false; + } + if((types & TechnologyType.ISO15693) == TechnologyType.ISO15693) { + type_names = type_names + "ISO15693,"; + unknown = false; + } + if(unknown) { + if((types & TechnologyType.NONE) == TechnologyType.NONE) { + type_names = type_names + "NONE,"; + unknown = false; + } + } + if(unknown) { + type_names = type_names + "Unknown,"; + } + + return type_names.substring(0, type_names.length() - 1); + } + + public static int ledBooleanToInt(boolean on) { + if(on) { + return Constants.LED_ON; + } else { + return Constants.LED_OFF; + } + } + + public static void popupMessage(String message) { + synchronized(UiApplication.getEventLock()) { + Dialog.inform(message); + } + } + + public static void popupAlert(String message) { + synchronized(UiApplication.getEventLock()) { + Dialog.alert(message); + } + } + + public static int getTextWidth(String text) { + return system_font.getBounds(text); + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/ClearCommand.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/ClearCommand.java new file mode 100644 index 0000000..e04b5c5 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/ClearCommand.java @@ -0,0 +1,37 @@ +package nfc.sample.nfctransaction.commands; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*/ +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.command.ReadOnlyCommandMetadata; +import net.rim.device.api.ui.UiApplication; +import nfc.sample.nfctransaction.Utilities; +import nfc.sample.nfctransaction.ui.NfcTransScreen; + +// clear the UI area which holds the applet AID from a previous TransactionListener call back + +public class ClearCommand extends AlwaysExecutableCommand { + + public void execute(ReadOnlyCommandMetadata metadata, Object context) { + synchronized(UiApplication.getUiApplication().getEventLock()) { + NfcTransScreen screen = NfcTransScreen.getInstance(); + screen.clearLastAIDs(); + Utilities.log("XXXX " + Thread.currentThread().getName() + " AID field cleared"); + } + + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/CloseCommand.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/CloseCommand.java new file mode 100644 index 0000000..759f742 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/CloseCommand.java @@ -0,0 +1,34 @@ +package nfc.sample.nfctransaction.commands; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.command.ReadOnlyCommandMetadata; +import net.rim.device.api.ui.UiApplication; + +// Send the app into background + +public class CloseCommand extends AlwaysExecutableCommand { + + public void execute(ReadOnlyCommandMetadata metadata, Object context) { + synchronized(UiApplication.getUiApplication().getEventLock()) { + // don't actually close otherwise our thread which is receiving the NFC transactions will exit as the app will be fully + // closed + UiApplication.getUiApplication().requestBackground(); + } + + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/Iso7816Command.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/Iso7816Command.java new file mode 100755 index 0000000..12c023a --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/Iso7816Command.java @@ -0,0 +1,79 @@ +package nfc.sample.nfctransaction.commands; + +/* + * Copyright (c) 2012 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import javax.microedition.apdu.APDUConnection; +import javax.microedition.io.Connector; + +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.command.ReadOnlyCommandMetadata; +import net.rim.device.api.util.ByteArrayUtilities; +import nfc.sample.nfctransaction.Constants; +import nfc.sample.nfctransaction.Settings; +import nfc.sample.nfctransaction.Utilities; +import nfc.sample.nfctransaction.ui.NfcTransScreen; +import nfc.sample.nfctransaction.ui.buttons.MultiStateButtonField; + +/** + * This command sends a ISO7816-4 SELECT APDU using the JSR177 API followed by a proprietary APDU. For this to work, the target + * SecureElement must contain an applet with the AID used here. So developers who just run this code to see what happens are + * likely to see an error from this command. This is to be expected however. + * + * Authors: John Murray and Martin Woolley + * + */ + +public class Iso7816Command extends AlwaysExecutableCommand { + + public void execute(ReadOnlyCommandMetadata metadata, Object context) { + MultiStateButtonField btn = (MultiStateButtonField) context; + if(btn.getMsbState() == Constants.BTN_SELECT_OFF) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " ISO 7816-4 command exiting because button is in OFF state"); + return; + } + Settings settings = Settings.getInstance(); + NfcTransScreen screen = NfcTransScreen.getInstance(); + Utilities.log("XXXX " + Thread.currentThread().getName() + " selecting applet"); + APDUConnection apduConn = null; + // this is an example and completely proprietary APDU included solely to demonstrate the basic use of JSR-177 + // Decode: + // 0x80 : CLASS = proprietary + // 0x01 : INS = invented command! Interpretation will require the selected applet to understand this command + // 0x00 : P1 = null + // 0x00 : P1 = null + byte[] command = settings.getAPDU(); + try { + // Open an APDUConnection to our applet. This results in an ISO 7816-4 SELECT command being sent by the JSR-177 API + String connection_string = Utilities.makeApduConnectionString(settings.getRegisteredAIDAsString()); + Utilities.log("XXXX " + Thread.currentThread().getName() + " ISO 7816-4 command: opening APDUConnection to " + connection_string); + apduConn = (APDUConnection) Connector.open(connection_string); + Utilities.log("XXXX " + Thread.currentThread().getName() + " ISO 7816-4 command: APDUConnection opened"); + screen.setUserMessage("Selected AID OK"); + // Send the APDU and wait for a response - expect an error here unless your applet supports the command that was sent + Utilities.log("XXXX " + Thread.currentThread().getName() + " ISO 7816-4 command: sending APDU"); + byte[] ret = apduConn.exchangeAPDU(command); + String resp_string = ByteArrayUtilities.byteArrayToHex(ret); + Utilities.log("XXXX " + Thread.currentThread().getName() + " ISO 7816-4 command: response=" + resp_string); + screen.setUserMessage("APDU response=" + resp_string); + // Close the logical channel connection + apduConn.close(); + } catch(Exception e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " ISO 7816-4 command failed:" + e.getClass().getName() + ":" + e.getMessage()); + screen.setUserMessage("Error. Select failed: check log"); + } + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/KillCommand.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/KillCommand.java new file mode 100644 index 0000000..91ed522 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/KillCommand.java @@ -0,0 +1,33 @@ +package nfc.sample.nfctransaction.commands; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.command.CommandHandler; +import net.rim.device.api.command.ReadOnlyCommandMetadata; +import net.rim.device.api.ui.UiApplication; +import nfc.sample.nfctransaction.Utilities; + +// Cause the app to exit fully + +public class KillCommand extends CommandHandler { + + public void execute(ReadOnlyCommandMetadata metadata, Object context) { + synchronized (UiApplication.getUiApplication().getEventLock()) { + Utilities.setUiNotRunningIndication(); + System.exit(-1); + } + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/SettingsCommand.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/SettingsCommand.java new file mode 100644 index 0000000..04c2029 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/SettingsCommand.java @@ -0,0 +1,33 @@ +package nfc.sample.nfctransaction.commands; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.command.ReadOnlyCommandMetadata; +import net.rim.device.api.ui.UiApplication; +import nfc.sample.nfctransaction.ui.NfcSettingsScreen; + +// Show the settings screen + +public class SettingsCommand extends AlwaysExecutableCommand { + + public void execute(ReadOnlyCommandMetadata metadata, Object context) { + synchronized(UiApplication.getUiApplication().getEventLock()) { + UiApplication.getUiApplication().pushScreen(new NfcSettingsScreen()); + } + + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/ToggleCeCommand.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/ToggleCeCommand.java new file mode 100644 index 0000000..b888fce --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/commands/ToggleCeCommand.java @@ -0,0 +1,122 @@ +package nfc.sample.nfctransaction.commands; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.command.ReadOnlyCommandMetadata; +import net.rim.device.api.io.nfc.NFCException; +import net.rim.device.api.io.nfc.se.SecureElement; +import nfc.sample.nfctransaction.Constants; +import nfc.sample.nfctransaction.Utilities; +import nfc.sample.nfctransaction.nfc.CardEmulation; +import nfc.sample.nfctransaction.nfc.NfcService; +import nfc.sample.nfctransaction.ui.NfcTransScreen; + +// toggle the state of card emulation ON | OFF + +public class ToggleCeCommand extends AlwaysExecutableCommand { + + private NfcService nfc_service = NfcService.getInstance(); + private CardEmulation ce = CardEmulation.getInstance(); + + public void execute(ReadOnlyCommandMetadata metadata, Object context) { + NfcTransScreen screen = NfcTransScreen.getInstance(); + Utilities.log("XXXX " + Thread.currentThread().getName() + " toggling card emulation"); + boolean nfc_enabled = false; + try { + nfc_enabled = nfc_service.isNfcEnabled(); + screen.setNfcLed(Utilities.ledBooleanToInt(nfc_enabled)); + } catch (NFCException e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " exception when establishing NFC service status: " + e.getClass().getName() + ":" + + e.getMessage()); + screen.setUserMessage("Failed to establish NFC service status"); + screen.setNfcLed(Constants.LED_ERR); + return; + } + + if (!nfc_enabled) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " NFC seems to be OFF so prompting user to enable it"); + screen.setUserMessage("NFC is off"); + try { + nfc_service.promptToEnableNFC(); + screen.setCeButtonState(ce.isCeEnabled(SecureElement.BATTERY_ON_MODE)); + } catch (NFCException e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " exception when prompting to enable NFC: " + e.getClass().getName() + ":" + + e.getMessage()); + screen.setUserMessage("Failed when prompting to enable NFC"); + } + return; + } + + boolean ce_enabled = false; + try { + ce_enabled = ce.isCeEnabled(SecureElement.BATTERY_ON_MODE); + } catch (NFCException e1) { + Utilities + .log("XXXX " + Thread.currentThread().getName() + " exception when checking CE status: " + e1.getClass().getName() + ":" + e1.getMessage()); + screen.setUserMessage("Error: could not establish CE status"); + screen.setCemLed(Constants.LED_ERR); + return; + } + if (!ce_enabled) { + try { + if (nfc_service.isNfcEnabled()) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " NFC is ON so setting technology types"); + // Route ISO14443x to the Secure Element + // for battery on, device on mode + ce_enabled = ce.setRoutingOn(ce.getCurrentTechnologyTypes()); + if (ce_enabled) { + screen.setCeButtonState(true); + screen.setSelectButtonState(true); + screen.setUserMessage("Card emulation enabled OK"); + screen.setCemLed(Constants.LED_ON); + } else { + screen.setUserMessage("Card emulation not enabled"); + } + } else { + Utilities.log("XXXX " + Thread.currentThread().getName() + " NFC seems to be OFF so prompting user to enable it"); + screen.setUserMessage("NFC is off"); + nfc_service.promptToEnableNFC(); + } + } catch (NFCException e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " exception when setting SE routing: " + e.getClass().getName() + ":" + + e.getMessage()); + screen.setUserMessage("Failed to set NFC routing"); + return; + } + } else { + try { + // Remove routing + Utilities.log("XXXX " + Thread.currentThread().getName() + " NFC removing NFC SIM SE routing"); + ce_enabled = ce.setRoutingOff(); + if (!ce_enabled) { + screen.setCeButtonState(false); + screen.setSelectButtonState(false); + screen.setUserMessage("Card emulation disabled OK"); + screen.setCemLed(Constants.LED_OFF); + } else { + screen.setUserMessage("Card emulation not disabled"); + } + } catch (NFCException e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " exception when setting SE routing: " + e.getClass().getName() + ":" + + e.getMessage()); + screen.setUserMessage("Failed to set NFC routing"); + return; + } + } + + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/nfc/CardEmulation.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/nfc/CardEmulation.java new file mode 100755 index 0000000..396a8e1 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/nfc/CardEmulation.java @@ -0,0 +1,205 @@ +package nfc.sample.nfctransaction.nfc; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.io.nfc.NFCException; +import net.rim.device.api.io.nfc.emulation.TechnologyType; +import net.rim.device.api.io.nfc.se.SecureElement; +import net.rim.device.api.io.nfc.se.SecureElementManager; +import net.rim.device.api.io.nfc.se.TransactionListener; +import net.rim.device.api.system.ApplicationDescriptor; +import net.rim.device.api.system.ApplicationManager; +import nfc.sample.nfctransaction.Settings; +import nfc.sample.nfctransaction.Utilities; +import nfc.sample.nfctransaction.ui.TextDetailsProvider; + +// This class contains various Card Emulation related methods + +public class CardEmulation implements TextDetailsProvider { + + private static CardEmulation ce; + + private static TransactionListener _tl; + + private SecureElementManager sem = SecureElementManager.getInstance(); + private SecureElement se = null; + + private int tech_type=TechnologyType.ISO14443B; + + private boolean se_obtained = false; + + private int current_se=-1; + private int current_tt=-1; + + public static synchronized CardEmulation getInstance() { + if (ce == null) { + ce = new CardEmulation(); + } + return ce; + } + + public void initCe(int se_choice) throws NFCException { + se = sem.getSecureElement(se_choice); + if (se == null) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " SecureElement(SIM) is null"); + se_obtained = false; + } else { + se_obtained = true; + current_se = se_choice; + } + } + + public static void registerTransactionListener(TransactionListener tl) { + + int pid = ApplicationManager.getApplicationManager().getProcessId(ApplicationDescriptor.currentApplicationDescriptor()); + Settings settings = Settings.getInstance(); + + SecureElementManager sem = SecureElementManager.getInstance(); + if(sem == null) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " SecureElementManager instance is null - exiting"); + System.exit(0); + } + + SecureElement[] sec_elements = null; + try { + sec_elements = sem.getSecureElements(); + } catch(NFCException e2) { + e2.printStackTrace(); + } + if(sec_elements == null) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " SecureElement[] is null - exiting"); + System.exit(0); + } + + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " device has " + sec_elements.length + " SEs"); + + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " getting SecureElement instance"); + SecureElement se = null; + try { + if(settings.isSimSeSelected()) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " Obtaining SecureElement in SIM"); + se = sem.getSecureElement(SecureElement.SIM); + } else { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " Obtaining embedded SecureElement"); + se = sem.getSecureElement(SecureElement.EMBEDDED); + } + } catch(NFCException e1) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " exception when getting SE: " + e1.getClass().getName() + ":" + e1.getMessage()); + } + + if(se == null) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " SecureElement is null - exiting"); + System.exit(0); + } + + // register our app as a transaction listener + try { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " adding transaction listener for AID:"+settings.getRegisteredAIDAsString()); + se.addTransactionListener(tl, new byte[][] { settings.getRegisteredAID() }); + _tl = tl; + } catch(NFCException e) { + if(!e.getMessage().startsWith("TransactionListener has already been added")) { + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " exception when adding transaction listener: " + e.getClass().getName() + ":" + e.getMessage()); + System.exit(0); + } + } + } + + public void removeTransactionListener() { + if (se != null && _tl != null) { + try { + int pid = ApplicationManager.getApplicationManager().getProcessId(ApplicationDescriptor.currentApplicationDescriptor()); + Utilities.log("XXXX " + pid + ":" + Thread.currentThread().getName() + " removing transaction listener"); + se.removeTransactionListener(_tl); + } catch(NFCException e) { + Utilities.log("XXXX " + ":" + Thread.currentThread().getName() + " exception when removing transaction listener: " + e.getClass().getName() + ":" + e.getMessage()); + } + } + } + + public boolean isCeEnabled(int battery_mode) throws NFCException { + int types = getTechnologyTypes(battery_mode); + Utilities.log("XXXX " + Thread.currentThread().getName() + " " + Utilities.getTechnologyTypesNames(types)); + boolean ce_enabled = (types & TechnologyType.ISO14443B) == TechnologyType.ISO14443B; + Utilities.log("XXXX " + Thread.currentThread().getName() + " ce_enabled=" + ce_enabled); + return ce_enabled; + } + + public int getTechnologyTypes(int battery_mode) throws NFCException { + if (!se_obtained) { + return TechnologyType.NONE; + } + return se.getTechnologyTypes(battery_mode); + } + + public int getTechnologyTypes() throws NFCException { + return getTechnologyTypes(SecureElement.BATTERY_ON_MODE); + } + + public String getTextDetails() { + return Utilities.getCeStatusSummary(); + } + + public boolean isSe_obtained() { + return se_obtained; + } + + public void setSe_obtained(boolean se_obtained) { + this.se_obtained = se_obtained; + } + + public boolean setRoutingOn(int technology_types) throws NFCException { + if (se_obtained) { + se.setTechnologyTypes(SecureElement.BATTERY_ON_MODE, technology_types); + Utilities.log("XXXX " + Thread.currentThread().getName() + " NFC routing established OK"); + int types = se.getTechnologyTypes(SecureElement.BATTERY_ON_MODE); + Utilities.log("XXXX " + Thread.currentThread().getName() + " " + Utilities.getTechnologyTypesNames(types)); + current_tt = technology_types; + return true; + } else { + Utilities.log("XXXX " + Thread.currentThread().getName() + " No SE selected"); + return false; + } + } + + public boolean setRoutingOff() throws NFCException { + if (se_obtained) { + se.setTechnologyTypes(SecureElement.BATTERY_ON_MODE, TechnologyType.NONE); + return false; + } else { + Utilities.log("XXXX " + Thread.currentThread().getName() + " No SE selected"); + return true; + } + } + + public int getCurrentSecureElement() { + if (current_se != -1) { + return current_se; + } else { + // default is to use the SIM SE + return SecureElement.SIM; + } + } + + public int getCurrentTechnologyTypes() { + if (current_tt != -1) { + return current_tt; + } else { + // default is to use the ISO14443B + return TechnologyType.ISO14443B; + } + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/nfc/MyNfcStatusListener.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/nfc/MyNfcStatusListener.java new file mode 100644 index 0000000..d7a0329 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/nfc/MyNfcStatusListener.java @@ -0,0 +1,45 @@ +package nfc.sample.nfctransaction.nfc; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.io.nfc.NFCException; +import net.rim.device.api.io.nfc.NFCManager; +import net.rim.device.api.io.nfc.NFCStatusListener; +import net.rim.device.api.io.nfc.se.SecureElement; +import nfc.sample.nfctransaction.Utilities; +import nfc.sample.nfctransaction.ui.NfcTransScreen; + +// NFCStatusListener implementation that monitors the NFC service and updates the UI when it changes + +public class MyNfcStatusListener implements NFCStatusListener { + + private NfcTransScreen screen = NfcTransScreen.getInstance(); + private CardEmulation ce = CardEmulation.getInstance(); + + public void onStatusChange(int nfcServicesAvailable) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " onStatusChange:" + nfcServicesAvailable); + boolean nfc_status = (nfcServicesAvailable != NFCManager.NFC_NONE); + boolean ce_status = true; + try { + ce_status = ce.isCeEnabled(SecureElement.BATTERY_ON_MODE); + Utilities.log("XXXX " + Thread.currentThread().getName() + " onStatusChange: CE state=" + ce_status); + } catch(NFCException e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " : " + + e.getClass().getName() + ":" + e.getMessage()); + } + screen.nfcStateChanged(nfc_status, ce_status); + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/nfc/NfcService.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/nfc/NfcService.java new file mode 100644 index 0000000..9f2a54d --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/nfc/NfcService.java @@ -0,0 +1,62 @@ +package nfc.sample.nfctransaction.nfc; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.io.nfc.NFCException; +import net.rim.device.api.io.nfc.NFCManager; +import net.rim.device.api.ui.UiApplication; +import nfc.sample.nfctransaction.Utilities; +import nfc.sample.nfctransaction.ui.TextDetailsProvider; + +public class NfcService implements TextDetailsProvider { + + private static NfcService nfc_service; + + public static synchronized NfcService getInstance() { + if (nfc_service == null) { + nfc_service = new NfcService(); + } + return nfc_service; + } + + public boolean isNfcEnabled() throws NFCException { + // checks that NFC is enabled and that the required NFC service is + // available + Utilities.log("XXXX " + Thread.currentThread().getName() + " establishing NFC service status"); + int service_status = NFCManager.getInstance().getAvailableNFCServices(); + Utilities.log("XXXX " + Thread.currentThread().getName() + " " + Utilities.getNFCServicesSummary()); + boolean nfc_ok = (service_status != NFCManager.NFC_NONE); + Utilities.log("XXXX " + Thread.currentThread().getName() + " NFC enabled="+nfc_ok); + return nfc_ok; + } + + public void promptToEnableNFC() throws NFCException { + synchronized (UiApplication.getEventLock()) { + NFCManager.getInstance().enableNFCByPrompt(); + } + } + + public String getTextDetails() { + int service_status; + try { + service_status = NFCManager.getInstance().getAvailableNFCServices(); + return Utilities.getNfcStatusDescription(service_status); + } catch (NFCException e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " " + e.getClass().getName()+":"+e.getMessage()); + return "Error establishing NFC service description"; + } + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/GraphicalButton.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/GraphicalButton.java new file mode 100644 index 0000000..7428221 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/GraphicalButton.java @@ -0,0 +1,58 @@ +package nfc.sample.nfctransaction.ui; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.ui.Graphics; +import net.rim.device.api.ui.component.BitmapField; + +public class GraphicalButton extends BitmapField { + + private boolean is_focused = false; + private Bitmap unfocused; + private Bitmap focused; + private int state=0; + + public GraphicalButton(Bitmap unfocused, Bitmap focused, boolean is_focused, long style) { + super(unfocused,style); + this.unfocused = unfocused; + this.focused = focused; + this.is_focused = is_focused; + } + + public void paint(Graphics g) { + if (is_focused) { + g.drawBitmap(0, 0, focused.getWidth(), focused.getHeight(), focused, 0, 0); + } else { + g.drawBitmap(0, 0, unfocused.getWidth(), unfocused.getHeight(), unfocused, 0, 0); + } + } + + public void setFocused(boolean focus_state) { + is_focused = focus_state; + } + + public boolean isFocused() { + return is_focused; + } + + public int getState() { + return state; + } + + public void setState(int state) { + this.state = state; + } +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/LabelFieldColoured.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/LabelFieldColoured.java new file mode 100644 index 0000000..fb71908 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/LabelFieldColoured.java @@ -0,0 +1,39 @@ +package nfc.sample.nfctransaction.ui; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.ui.Color; +import net.rim.device.api.ui.Graphics; +import net.rim.device.api.ui.component.LabelField; + +public class LabelFieldColoured extends LabelField { + + private int text_colour = Color.BLACK; + + public LabelFieldColoured(String text) { + super(text); + } + + public LabelFieldColoured(String text,int text_colour,long style) { + super(text,style); + this.text_colour = text_colour; + } + + public void paint(Graphics g) { + g.setColor(text_colour); + super.paint(g); + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/NfcSettingsScreen.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/NfcSettingsScreen.java new file mode 100644 index 0000000..30234f2 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/NfcSettingsScreen.java @@ -0,0 +1,213 @@ +package nfc.sample.nfctransaction.ui; + +/* + * Copyright (c) 2012 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.io.IOException; + +import net.rim.device.api.io.nfc.NFCException; +import net.rim.device.api.io.nfc.NFCManager; +import net.rim.device.api.io.nfc.emulation.TechnologyType; +import net.rim.device.api.io.nfc.se.SecureElement; +import net.rim.device.api.ui.Color; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.FieldChangeListener; +import net.rim.device.api.ui.component.ButtonField; +import net.rim.device.api.ui.component.CheckboxField; +import net.rim.device.api.ui.component.EditField; +import net.rim.device.api.ui.component.RadioButtonField; +import net.rim.device.api.ui.component.RadioButtonGroup; +import net.rim.device.api.ui.component.RichTextField; +import net.rim.device.api.ui.component.SeparatorField; +import net.rim.device.api.ui.container.MainScreen; +import net.rim.device.api.util.ByteArrayUtilities; +import nfc.sample.nfctransaction.Constants; +import nfc.sample.nfctransaction.NfcTransHandlerApp; +import nfc.sample.nfctransaction.Settings; +import nfc.sample.nfctransaction.Utilities; +import nfc.sample.nfctransaction.nfc.CardEmulation; +import nfc.sample.nfctransaction.nfc.NfcService; + +public class NfcSettingsScreen extends MainScreen { + + private Settings settings = Settings.getInstance(); + + private CardEmulation ce = CardEmulation.getInstance(); + private NfcService nfc = NfcService.getInstance(); + + private LabelFieldColoured lbl_se_choices = new LabelFieldColoured("Secure Element", Color.GREEN, Field.FIELD_LEFT); + private RadioButtonGroup se_choices = new RadioButtonGroup(); + private RadioButtonField se_sim = new RadioButtonField("SIM", se_choices, true); + private RadioButtonField se_embedded = new RadioButtonField("EMBEDDED", se_choices, false); + + private LabelFieldColoured lbl_pr_choices = new LabelFieldColoured("Protocols", Color.GREEN, Field.FIELD_LEFT); + private CheckboxField cbx_iso1443a = new CheckboxField("ISO14443A", false); + private CheckboxField cbx_iso1443b = new CheckboxField("ISO14443B", true); + private CheckboxField cbx_iso1443b_prime = new CheckboxField("ISO14443B PRIME", false); + + private LabelFieldColoured lbl_aid = new LabelFieldColoured("AID", Color.GREEN, Field.FIELD_LEFT); + private EditField edt_aid = new EditField("",""); + + private LabelFieldColoured lbl_apdu = new LabelFieldColoured("APDU", Color.GREEN, Field.FIELD_LEFT); + private EditField edt_apdu = new EditField("",""); + + private ButtonField btn_save_settings = new ButtonField("Apply", ButtonField.CONSUME_CLICK); + private SeparatorField separator = new SeparatorField(); + private LabelFieldColoured lbl_nfc_service_details = new LabelFieldColoured("NFC Service Details", Color.GREEN, + Field.FIELD_LEFT); + private RichTextField rtf_nfc_service_details = new RichTextField(); + + private FieldChangeListener listener = new FieldChangeListener() { + + public void fieldChanged(Field field, int context) { + if(field == btn_save_settings) { + save(); + } + } + }; + + private int current_se; + private int current_tt; + private boolean aid_changed=false; + + public NfcSettingsScreen() { + setTitle("NFCTransactionHandler V" + Constants.VERSION + "-Settings"); + add(lbl_se_choices); + add(se_sim); + add(se_embedded); + add(lbl_pr_choices); + add(cbx_iso1443a); + add(cbx_iso1443b); + add(cbx_iso1443b_prime); + add(lbl_aid); + edt_aid.setText(settings.getRegisteredAIDAsString()); + add(edt_aid); + add(lbl_apdu); + edt_apdu.setText(settings.getAPDUAsString()); + add(edt_apdu); + add(btn_save_settings); + btn_save_settings.setChangeListener(listener); + add(separator); + add(lbl_nfc_service_details); + String nfc_details = ""; + try { + nfc_details = Utilities.getNfcStatusDescription(NFCManager.getInstance().getEnabledNFCServices()); + } catch(NFCException e) { + nfc_details = e.getClass().getName() + ":" + e.getMessage(); + } + rtf_nfc_service_details.setText(nfc_details); + add(rtf_nfc_service_details); + syncUiWithNfcSettings(); + } + + private void syncUiWithNfcSettings() { + current_se = ce.getCurrentSecureElement(); + current_tt = ce.getCurrentTechnologyTypes(); + if(current_se == SecureElement.SIM) { + se_sim.setSelected(true); + se_embedded.setSelected(false); + } else { + se_sim.setSelected(false); + se_embedded.setSelected(true); + } + try { + int tech_types = ce.getTechnologyTypes(SecureElement.BATTERY_ON_MODE); + if((tech_types & TechnologyType.ISO14443A) == TechnologyType.ISO14443A) { + cbx_iso1443a.setChecked(true); + } else { + cbx_iso1443a.setChecked(false); + } + if((tech_types & TechnologyType.ISO14443B) == TechnologyType.ISO14443B) { + cbx_iso1443b.setChecked(true); + } else { + cbx_iso1443b.setChecked(false); + } + if((tech_types & TechnologyType.ISO14443B_PRIME) == TechnologyType.ISO14443B_PRIME) { + cbx_iso1443b_prime.setChecked(true); + } else { + cbx_iso1443b_prime.setChecked(false); + } + } catch(NFCException e) { + } + } + + public void save() { + applySettings(); + settings.saveSettings(); + try { + super.save(); + } catch(IOException e) { + } + } + + private void applySettings() { + try { + if((current_se == SecureElement.SIM) && (se_choices.getSelectedIndex() == 1)) { + ce.initCe(SecureElement.EMBEDDED); + settings.setSeEmbedded(); + } else { + if((current_se == SecureElement.EMBEDDED) && (se_choices.getSelectedIndex() == 0)) { + ce.initCe(SecureElement.SIM); + settings.setSeSIM(); + } + } + } catch(NFCException e) { + Utilities.popupAlert("Error: could not change SE selection"); + return; + } + int tech_types = TechnologyType.NONE; + if(cbx_iso1443a.getChecked() == true) { + tech_types = tech_types | TechnologyType.ISO14443A; + } + if(cbx_iso1443b.getChecked() == true) { + tech_types = tech_types | TechnologyType.ISO14443B; + } + if(cbx_iso1443b_prime.getChecked() == true) { + tech_types = tech_types | TechnologyType.ISO14443B_PRIME; + } + settings.setISO14443A(cbx_iso1443a.getChecked()); + settings.setISO14443B(cbx_iso1443b.getChecked()); + settings.setISO14443B_PRIME(cbx_iso1443b_prime.getChecked()); + if (!settings.getRegisteredAIDAsString().equals(edt_aid.getText())) { + settings.setRegisteredAID(edt_aid.getText()); + CardEmulation ce = CardEmulation.getInstance(); + ce.removeTransactionListener(); + CardEmulation.registerTransactionListener(NfcTransHandlerApp.getTransactionListener()); + } + + settings.setAPDU(edt_apdu.getText()); + + Utilities.log("XXXX " + Thread.currentThread().getName() + " Selected tech types=" + + Utilities.getTechnologyTypesNames(tech_types)); + + if(current_tt != tech_types) { + try { + ce.setRoutingOn(tech_types); + } catch(NFCException e) { + Utilities.popupAlert("Error: could not change CE technology types"); + return; + } catch(Exception e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " " + e.getClass().getName() + ":" + e.getMessage()); + Utilities.popupAlert(e.getClass().getName() + ": could not change CE technology types"); + return; + } + } + Utilities.log("XXXX " + Thread.currentThread().getName() + " applySettings 11"); + setDirty(false); + Utilities.log("XXXX " + Thread.currentThread().getName() + " applySettings 12"); + Utilities.popupMessage("New settings applied"); + + } +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/NfcTransScreen.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/NfcTransScreen.java new file mode 100644 index 0000000..0e77fa8 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/NfcTransScreen.java @@ -0,0 +1,577 @@ +package nfc.sample.nfctransaction.ui; + +/* + * Copyright (c) 2012 Research In Motion Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import net.rim.device.api.command.Command; +import net.rim.device.api.io.nfc.NFCException; +import net.rim.device.api.io.nfc.NFCManager; +import net.rim.device.api.io.nfc.se.SecureElement; +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.system.Display; +import net.rim.device.api.system.RuntimeStore; +import net.rim.device.api.ui.Color; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.FieldChangeListener; +import net.rim.device.api.ui.FocusChangeListener; +import net.rim.device.api.ui.MenuItem; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.component.BitmapField; +import net.rim.device.api.ui.component.LabelField; +import net.rim.device.api.ui.container.AbsoluteFieldManager; +import net.rim.device.api.ui.container.MainScreen; +import net.rim.device.api.ui.decor.Background; +import net.rim.device.api.ui.decor.BackgroundFactory; +import net.rim.device.api.util.StringProvider; +import nfc.sample.nfctransaction.Constants; +import nfc.sample.nfctransaction.NfcTransHandlerApp; +import nfc.sample.nfctransaction.Settings; +import nfc.sample.nfctransaction.Utilities; +import nfc.sample.nfctransaction.commands.ClearCommand; +import nfc.sample.nfctransaction.commands.CloseCommand; +import nfc.sample.nfctransaction.commands.KillCommand; +import nfc.sample.nfctransaction.commands.Iso7816Command; +import nfc.sample.nfctransaction.commands.SettingsCommand; +import nfc.sample.nfctransaction.commands.ToggleCeCommand; +import nfc.sample.nfctransaction.nfc.CardEmulation; +import nfc.sample.nfctransaction.nfc.MyNfcStatusListener; +import nfc.sample.nfctransaction.nfc.NfcService; +import nfc.sample.nfctransaction.ui.buttons.MsbConfig; +import nfc.sample.nfctransaction.ui.buttons.MsbState; +import nfc.sample.nfctransaction.ui.buttons.MultiStateButtonField; + +public final class NfcTransScreen extends MainScreen implements Runnable { + + private static NfcTransScreen screen; + private static MyNfcStatusListener nfc_status_listener = new MyNfcStatusListener(); + private Settings settings = Settings.getInstance(); + + private NfcService nfc_service = NfcService.getInstance(); + private CardEmulation ce = CardEmulation.getInstance(); + + private AbsoluteFieldManager mgr = new AbsoluteFieldManager(); + + private Bitmap ce_on_focused = Bitmap.getBitmapResource("ce_on_focused.png"); + private Bitmap ce_on_unfocused = Bitmap.getBitmapResource("ce_on_unfocused.png"); + private Bitmap ce_on_clicked = Bitmap.getBitmapResource("ce_on_clicked.png"); + private Bitmap ce_on_unclicked = Bitmap.getBitmapResource("ce_on_focused.png"); + + private Bitmap ce_off_focused = Bitmap.getBitmapResource("ce_off_focused.png"); + private Bitmap ce_off_unfocused = Bitmap.getBitmapResource("ce_off_unfocused.png"); + private Bitmap ce_off_clicked = Bitmap.getBitmapResource("ce_off_clicked.png"); + private Bitmap ce_off_unclicked = Bitmap.getBitmapResource("ce_off_focused.png"); + + private Bitmap clear_focused = Bitmap.getBitmapResource("clear_focused.png"); + private Bitmap clear_unfocused = Bitmap.getBitmapResource("clear_unfocused.png"); + private Bitmap clear_clicked = Bitmap.getBitmapResource("clear_clicked.png"); + private Bitmap clear_unclicked = Bitmap.getBitmapResource("clear_focused.png"); + + private Bitmap select_on_focused = Bitmap.getBitmapResource("select_focused.png"); + private Bitmap select_on_unfocused = Bitmap.getBitmapResource("select_unfocused.png"); + private Bitmap select_on_clicked = Bitmap.getBitmapResource("select_clicked.png"); + private Bitmap select_on_unclicked = Bitmap.getBitmapResource("select_focused.png"); + + private Bitmap select_off_focused = Bitmap.getBitmapResource("select_disabled_focused.png"); + private Bitmap select_off_unfocused = Bitmap.getBitmapResource("select_disabled.png"); + private Bitmap select_off_clicked = Bitmap.getBitmapResource("select_disabled.png"); + private Bitmap select_off_unclicked = Bitmap.getBitmapResource("select_disabled.png"); + + private Bitmap close_focused = Bitmap.getBitmapResource("close_focused.png"); + private Bitmap close_unfocused = Bitmap.getBitmapResource("close_unfocused.png"); + private Bitmap close_clicked = Bitmap.getBitmapResource("close_clicked.png"); + private Bitmap close_unclicked = Bitmap.getBitmapResource("close_focused.png"); + + private Bitmap bmp_nfc_led_on = Bitmap.getBitmapResource("nfc_led_on.png"); + private Bitmap bmp_nfc_led_off = Bitmap.getBitmapResource("nfc_led_off.png"); + private Bitmap bmp_nfc_led_err = Bitmap.getBitmapResource("nfc_led_err.png"); + + private Bitmap bmp_ce_led_on = Bitmap.getBitmapResource("ce_led_on.png"); + private Bitmap bmp_ce_led_off = Bitmap.getBitmapResource("ce_led_off.png"); + private Bitmap bmp_ce_led_err = Bitmap.getBitmapResource("ce_led_err.png"); + + private BitmapField nfc_led = new BitmapField(bmp_nfc_led_off); + private BitmapField cem_led = new BitmapField(bmp_ce_led_off); + + private LabelFieldColoured last_aids = new LabelFieldColoured("", Color.RED, Field.FIELD_HCENTER); + private int last_aids_y; + + private TimedLabelField user_message = new TimedLabelField("", Field.FIELD_HCENTER); + private int user_message_x; + private int user_message_y; + + private Background focus_bg = BackgroundFactory.createSolidBackground(Color.LIGHTBLUE); + + private MenuItem mi_kill = new MenuItem(new StringProvider("Kill"), 110, 10); + + private MenuItem mi_settings = new MenuItem(new StringProvider("Settings"), 110, 10); + + private MultiStateButtonField msbf_ce_on; + private MultiStateButtonField msbf_clear; + private MultiStateButtonField msbf_select; + private MultiStateButtonField msbf_close; + + private int focused_button = 0; + + boolean ce_enabled = false; + boolean cem_led_err = false; + boolean nfc_led_err = false; + + private FocusChangeListener focus_listener = new FocusChangeListener() { + + public void focusChanged(Field field, int eventType) { + if(field == msbf_ce_on) { + focused_button = 0; + } + if(field == msbf_clear) { + focused_button = 1; + } + if(field == msbf_select) { + focused_button = 2; + } + if(field == msbf_close) { + focused_button = 3; + } + } + }; + + private FieldChangeListener centre_text_listener = new FieldChangeListener() { + public void fieldChanged(Field field, int context) { + if (field == user_message || field == last_aids) { + LabelField label = (LabelField) field; + String content = label.getText(); + int msg_width = Utilities.getTextWidth(content); + int x = (Display.getWidth() - msg_width) / 2; + int y=0; + if (field == user_message) { + y = user_message_y; + } else { + y = last_aids_y; + } + Utilities.log("XXXX " + Thread.currentThread().getName() + " repositioning user message:" + x+","+user_message_y); + mgr.setPosChild(field, x, y); + } + } + }; + + public static synchronized NfcTransScreen getInstance() { + if(screen == null) { + screen = new NfcTransScreen(); + } + return screen; + } + + private NfcTransScreen() { + super(USE_ALL_HEIGHT | USE_ALL_WIDTH | FIELD_HCENTER | NO_VERTICAL_SCROLL); + Utilities.log("XXXX " + Thread.currentThread().getName() + " constructing NfcTransScreen"); + setTitle("NFCTransactionHandler V" + Constants.VERSION); + + clearLastAIDs(); + + user_message.setChangeListener(centre_text_listener); + last_aids.setChangeListener(centre_text_listener); + + mi_kill.setCommandContext(this); + mi_kill.setCommand(new Command(new KillCommand())); + addMenuItem(mi_kill); + + mi_settings.setCommandContext(this); + mi_settings.setCommand(new Command(new SettingsCommand())); + addMenuItem(mi_settings); + + try { + if(nfc_service.isNfcEnabled()) { + nfc_led = new BitmapField(bmp_nfc_led_on); + } else { + nfc_led = new BitmapField(bmp_nfc_led_off); + } + } catch(NFCException e2) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " from isNfcEnabled()"); + nfc_led = new BitmapField(bmp_nfc_led_err); + } + nfc_led.setPadding(7, 0, 0, 0); + + try { + ce.initCe(ce.getCurrentSecureElement()); + if(!ce.isSe_obtained()) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " SecureElement(SIM) not available"); + setUserMessage("Error: could not acquire SE"); + cem_led_err = true; + } else { + try { + ce_enabled = ce.isCeEnabled(SecureElement.BATTERY_ON_MODE); + if(ce_enabled) { + cem_led = new BitmapField(bmp_ce_led_on); + } else { + cem_led = new BitmapField(bmp_ce_led_off); + } + } catch(Exception e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " exception when enabling CE: " + e.getClass().getName() + ":" + e.getMessage()); + cem_led = new BitmapField(bmp_ce_led_err); + } + } + } catch(NFCException e1) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " exception when getting SE: " + e1.getClass().getName() + ":" + e1.getMessage()); + setUserMessage("Error: could not acquire SE"); + nfc_led_err = true; + cem_led_err = true; + } + cem_led.setPadding(7, 0, 0, 0); + + // bitmaps are 120 x 120 + int hgap = (int) ((Display.getWidth() - 240) / 3); + int vgap = (int) (Display.getHeight() - 240) / 6; + int x1 = hgap; + int x2 = x1 + 120 + hgap; + int y1 = bmp_nfc_led_on.getHeight() + 4; + int y2 = y1 + 120 + (vgap / 4); + int y3 = y2 + 120 + 10; + last_aids_y = y3; + user_message_y = y3 + vgap; + user_message_x = (Display.getWidth() - Utilities.getTextWidth(Constants.READY)) / 2; + int x_centre_1 = x1 + 60; + int x_centre_2 = x2 + 60; + int last_aids_x = (Display.getWidth() - Utilities.getTextWidth(Constants.AID_SPACE)) / 2; + + // centre LEDs over the button columns + mgr.add(nfc_led, x_centre_1 - (bmp_nfc_led_on.getWidth() / 2), 0); + mgr.add(cem_led, x_centre_2 - (bmp_ce_led_on.getWidth() / 2), 0); + + MsbConfig config1 = new MsbConfig(); + MsbState ce_off = new MsbState(Constants.BTN_CE_OFF, "Switch card emulation OFF", "CE OFF"); + ce_off.setbmp_focused(ce_off_focused); + ce_off.setbmp_unfocused(ce_off_unfocused); + ce_off.setbmp_clicked(ce_off_clicked); + ce_off.setbmp_unclicked(ce_off_unclicked); + config1.addState(ce_off); + MsbState ce_on = new MsbState(Constants.BTN_CE_ON, "Switch card emulation ON", "CE ON"); + ce_on.setbmp_focused(ce_on_focused); + ce_on.setbmp_unfocused(ce_on_unfocused); + ce_on.setbmp_clicked(ce_on_clicked); + ce_on.setbmp_unclicked(ce_on_unclicked); + config1.addState(ce_on); + msbf_ce_on = new MultiStateButtonField(config1, new ToggleCeCommand(), 0, Field.FIELD_HCENTER); + mgr.add(msbf_ce_on, x1, y1); + + MsbConfig config2 = new MsbConfig(); + MsbState clear = new MsbState(Constants.BTN_DEFAULT, "Clear last AID received field", "Clear"); + clear.setbmp_focused(clear_focused); + clear.setbmp_unfocused(clear_unfocused); + clear.setbmp_clicked(clear_clicked); + clear.setbmp_unclicked(clear_unclicked); + config2.addState(clear); + msbf_clear = new MultiStateButtonField(config2, new ClearCommand(), 0, Field.FIELD_HCENTER); + mgr.add(msbf_clear, x2, y1); + + MsbConfig config3 = new MsbConfig(); + MsbState select_on = new MsbState(Constants.BTN_DEFAULT, "Select applet", "Select"); + select_on.setbmp_focused(select_on_focused); + select_on.setbmp_unfocused(select_on_unfocused); + select_on.setbmp_clicked(select_on_clicked); + select_on.setbmp_unclicked(select_on_unclicked); + config3.addState(select_on); + MsbState select_off = new MsbState(Constants.BTN_SELECT_OFF, "Select applet", "Select"); + select_off.setbmp_focused(select_off_focused); + select_off.setbmp_unfocused(select_off_unfocused); + select_off.setbmp_clicked(select_off_clicked); + select_off.setbmp_unclicked(select_off_unclicked); + config3.addState(select_off); + Iso7816Command select_command = new Iso7816Command(); + msbf_select = new MultiStateButtonField(config3, select_command, 0, Field.FIELD_HCENTER); + mgr.add(msbf_select, x1, y2); + + MsbConfig config4 = new MsbConfig(); + MsbState close = new MsbState(0, "Send to background", "Close"); + close.setbmp_focused(close_focused); + close.setbmp_unfocused(close_unfocused); + close.setbmp_clicked(close_clicked); + close.setbmp_unclicked(close_unclicked); + config4.addState(close); + msbf_close = new MultiStateButtonField(config4, new CloseCommand(), 0, Field.FIELD_HCENTER); + mgr.add(msbf_close, x2, y2); + + mgr.add(last_aids, last_aids_x, last_aids_y); + mgr.add(user_message, user_message_x, user_message_y); + + add(mgr); + + msbf_ce_on.setFocusListener(focus_listener); + msbf_clear.setFocusListener(focus_listener); + msbf_select.setFocusListener(focus_listener); + msbf_close.setFocusListener(focus_listener); + + screen = this; + setUiRunningIndication(); + } + + public void init() { + setCeButtonState(ce_enabled); + try { + NFCManager.addNFCStatusListener(nfc_status_listener); + } catch(NFCException e) { + Utilities.log("XXXX exception when adding NFCStatusListener: " + e.getClass().getName() + ":" + e.getMessage()); + } + focused_button = 0; + msbf_ce_on.setFocus(); + msbf_ce_on.setImage(); + + } + + private void setUiRunningIndication() { + Object ui_running_token = new Object(); + RuntimeStore rts = RuntimeStore.getRuntimeStore(); + rts.replace(Constants.UI_IS_RUNNING, ui_running_token); + } + + public void startRtsMonitorThread() { + Thread thread = new Thread(this); + thread.start(); + } + + public boolean onClose() { + closeScreen(); + return false; + } + + public void setAidsReceived(String aids) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " updating UI with AID:" + aids); + synchronized(UiApplication.getUiApplication().getEventLock()) { + last_aids.setText(aids); + } + } + + public void run() { + boolean running = true; + Utilities.log("XXXX " + Thread.currentThread().getName() + " Starting RuntimeStore monitoring for screen"); + while(running) { + try { + RuntimeStore rts = RuntimeStore.getRuntimeStore(); + try { + Utilities.log("XXXX " + Thread.currentThread().getName() + " waiting for object from RTS"); + Object obj = rts.waitFor(NfcTransHandlerApp.PASSED_TO_UI_DATA_ID); + Utilities.log("XXXX " + Thread.currentThread().getName() + " got object from RTS=" + obj); + if(obj != null) { + String aids_received = (String) rts.remove(NfcTransHandlerApp.PASSED_TO_UI_DATA_ID); + Utilities.log("XXXX " + Thread.currentThread().getName() + " AIDs received are:" + aids_received); + setAidsReceived(Utilities.hexPresentation(aids_received)); + UiApplication.getApplication().requestForeground(); + + } + } catch(RuntimeException e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " RunTimeException - probably timed out waiting for object in RTS"); + } + + } catch(Exception e) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " Exception in RTS loop: " + e.getClass().getName() + ":" + e.getMessage()); + System.out.println("XXXX " + Thread.currentThread().getName() + " Exception in RTS loop: " + e.getClass().getName() + ":" + e.getMessage()); + } + } + } + + public void clearLastAIDs() { + last_aids.setText(Constants.AID_SPACE); + Utilities.log("XXXX " + Thread.currentThread().getName() + " AID field cleared"); + } + + public void closeScreen() { + // don't actually close otherwise our thread which is receiving the NFC transactions will exit as the app will be fully + // closed + UiApplication.getUiApplication().requestBackground(); + } + + public void setNfcLed(int state) { + synchronized(UiApplication.getEventLock()) { + switch(state) { + case Constants.LED_OFF: + nfc_led.setBitmap(bmp_nfc_led_off); + break; + case Constants.LED_ON: + nfc_led.setBitmap(bmp_nfc_led_on); + break; + case Constants.LED_ERR: + Utilities.log("XXXX " + Thread.currentThread().getName() + " NFC LED set to ERR state"); + nfc_led.setBitmap(bmp_nfc_led_err); + break; + } + } + } + + public void setCemLed(final int state) { + UiApplication.getUiApplication().invokeAndWait(new Runnable() { + public void run() { + switch(state) { + case Constants.LED_OFF: + cem_led.setBitmap(bmp_ce_led_off); + break; + case Constants.LED_ON: + cem_led.setBitmap(bmp_ce_led_on); + break; + case Constants.LED_ERR: + Utilities.log("XXXX " + Thread.currentThread().getName() + " CEM LED set to ERR state"); + cem_led.setBitmap(bmp_ce_led_err); + break; + } + } + }); + } + + public void nfcStateChanged(boolean nfc_on, boolean ce_on) { + if(nfc_on) { + setNfcLed(Constants.LED_ON); + if(ce_on) { + setCemLed(Constants.LED_ON); + setCeButtonState(true); + setSelectButtonState(true); + } + } else { + setNfcLed(Constants.LED_OFF); + setCemLed(Constants.LED_OFF); + setCeButtonState(false); + setSelectButtonState(false); + try { + ce.setRoutingOff(); + } catch(NFCException e) { + } + } + } + + public void setUserMessage(final String message) { + UiApplication.getUiApplication().invokeAndWait(new Runnable() { + public void run() { + user_message.setLabelText(message); + } + }); + } + + public void setCeButtonState(final boolean on) { + Utilities.log("XXXX " + Thread.currentThread().getName() + " setting CE button state to on=" + on); + UiApplication.getUiApplication().invokeAndWait(new Runnable() { + public void run() { + if(on) { + msbf_ce_on.setMsbState(Constants.BTN_CE_OFF); + } else { + msbf_ce_on.setMsbState(Constants.BTN_CE_ON); + } + } + }); + } + + public void setSelectButtonState(final boolean on) { + UiApplication.getUiApplication().invokeAndWait(new Runnable() { + public void run() { + if(on) { + msbf_select.setMsbState(Constants.BTN_SELECT_ON); + } else { + msbf_select.setMsbState(Constants.BTN_SELECT_OFF); + } + } + }); + } + + protected boolean navigationMovement(int dx, int dy, int status, int time) { + + int x_dir = 0; + int y_dir = 0; + + if(dx > 0) { + x_dir = 1; + } + if(dx < 0) { + x_dir = -1; + } + + if(dy > 0) { + y_dir = 1; + } + if(dy < 0) { + y_dir = -1; + } + setFocusedButton(x_dir, y_dir); + return true; + } + + private void setFocusedButton(int x_dir, int y_dir) { + switch(focused_button) { + case 0: + if(x_dir == 1 && y_dir == 0) { + focused_button = 1; + msbf_clear.setFocus(); + return; + } + if(x_dir == 0 && y_dir == 1) { + focused_button = 2; + msbf_select.setFocus(); + return; + } + if(x_dir == 1 && y_dir == 1) { + focused_button = 3; + msbf_close.setFocus(); + return; + } + break; + case 1: + if(x_dir == -1 && y_dir == 0) { + focused_button = 0; + msbf_ce_on.setFocus(); + return; + } + if(x_dir == 0 && y_dir == 1) { + focused_button = 3; + msbf_close.setFocus(); + return; + } + if(x_dir == -1 && y_dir == 1) { + focused_button = 2; + msbf_select.setFocus(); + return; + } + break; + case 2: + if(x_dir == 1 && y_dir == 0) { + focused_button = 3; + msbf_close.setFocus(); + return; + } + if(x_dir == 0 && y_dir == -1) { + focused_button = 0; + msbf_ce_on.setFocus(); + return; + } + if(x_dir == 1 && y_dir == -1) { + focused_button = 1; + msbf_clear.setFocus(); + return; + } + break; + case 3: + if(x_dir == -1 && y_dir == 0) { + focused_button = 2; + msbf_select.setFocus(); + return; + } + if(x_dir == 0 && y_dir == -1) { + focused_button = 1; + msbf_clear.setFocus(); + return; + } + if(x_dir == -1 && y_dir == -1) { + focused_button = 0; + msbf_ce_on.setFocus(); + return; + } + break; + } + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/TextDetailsProvider.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/TextDetailsProvider.java new file mode 100644 index 0000000..ae14516 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/TextDetailsProvider.java @@ -0,0 +1,21 @@ +package nfc.sample.nfctransaction.ui; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +public interface TextDetailsProvider { + + public String getTextDetails(); + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/TimedLabelField.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/TimedLabelField.java new file mode 100644 index 0000000..dda8541 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/TimedLabelField.java @@ -0,0 +1,53 @@ +package nfc.sample.nfctransaction.ui; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.component.LabelField; +import nfc.sample.nfctransaction.Constants; + +public class TimedLabelField extends LabelField implements Runnable { + + private String new_value=""; + + public TimedLabelField(String value,long style) { + super(value,style); + } + + public void run() { + synchronized (UiApplication.getEventLock()) { + setText(new_value); + } + + try { + Thread.sleep(3000); + synchronized (UiApplication.getEventLock()) { + setText(Constants.READY); + } + } catch (InterruptedException e) { + synchronized (UiApplication.getEventLock()) { + setText(e.getClass().getName()+":"+e.getMessage()); + } + } + } + + public void setLabelText(String text) { + new_value = text; + Thread t = new Thread(this); + t.start(); + } +} + + diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/buttons/MsbConfig.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/buttons/MsbConfig.java new file mode 100644 index 0000000..d57cd75 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/buttons/MsbConfig.java @@ -0,0 +1,40 @@ +package nfc.sample.nfctransaction.ui.buttons; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import java.util.Hashtable; + + +/** + * A MultiStateButtonField has a series of states, each of which has multiple visual indications depending on + * focused/unfocused + * click/unclick + * + */ +public class MsbConfig { + + private Hashtable states = new Hashtable(); + + public void addState(MsbState state) { + Integer key = new Integer(state.getState_id()); + states.put(key,state); + } + + public MsbState getState(int state_id) { + MsbState state = (MsbState) states.get(new Integer(state_id)); + return state; + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/buttons/MsbState.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/buttons/MsbState.java new file mode 100644 index 0000000..2e46944 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/buttons/MsbState.java @@ -0,0 +1,103 @@ +package nfc.sample.nfctransaction.ui.buttons; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.system.Bitmap; + +public class MsbState { + + public static final int DEFAULT_STATE=0; + + private int state_id; // zero is the default state + private String state_description; // e.g. "Service is currently ON" + private String state_label; // for display on buttons e.g. "ON" + + private Bitmap bmp_unfocused; + private Bitmap bmp_focused; + private Bitmap bmp_clicked; + private Bitmap bmp_unclicked; + + public MsbState(int state_id, String state_description, String state_label) { + this.state_id = state_id; + this.state_description = state_description; + this.state_label = state_label; + } + + public boolean equals(Object obj) { + if (obj instanceof MsbState) { + if (((MsbState) obj).getState_id() == this.state_id) { + return true; + } + } + return false; + } + + public int getState_id() { + return state_id; + } + + public void setState_id(int state_id) { + this.state_id = state_id; + } + + public String getState_description() { + return state_description; + } + + public void setState_description(String state_description) { + this.state_description = state_description; + } + + public String getState_label() { + return state_label; + } + + public void setState_label(String state_label) { + this.state_label = state_label; + } + + public Bitmap getbmp_unfocused() { + return bmp_unfocused; + } + + public void setbmp_unfocused(Bitmap bmp_unfocused) { + this.bmp_unfocused = bmp_unfocused; + } + + public Bitmap getbmp_focused() { + return bmp_focused; + } + + public void setbmp_focused(Bitmap bmp_focused) { + this.bmp_focused = bmp_focused; + } + + public Bitmap getbmp_clicked() { + return bmp_clicked; + } + + public void setbmp_clicked(Bitmap bmp_clicked) { + this.bmp_clicked = bmp_clicked; + } + + public Bitmap getbmp_unclicked() { + return bmp_unclicked; + } + + public void setbmp_unclicked(Bitmap bmp_unclicked) { + this.bmp_unclicked = bmp_unclicked; + } + +} diff --git a/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/buttons/MultiStateButtonField.java b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/buttons/MultiStateButtonField.java new file mode 100644 index 0000000..0a319b6 --- /dev/null +++ b/NFC/NfcTransactionHandler/src/nfc/sample/nfctransaction/ui/buttons/MultiStateButtonField.java @@ -0,0 +1,143 @@ +package nfc.sample.nfctransaction.ui.buttons; +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.Graphics; +import net.rim.device.api.ui.TouchEvent; +import nfc.sample.nfctransaction.Utilities; + +public class MultiStateButtonField extends Field { + + private MsbConfig config; + private int current_state; + private Bitmap current_bitmap; + private AlwaysExecutableCommand command; + + public MultiStateButtonField(MsbConfig config, AlwaysExecutableCommand command,int initial_state, long style) { + super(style); + this.config = config; + this.command = command; + this.current_state = initial_state; + current_bitmap = config.getState(initial_state).getbmp_unfocused(); + } + + protected void paint(Graphics graphics) { + if (current_bitmap != null) { + graphics.drawBitmap(0, 0, current_bitmap.getWidth(), current_bitmap.getHeight(), current_bitmap, 0, 0); + } else { + Utilities.log("XXXX "+config.getState(current_state).getState_label()+"-ERROR:current_bitmap=null"); + } + } + + protected void drawFocus(Graphics graphics, + boolean on) { + } + + public void setMsbState(int state_id) { + current_state = state_id; + current_bitmap = config.getState(state_id).getbmp_unfocused(); + } + + public int getMsbState() { + return current_state; + } + + protected boolean navigationClick(int status, + int time) { + setFocus(); + if (config.getState(current_state).getbmp_clicked() != null) { + current_bitmap = config.getState(current_state).getbmp_clicked(); + invalidate(); + } + return true; + } + + protected boolean navigationUnclick(int status, + int time) { + if (config.getState(current_state).getbmp_unclicked() != null) { + current_bitmap = config.getState(current_state).getbmp_unclicked(); + invalidate(); + } + // pass button so we can check its state + command.execute(null, this); + return true; + } + + protected boolean touchEvent(TouchEvent message) { + if (message.getY(1) < 0) { + return false; + } + if (message.getY(1) > getHeight()){ + return false; + } + if (message.getX(1) < 0){ + return false; + } + if (message.getX(1) > getWidth()){ + return false; + } + + setFocus(); + if (message.getEvent() == TouchEvent.DOWN && config.getState(current_state).getbmp_clicked() != null) { + current_bitmap = config.getState(current_state).getbmp_clicked(); + invalidate(); + return true; + } + if (message.getEvent() == TouchEvent.UP && config.getState(current_state).getbmp_focused() != null) { + current_bitmap = config.getState(current_state).getbmp_focused(); + invalidate(); + command.execute(null, null); + return true; + } + return false; + } + + protected void onFocus(int direction) { + if (config.getState(current_state).getbmp_focused() != null) { + current_bitmap = config.getState(current_state).getbmp_focused(); + invalidate(); + } + } + + protected void onUnfocus() { + if (config.getState(current_state).getbmp_unfocused() != null) { + current_bitmap = config.getState(current_state).getbmp_unfocused(); + invalidate(); + } + } + + public void setImage() { + current_bitmap = config.getState(current_state).getbmp_focused(); + } + + public boolean isFocusable() { + return true; + } + + protected void layout(int width, int height) { + setExtent(current_bitmap.getWidth(),current_bitmap.getHeight()); + } + + public int getPreferredWidth() { + return current_bitmap.getWidth(); + } + + public int getPreferredHeight() { + return current_bitmap.getHeight(); + } +} diff --git a/NFC/NfcVirtualTargetFun/BlackBerry_App_Descriptor.xml b/NFC/NfcVirtualTargetFun/BlackBerry_App_Descriptor.xml index cc2fb33..a5096b2 100644 --- a/NFC/NfcVirtualTargetFun/BlackBerry_App_Descriptor.xml +++ b/NFC/NfcVirtualTargetFun/BlackBerry_App_Descriptor.xml @@ -1,7 +1,7 @@ - + diff --git a/NFC/NfcVirtualTargetFun/README.md b/NFC/NfcVirtualTargetFun/README.md index 56750e7..2d3d9cb 100644 --- a/NFC/NfcVirtualTargetFun/README.md +++ b/NFC/NfcVirtualTargetFun/README.md @@ -32,12 +32,12 @@ None ## Contributing Changes -Please see the [README](https://github.com/blackberry/BlackBerry-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. +Please see the [README](https://github.com/blackberry/Samples-For-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. ## Bug Reporting and Feature Requests -If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/BlackBerry-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/BlackBerry-Java/issues). +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-For-Java/issues) for the Sample. ## Disclaimer diff --git a/NFC/NfcVirtualTargetFun/src/nfc/sample/virtual/target/Constants.java b/NFC/NfcVirtualTargetFun/src/nfc/sample/virtual/target/Constants.java index 2769cd9..0088a37 100644 --- a/NFC/NfcVirtualTargetFun/src/nfc/sample/virtual/target/Constants.java +++ b/NFC/NfcVirtualTargetFun/src/nfc/sample/virtual/target/Constants.java @@ -17,8 +17,8 @@ public interface Constants { - public static final String MYAPP_VERSION = "1.0.6"; - public static final String MY_ISO_TARGET_ID = "12131415"; + public static final String MYAPP_VERSION = "1.0.7"; + public static final String MY_ISO_TARGET_ID = "1213141"; // length 4, 7 or 10 by NFC specification public static final int DISPLAY_COLUMN_WIDTH = 8; public static final int SC_BTN_STATE=0; diff --git a/NFC/NfcWriteNdefSmartTag/README.md b/NFC/NfcWriteNdefSmartTag/README.md index 8d8e4bd..49c244a 100644 --- a/NFC/NfcWriteNdefSmartTag/README.md +++ b/NFC/NfcWriteNdefSmartTag/README.md @@ -32,12 +32,12 @@ None ## Contributing Changes -Please see the [README](https://github.com/blackberry/BlackBerry-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. +Please see the [README](https://github.com/blackberry/Samples-For-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. ## Bug Reporting and Feature Requests -If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/BlackBerry-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/BlackBerry-Java/issues). +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-For-Java/issues) for the Sample. ## Disclaimer diff --git a/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/Constants.java b/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/Constants.java index bf8d275..e23fe3b 100644 --- a/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/Constants.java +++ b/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/Constants.java @@ -17,7 +17,7 @@ public interface Constants { - public static final String MYAPP_VERSION = "1.1.1"; + public static final String MYAPP_VERSION = "1.1.2"; public static final int BTN_STATE=0; diff --git a/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/CustomTagScreen.java b/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/CustomTagScreen.java index dfe4cc2..427e9d6 100644 --- a/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/CustomTagScreen.java +++ b/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/CustomTagScreen.java @@ -61,9 +61,6 @@ public class CustomTagScreen extends MainScreen implements TagCreatorScreen { private RichTextField heading = new RichTextField(); - private MenuItem mi_reg = new MenuItem(new StringProvider("Start listening"), 110, 10); - private MenuItem mi_unreg = new MenuItem(new StringProvider("Stop listening"), 110, 10); - private Hashtable _tag_attrs = new Hashtable(); /* @@ -99,14 +96,6 @@ public CustomTagScreen() { add(_log); - mi_reg.setCommandContext(_smartTagListener); - mi_reg.setCommand(new Command(new RegisterCommand(this))); - addMenuItem(mi_reg); - - mi_unreg.setCommandContext(_smartTagListener); - mi_unreg.setCommand(new Command(new UnregisterCommand(this))); - addMenuItem(mi_unreg); - _listener_mgr.set_log_screen(this); _listener_mgr.registerListener(_smartTagListener); diff --git a/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/SpTagScreen.java b/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/SpTagScreen.java index d0c05c1..f8698fe 100644 --- a/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/SpTagScreen.java +++ b/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/SpTagScreen.java @@ -58,9 +58,6 @@ public class SpTagScreen extends MainScreen implements TagCreatorScreen { private RichTextField heading = new RichTextField(); - private MenuItem mi_reg = new MenuItem(new StringProvider("Start listening"), 110, 10); - private MenuItem mi_unreg = new MenuItem(new StringProvider("Stop listening"), 110, 10); - private Hashtable _tag_attrs = new Hashtable(); /* @@ -97,14 +94,6 @@ public SpTagScreen() { add(_log); - mi_reg.setCommandContext(_smartTagListener); - mi_reg.setCommand(new Command(new RegisterCommand(this))); - addMenuItem(mi_reg); - - mi_unreg.setCommandContext(_smartTagListener); - mi_unreg.setCommand(new Command(new UnregisterCommand(this))); - addMenuItem(mi_unreg); - _listener_mgr.set_log_screen(this); _listener_mgr.registerListener(_smartTagListener); diff --git a/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/TextTagScreen.java b/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/TextTagScreen.java index ab8c5b9..9c29f6a 100644 --- a/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/TextTagScreen.java +++ b/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/TextTagScreen.java @@ -56,9 +56,6 @@ public class TextTagScreen extends MainScreen implements TagCreatorScreen { private RichTextField heading = new RichTextField(); - private MenuItem mi_reg = new MenuItem(new StringProvider("Start listening"), 110, 10); - private MenuItem mi_unreg = new MenuItem(new StringProvider("Stop listening"), 110, 10); - private Hashtable _tag_attrs = new Hashtable(); /* @@ -94,14 +91,6 @@ public TextTagScreen() { add(_log); - mi_reg.setCommandContext(_smartTagListener); - mi_reg.setCommand(new Command(new RegisterCommand(this))); - addMenuItem(mi_reg); - - mi_unreg.setCommandContext(_smartTagListener); - mi_unreg.setCommand(new Command(new UnregisterCommand(this))); - addMenuItem(mi_unreg); - _listener_mgr.set_log_screen(this); _listener_mgr.registerListener(_smartTagListener); diff --git a/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/UriTagScreen.java b/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/UriTagScreen.java index 96fdcf4..8b761bb 100644 --- a/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/UriTagScreen.java +++ b/NFC/NfcWriteNdefSmartTag/src/nfc/sample/Ndef/Write/ui/UriTagScreen.java @@ -56,9 +56,6 @@ public class UriTagScreen extends MainScreen implements TagCreatorScreen { private RichTextField heading = new RichTextField(); - private MenuItem mi_reg = new MenuItem(new StringProvider("Start listening"), 110, 10); - private MenuItem mi_unreg = new MenuItem(new StringProvider("Stop listening"), 110, 10); - private Hashtable _tag_attrs = new Hashtable(); /* @@ -94,14 +91,6 @@ public UriTagScreen() { add(_log); - mi_reg.setCommandContext(_smartTagListener); - mi_reg.setCommand(new Command(new RegisterCommand(this))); - addMenuItem(mi_reg); - - mi_unreg.setCommandContext(_smartTagListener); - mi_unreg.setCommand(new Command(new UnregisterCommand(this))); - addMenuItem(mi_unreg); - _listener_mgr.set_log_screen(this); _listener_mgr.registerListener(_smartTagListener); diff --git a/NFC/TouchTicTacToe/.classpath b/NFC/TouchTicTacToe/.classpath new file mode 100644 index 0000000..f96974e --- /dev/null +++ b/NFC/TouchTicTacToe/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/NFC/TouchTicTacToe/.project b/NFC/TouchTicTacToe/.project new file mode 100644 index 0000000..c577420 --- /dev/null +++ b/NFC/TouchTicTacToe/.project @@ -0,0 +1,29 @@ + + + TouchTicTacToe + + + + + + net.rim.ejde.internal.builder.BlackBerryPreprocessBuilder + + + + + net.rim.ejde.internal.builder.BlackBerryResourcesBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + + net.rim.ejde.BlackBerryPreProcessNature + net.rim.ejde.BlackBerryProjectCoreNature + org.eclipse.jdt.core.javanature + + diff --git a/NFC/TouchTicTacToe/.settings/net.rim.browser.tools.debug.widget.prefs b/NFC/TouchTicTacToe/.settings/net.rim.browser.tools.debug.widget.prefs new file mode 100644 index 0000000..a7d4465 --- /dev/null +++ b/NFC/TouchTicTacToe/.settings/net.rim.browser.tools.debug.widget.prefs @@ -0,0 +1,3 @@ +#Tue Jul 03 14:17:25 BST 2012 +eclipse.preferences.version=1 +outputfolder=build diff --git a/NFC/TouchTicTacToe/.settings/org.eclipse.jdt.core.prefs b/NFC/TouchTicTacToe/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..60ce41f --- /dev/null +++ b/NFC/TouchTicTacToe/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Tue Jul 03 14:15:38 BST 2012 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore +org.eclipse.jdt.core.compiler.source=1.3 diff --git a/NFC/TouchTicTacToe/BlackBerry_App_Descriptor.xml b/NFC/TouchTicTacToe/BlackBerry_App_Descriptor.xml new file mode 100644 index 0000000..aee5a42 --- /dev/null +++ b/NFC/TouchTicTacToe/BlackBerry_App_Descriptor.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NFC/TouchTicTacToe/README.md b/NFC/TouchTicTacToe/README.md new file mode 100644 index 0000000..677aed3 --- /dev/null +++ b/NFC/TouchTicTacToe/README.md @@ -0,0 +1,44 @@ +# TouchTicTacToe + + +The purpose of this application is to demonstrate "Proximity Gaming". Proximity Gaming is a term coined by Martin Woolley of Research In Motion for the use +of Near Field Communications in multi-player games. See http://devblog.blackberry.com/ for a blog post on this subject. + +The sample code for this application is Open Source under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0.html). + +**Applies To** + +* [BlackBerry Java SDK for Smartphones](http://us.blackberry.com/developers/javaappdev/) + + +**Authors** + +* [Martin Woolley](https://github.com/mdwoolley) +* [John Murray](https://github.com/jcmurray) + + +**Dependencies** + +1. BlackBerry Device Software 7.1 and above. + + +**Known Issues** + +None + +**To contribute code to this repository you must be [signed up as an official contributor](http://blackberry.github.com/howToContribute.html).** + + +## Contributing Changes + +Please see the [README](https://github.com/blackberry/BlackBerry-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples. + + +## Bug Reporting and Feature Requests + +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/BlackBerry-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/BlackBerry-Java/issues). + + +## Disclaimer + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/NFC/TouchTicTacToe/bin/img/blank_clicked_160x120.png b/NFC/TouchTicTacToe/bin/img/blank_clicked_160x120.png new file mode 100644 index 0000000..4010d45 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/blank_clicked_160x120.png differ diff --git a/NFC/TouchTicTacToe/bin/img/blank_clicked_213x160.png b/NFC/TouchTicTacToe/bin/img/blank_clicked_213x160.png new file mode 100644 index 0000000..f0e456d Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/blank_clicked_213x160.png differ diff --git a/NFC/TouchTicTacToe/bin/img/blank_focus_160x120.png b/NFC/TouchTicTacToe/bin/img/blank_focus_160x120.png new file mode 100644 index 0000000..3dcdf37 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/blank_focus_160x120.png differ diff --git a/NFC/TouchTicTacToe/bin/img/blank_focus_213x160.png b/NFC/TouchTicTacToe/bin/img/blank_focus_213x160.png new file mode 100644 index 0000000..b1fd68e Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/blank_focus_213x160.png differ diff --git a/NFC/TouchTicTacToe/bin/img/blank_unfocus_160x120.png b/NFC/TouchTicTacToe/bin/img/blank_unfocus_160x120.png new file mode 100644 index 0000000..cd54e52 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/blank_unfocus_160x120.png differ diff --git a/NFC/TouchTicTacToe/bin/img/blank_unfocus_213x160.png b/NFC/TouchTicTacToe/bin/img/blank_unfocus_213x160.png new file mode 100644 index 0000000..cf49626 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/blank_unfocus_213x160.png differ diff --git a/NFC/TouchTicTacToe/bin/img/board_480x360.png b/NFC/TouchTicTacToe/bin/img/board_480x360.png new file mode 100644 index 0000000..e6d3cfb Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/board_480x360.png differ diff --git a/NFC/TouchTicTacToe/bin/img/board_640x480.png b/NFC/TouchTicTacToe/bin/img/board_640x480.png new file mode 100644 index 0000000..77674ea Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/board_640x480.png differ diff --git a/NFC/TouchTicTacToe/bin/img/cross_clicked_160x120.png b/NFC/TouchTicTacToe/bin/img/cross_clicked_160x120.png new file mode 100644 index 0000000..1208e6d Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/cross_clicked_160x120.png differ diff --git a/NFC/TouchTicTacToe/bin/img/cross_clicked_213x160.png b/NFC/TouchTicTacToe/bin/img/cross_clicked_213x160.png new file mode 100644 index 0000000..ad4e222 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/cross_clicked_213x160.png differ diff --git a/NFC/TouchTicTacToe/bin/img/cross_focus_160x120.png b/NFC/TouchTicTacToe/bin/img/cross_focus_160x120.png new file mode 100644 index 0000000..70d1448 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/cross_focus_160x120.png differ diff --git a/NFC/TouchTicTacToe/bin/img/cross_focus_213x160.png b/NFC/TouchTicTacToe/bin/img/cross_focus_213x160.png new file mode 100644 index 0000000..c2c0770 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/cross_focus_213x160.png differ diff --git a/NFC/TouchTicTacToe/bin/img/cross_unfocus_160x120.png b/NFC/TouchTicTacToe/bin/img/cross_unfocus_160x120.png new file mode 100644 index 0000000..bc8c6e6 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/cross_unfocus_160x120.png differ diff --git a/NFC/TouchTicTacToe/bin/img/cross_unfocus_213x160.png b/NFC/TouchTicTacToe/bin/img/cross_unfocus_213x160.png new file mode 100644 index 0000000..0057973 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/cross_unfocus_213x160.png differ diff --git a/NFC/TouchTicTacToe/bin/img/icon.png b/NFC/TouchTicTacToe/bin/img/icon.png new file mode 100644 index 0000000..193950c Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/icon.png differ diff --git a/NFC/TouchTicTacToe/bin/img/icon2.png b/NFC/TouchTicTacToe/bin/img/icon2.png new file mode 100644 index 0000000..5a10cdd Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/icon2.png differ diff --git a/NFC/TouchTicTacToe/bin/img/icon3.png b/NFC/TouchTicTacToe/bin/img/icon3.png new file mode 100644 index 0000000..07cc1a7 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/icon3.png differ diff --git a/NFC/TouchTicTacToe/bin/img/icon4.png b/NFC/TouchTicTacToe/bin/img/icon4.png new file mode 100644 index 0000000..7eeaab4 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/icon4.png differ diff --git a/NFC/TouchTicTacToe/bin/img/new_game_480x360.png b/NFC/TouchTicTacToe/bin/img/new_game_480x360.png new file mode 100644 index 0000000..a30f906 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/new_game_480x360.png differ diff --git a/NFC/TouchTicTacToe/bin/img/new_game_640x480.png b/NFC/TouchTicTacToe/bin/img/new_game_640x480.png new file mode 100644 index 0000000..8f08ebc Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/new_game_640x480.png differ diff --git a/NFC/TouchTicTacToe/bin/img/nought_clicked_160x120.png b/NFC/TouchTicTacToe/bin/img/nought_clicked_160x120.png new file mode 100644 index 0000000..0691c15 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/nought_clicked_160x120.png differ diff --git a/NFC/TouchTicTacToe/bin/img/nought_clicked_213x160.png b/NFC/TouchTicTacToe/bin/img/nought_clicked_213x160.png new file mode 100644 index 0000000..beaeb7f Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/nought_clicked_213x160.png differ diff --git a/NFC/TouchTicTacToe/bin/img/nought_focus_160x120.png b/NFC/TouchTicTacToe/bin/img/nought_focus_160x120.png new file mode 100644 index 0000000..fb6fb8a Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/nought_focus_160x120.png differ diff --git a/NFC/TouchTicTacToe/bin/img/nought_focus_213x160.png b/NFC/TouchTicTacToe/bin/img/nought_focus_213x160.png new file mode 100644 index 0000000..e030707 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/nought_focus_213x160.png differ diff --git a/NFC/TouchTicTacToe/bin/img/nought_unfocus_160x120.png b/NFC/TouchTicTacToe/bin/img/nought_unfocus_160x120.png new file mode 100644 index 0000000..e978634 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/nought_unfocus_160x120.png differ diff --git a/NFC/TouchTicTacToe/bin/img/nought_unfocus_213x160.png b/NFC/TouchTicTacToe/bin/img/nought_unfocus_213x160.png new file mode 100644 index 0000000..b9d342a Binary files /dev/null and b/NFC/TouchTicTacToe/bin/img/nought_unfocus_213x160.png differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/Constants.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/Constants.class new file mode 100644 index 0000000..72f47c9 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/Constants.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/TouchTicTacToe.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/TouchTicTacToe.class new file mode 100644 index 0000000..92d6500 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/TouchTicTacToe.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/Utilities.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/Utilities.class new file mode 100644 index 0000000..9955d06 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/Utilities.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/commands/AboutCommand.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/commands/AboutCommand.class new file mode 100644 index 0000000..5fa1e2f Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/commands/AboutCommand.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/commands/ChooseCrossCommand.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/commands/ChooseCrossCommand.class new file mode 100644 index 0000000..3f1d0aa Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/commands/ChooseCrossCommand.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/commands/ChooseNoughtCommand.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/commands/ChooseNoughtCommand.class new file mode 100644 index 0000000..409d647 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/commands/ChooseNoughtCommand.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/commands/SelectTileCommand.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/commands/SelectTileCommand.class new file mode 100644 index 0000000..d39f1c2 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/commands/SelectTileCommand.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/game/GameState.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/game/GameState.class new file mode 100644 index 0000000..e323c1e Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/game/GameState.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/game/GameStateChangeListener.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/game/GameStateChangeListener.class new file mode 100644 index 0000000..2244936 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/game/GameStateChangeListener.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/nfc/NfcReceiver.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/nfc/NfcReceiver.class new file mode 100644 index 0000000..b1bf6a5 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/nfc/NfcReceiver.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/nfc/NfcSender.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/nfc/NfcSender.class new file mode 100644 index 0000000..50d6d90 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/nfc/NfcSender.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/nfc/SnepCallBack.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/nfc/SnepCallBack.class new file mode 100644 index 0000000..7d81153 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/nfc/SnepCallBack.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/GameMessageProcessor.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/GameMessageProcessor.class new file mode 100644 index 0000000..908c205 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/GameMessageProcessor.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/GameProtocol.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/GameProtocol.class new file mode 100644 index 0000000..70d9a92 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/GameProtocol.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/ProtocolMessage.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/ProtocolMessage.class new file mode 100644 index 0000000..d35f2a9 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/ProtocolMessage.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/ProtocolMessageMasterBid.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/ProtocolMessageMasterBid.class new file mode 100644 index 0000000..8f4f649 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/ProtocolMessageMasterBid.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/ProtocolMessageResetBidState.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/ProtocolMessageResetBidState.class new file mode 100644 index 0000000..06475d0 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/ProtocolMessageResetBidState.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/ProtocolMessageTurnOver.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/ProtocolMessageTurnOver.class new file mode 100644 index 0000000..956ed27 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/protocol/ProtocolMessageTurnOver.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/tiles/MsbConfig.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/tiles/MsbConfig.class new file mode 100644 index 0000000..b174504 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/tiles/MsbConfig.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/tiles/MsbState.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/tiles/MsbState.class new file mode 100644 index 0000000..7c44b70 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/tiles/MsbState.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/tiles/MultiStateButtonField.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/tiles/MultiStateButtonField.class new file mode 100644 index 0000000..d83a2a7 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/tiles/MultiStateButtonField.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/BitmapFactory.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/BitmapFactory.class new file mode 100644 index 0000000..7023097 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/BitmapFactory.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/GameScreen$1.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/GameScreen$1.class new file mode 100644 index 0000000..318e314 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/GameScreen$1.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/GameScreen$2.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/GameScreen$2.class new file mode 100644 index 0000000..9f9e436 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/GameScreen$2.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/GameScreen$3.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/GameScreen$3.class new file mode 100644 index 0000000..940a88c Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/GameScreen$3.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/GameScreen.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/GameScreen.class new file mode 100644 index 0000000..6c76eed Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/GameScreen.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/StartGameScreen$1.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/StartGameScreen$1.class new file mode 100644 index 0000000..589f4b7 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/StartGameScreen$1.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/StartGameScreen.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/StartGameScreen.class new file mode 100644 index 0000000..bc02ca7 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/StartGameScreen.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/SymbolSelectionScreen$1.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/SymbolSelectionScreen$1.class new file mode 100644 index 0000000..1d5e036 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/SymbolSelectionScreen$1.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/SymbolSelectionScreen.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/SymbolSelectionScreen.class new file mode 100644 index 0000000..ed9a86d Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/SymbolSelectionScreen.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TileChangedListener.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TileChangedListener.class new file mode 100644 index 0000000..4f2d582 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TileChangedListener.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TimedLabelField$1.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TimedLabelField$1.class new file mode 100644 index 0000000..dd8ea49 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TimedLabelField$1.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TimedLabelField$2.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TimedLabelField$2.class new file mode 100644 index 0000000..f32060c Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TimedLabelField$2.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TimedLabelField$3.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TimedLabelField$3.class new file mode 100644 index 0000000..fa520d5 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TimedLabelField$3.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TimedLabelField.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TimedLabelField.class new file mode 100644 index 0000000..416257d Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/TimedLabelField.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/UiConfig.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/UiConfig.class new file mode 100644 index 0000000..58f4fb5 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/UiConfig.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/UiConfig480x360.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/UiConfig480x360.class new file mode 100644 index 0000000..a240fc6 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/UiConfig480x360.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/UiConfig640x480.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/UiConfig640x480.class new file mode 100644 index 0000000..5ff249d Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/UiConfig640x480.class differ diff --git a/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/UiConfigFactory.class b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/UiConfigFactory.class new file mode 100644 index 0000000..29c7e32 Binary files /dev/null and b/NFC/TouchTicTacToe/bin/nfc/sample/tictactoe/ui/UiConfigFactory.class differ diff --git a/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe-1.debug b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe-1.debug new file mode 100644 index 0000000..2c91029 Binary files /dev/null and b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe-1.debug differ diff --git a/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.cod b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.cod new file mode 100644 index 0000000..6c4cf6d Binary files /dev/null and b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.cod differ diff --git a/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.csl b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.csl new file mode 100644 index 0000000..725a93b --- /dev/null +++ b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.csl @@ -0,0 +1 @@ +52525400=RIM Runtime API diff --git a/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.cso b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.cso new file mode 100644 index 0000000..1a589a3 --- /dev/null +++ b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.cso @@ -0,0 +1,5 @@ +33000000=RIMAPPSA2 +52424200=RIM Blackberry Apps API +52434900=RIM Crypto API - Internal +52435200=RIM Crypto API - RIM +4e464352=NFCRoutingAPI diff --git a/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.debug b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.debug new file mode 100644 index 0000000..251e583 Binary files /dev/null and b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.debug differ diff --git a/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.jad b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.jad new file mode 100644 index 0000000..161c5bc --- /dev/null +++ b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.jad @@ -0,0 +1,19 @@ +MIDlet-Name: TouchTicTacToe +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: TouchTicTacToe.jar +MIDlet-Jar-Size: 249747 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: ,img/icon4.png, +RIM-MIDlet-Flags-1: 0 +Manifest-Version: 1.0 +RIM-COD-URL: TouchTicTacToe.cod +RIM-COD-Size: 61656 +RIM-COD-Creation-Time: 1346403036 +RIM-COD-Module-Name: TouchTicTacToe +RIM-COD-Module-Dependencies: net_rim_cldc,net_rim_nfc +RIM-COD-SHA1: ad 04 2d 5a 84 0f b9 5a d0 1e b9 e7 b2 54 e7 dd 2b 39 68 6e +RIM-COD-URL-1: TouchTicTacToe-1.cod +RIM-COD-Size-1: 24700 +RIM-COD-SHA1-1: 2a 2e f4 76 d3 c7 66 42 d5 f1 65 36 68 08 f0 2b a1 2b 97 72 diff --git a/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.jar b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.jar new file mode 100644 index 0000000..cf02cc7 Binary files /dev/null and b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.jar differ diff --git a/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.rapc b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.rapc new file mode 100644 index 0000000..1bd6bee --- /dev/null +++ b/NFC/TouchTicTacToe/deliverables/Standard/7.1.0/TouchTicTacToe.rapc @@ -0,0 +1,10 @@ +MIDlet-Name: TouchTicTacToe +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: TouchTicTacToe.jar +MIDlet-Jar-Size: 0 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: ,img/icon4.png, +RIM-MIDlet-Flags-1: 0 + diff --git a/NFC/TouchTicTacToe/deliverables/Standard/TouchTicTacToe.alx b/NFC/TouchTicTacToe/deliverables/Standard/TouchTicTacToe.alx new file mode 100644 index 0000000..aac12fb --- /dev/null +++ b/NFC/TouchTicTacToe/deliverables/Standard/TouchTicTacToe.alx @@ -0,0 +1,31 @@ + + + + + + + + + + 1.0.0 + + + BlackBerry Developer + + + Copyright (c) 2012 BlackBerry Developer + + + + 7.1.0 + + + TouchTicTacToe.cod + + + + + + + + diff --git a/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe-1.cod b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe-1.cod new file mode 100644 index 0000000..99efa74 Binary files /dev/null and b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe-1.cod differ diff --git a/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe-1.debug b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe-1.debug new file mode 100644 index 0000000..2c91029 Binary files /dev/null and b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe-1.debug differ diff --git a/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.cod b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.cod new file mode 100644 index 0000000..4634aaa Binary files /dev/null and b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.cod differ diff --git a/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.csl b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.csl new file mode 100644 index 0000000..725a93b --- /dev/null +++ b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.csl @@ -0,0 +1 @@ +52525400=RIM Runtime API diff --git a/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.cso b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.cso new file mode 100644 index 0000000..1a589a3 --- /dev/null +++ b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.cso @@ -0,0 +1,5 @@ +33000000=RIMAPPSA2 +52424200=RIM Blackberry Apps API +52434900=RIM Crypto API - Internal +52435200=RIM Crypto API - RIM +4e464352=NFCRoutingAPI diff --git a/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.debug b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.debug new file mode 100644 index 0000000..251e583 Binary files /dev/null and b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.debug differ diff --git a/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.jad b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.jad new file mode 100644 index 0000000..161c5bc --- /dev/null +++ b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.jad @@ -0,0 +1,19 @@ +MIDlet-Name: TouchTicTacToe +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: TouchTicTacToe.jar +MIDlet-Jar-Size: 249747 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: ,img/icon4.png, +RIM-MIDlet-Flags-1: 0 +Manifest-Version: 1.0 +RIM-COD-URL: TouchTicTacToe.cod +RIM-COD-Size: 61656 +RIM-COD-Creation-Time: 1346403036 +RIM-COD-Module-Name: TouchTicTacToe +RIM-COD-Module-Dependencies: net_rim_cldc,net_rim_nfc +RIM-COD-SHA1: ad 04 2d 5a 84 0f b9 5a d0 1e b9 e7 b2 54 e7 dd 2b 39 68 6e +RIM-COD-URL-1: TouchTicTacToe-1.cod +RIM-COD-Size-1: 24700 +RIM-COD-SHA1-1: 2a 2e f4 76 d3 c7 66 42 d5 f1 65 36 68 08 f0 2b a1 2b 97 72 diff --git a/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.jar b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.jar new file mode 100644 index 0000000..cf02cc7 Binary files /dev/null and b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.jar differ diff --git a/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.rapc b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.rapc new file mode 100644 index 0000000..1bd6bee --- /dev/null +++ b/NFC/TouchTicTacToe/deliverables/Web/7.1.0/TouchTicTacToe.rapc @@ -0,0 +1,10 @@ +MIDlet-Name: TouchTicTacToe +MIDlet-Version: 1.0.0 +MIDlet-Vendor: BlackBerry Developer +MIDlet-Jar-URL: TouchTicTacToe.jar +MIDlet-Jar-Size: 0 +MicroEdition-Profile: MIDP-2.0 +MicroEdition-Configuration: CLDC-1.1 +MIDlet-1: ,img/icon4.png, +RIM-MIDlet-Flags-1: 0 + diff --git a/NFC/TouchTicTacToe/res/img/blank_clicked_160x120.png b/NFC/TouchTicTacToe/res/img/blank_clicked_160x120.png new file mode 100644 index 0000000..4010d45 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/blank_clicked_160x120.png differ diff --git a/NFC/TouchTicTacToe/res/img/blank_clicked_213x160.png b/NFC/TouchTicTacToe/res/img/blank_clicked_213x160.png new file mode 100644 index 0000000..f0e456d Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/blank_clicked_213x160.png differ diff --git a/NFC/TouchTicTacToe/res/img/blank_focus_160x120.png b/NFC/TouchTicTacToe/res/img/blank_focus_160x120.png new file mode 100644 index 0000000..3dcdf37 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/blank_focus_160x120.png differ diff --git a/NFC/TouchTicTacToe/res/img/blank_focus_213x160.png b/NFC/TouchTicTacToe/res/img/blank_focus_213x160.png new file mode 100644 index 0000000..b1fd68e Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/blank_focus_213x160.png differ diff --git a/NFC/TouchTicTacToe/res/img/blank_unfocus_160x120.png b/NFC/TouchTicTacToe/res/img/blank_unfocus_160x120.png new file mode 100644 index 0000000..cd54e52 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/blank_unfocus_160x120.png differ diff --git a/NFC/TouchTicTacToe/res/img/blank_unfocus_213x160.png b/NFC/TouchTicTacToe/res/img/blank_unfocus_213x160.png new file mode 100644 index 0000000..cf49626 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/blank_unfocus_213x160.png differ diff --git a/NFC/TouchTicTacToe/res/img/board_480x360.png b/NFC/TouchTicTacToe/res/img/board_480x360.png new file mode 100644 index 0000000..e6d3cfb Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/board_480x360.png differ diff --git a/NFC/TouchTicTacToe/res/img/board_640x480.png b/NFC/TouchTicTacToe/res/img/board_640x480.png new file mode 100644 index 0000000..77674ea Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/board_640x480.png differ diff --git a/NFC/TouchTicTacToe/res/img/cross_clicked_160x120.png b/NFC/TouchTicTacToe/res/img/cross_clicked_160x120.png new file mode 100644 index 0000000..1208e6d Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/cross_clicked_160x120.png differ diff --git a/NFC/TouchTicTacToe/res/img/cross_clicked_213x160.png b/NFC/TouchTicTacToe/res/img/cross_clicked_213x160.png new file mode 100644 index 0000000..ad4e222 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/cross_clicked_213x160.png differ diff --git a/NFC/TouchTicTacToe/res/img/cross_focus_160x120.png b/NFC/TouchTicTacToe/res/img/cross_focus_160x120.png new file mode 100644 index 0000000..70d1448 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/cross_focus_160x120.png differ diff --git a/NFC/TouchTicTacToe/res/img/cross_focus_213x160.png b/NFC/TouchTicTacToe/res/img/cross_focus_213x160.png new file mode 100644 index 0000000..c2c0770 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/cross_focus_213x160.png differ diff --git a/NFC/TouchTicTacToe/res/img/cross_unfocus_160x120.png b/NFC/TouchTicTacToe/res/img/cross_unfocus_160x120.png new file mode 100644 index 0000000..bc8c6e6 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/cross_unfocus_160x120.png differ diff --git a/NFC/TouchTicTacToe/res/img/cross_unfocus_213x160.png b/NFC/TouchTicTacToe/res/img/cross_unfocus_213x160.png new file mode 100644 index 0000000..0057973 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/cross_unfocus_213x160.png differ diff --git a/NFC/TouchTicTacToe/res/img/icon.png b/NFC/TouchTicTacToe/res/img/icon.png new file mode 100644 index 0000000..193950c Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/icon.png differ diff --git a/NFC/TouchTicTacToe/res/img/icon2.png b/NFC/TouchTicTacToe/res/img/icon2.png new file mode 100644 index 0000000..5a10cdd Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/icon2.png differ diff --git a/NFC/TouchTicTacToe/res/img/icon3.png b/NFC/TouchTicTacToe/res/img/icon3.png new file mode 100644 index 0000000..07cc1a7 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/icon3.png differ diff --git a/NFC/TouchTicTacToe/res/img/icon4.png b/NFC/TouchTicTacToe/res/img/icon4.png new file mode 100644 index 0000000..7eeaab4 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/icon4.png differ diff --git a/NFC/TouchTicTacToe/res/img/new_game_480x360.png b/NFC/TouchTicTacToe/res/img/new_game_480x360.png new file mode 100644 index 0000000..a30f906 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/new_game_480x360.png differ diff --git a/NFC/TouchTicTacToe/res/img/new_game_640x480.png b/NFC/TouchTicTacToe/res/img/new_game_640x480.png new file mode 100644 index 0000000..8f08ebc Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/new_game_640x480.png differ diff --git a/NFC/TouchTicTacToe/res/img/nought_clicked_160x120.png b/NFC/TouchTicTacToe/res/img/nought_clicked_160x120.png new file mode 100644 index 0000000..0691c15 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/nought_clicked_160x120.png differ diff --git a/NFC/TouchTicTacToe/res/img/nought_clicked_213x160.png b/NFC/TouchTicTacToe/res/img/nought_clicked_213x160.png new file mode 100644 index 0000000..beaeb7f Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/nought_clicked_213x160.png differ diff --git a/NFC/TouchTicTacToe/res/img/nought_focus_160x120.png b/NFC/TouchTicTacToe/res/img/nought_focus_160x120.png new file mode 100644 index 0000000..fb6fb8a Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/nought_focus_160x120.png differ diff --git a/NFC/TouchTicTacToe/res/img/nought_focus_213x160.png b/NFC/TouchTicTacToe/res/img/nought_focus_213x160.png new file mode 100644 index 0000000..e030707 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/nought_focus_213x160.png differ diff --git a/NFC/TouchTicTacToe/res/img/nought_unfocus_160x120.png b/NFC/TouchTicTacToe/res/img/nought_unfocus_160x120.png new file mode 100644 index 0000000..e978634 Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/nought_unfocus_160x120.png differ diff --git a/NFC/TouchTicTacToe/res/img/nought_unfocus_213x160.png b/NFC/TouchTicTacToe/res/img/nought_unfocus_213x160.png new file mode 100644 index 0000000..b9d342a Binary files /dev/null and b/NFC/TouchTicTacToe/res/img/nought_unfocus_213x160.png differ diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/Constants.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/Constants.java new file mode 100644 index 0000000..ef6352a --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/Constants.java @@ -0,0 +1,55 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe; +import net.rim.device.api.ui.Color; + +public interface Constants { + + public static final String MYAPP_VERSION = "1.0.3"; + public static final String MYAPP_NAME = "Touch Tic Tac Toe"; + + public static final String [] WINNER_MESSAGE = {"YOU HAVE WON!!","Touch devices to start new game"}; + public static final String [] STALE_MATE_MESSAGE = {"Stale mate! No more moves.","Touch devices to start new game"}; + + public static final int BOARD_STATE_OPEN=0; + public static final int BOARD_STATE_LOCKED=1; + public static final int NO_PREV_TURN=-1; + public static final int TILE_STATE_BLANK=0; + public static final int TILE_STATE_NOUGHT=1; + public static final int TILE_STATE_CROSS=2; + public static final int SELECT_STATE_NOUGHT=0; + public static final int SELECT_STATE_CROSS=0; + public static final int STATUS_COLOUR = Color.RED; + public static final int FOCUSED_COLOUR = Color.GOLD; + public static final int CLICKED_COLOUR = Color.RED; + public static final int WIN_LINE_COLOUR = Color.DARKORANGE; + public static final int STALE_MATE_TILE_COLOUR = Color.BLUE; + public static final int TRANSPARENCY = 30; + public static final int PLAYER_1 = 1; + public static final int PLAYER_2 = 2; + public static final int PLAYER_SYMBOL_NOUGHT = 1; + public static final int PLAYER_SYMBOL_CROSS = 2; + public static final long MESSAGE_TIME = 5000; + public static final int INITIAL_TILE = 4; + + // protocol + public static final int PROTOCOL_MASTER_BID=1; + public static final int PROTOCOL_TURN_OVER=2; + public static final int PROTOCOL_RESET_BID_STATE=3; + public static final String SNEP_DOMAIN = "com.blackberry.nfc.sample"; + public static final String SNEP_TYPE = "G1"; // Game #1 + +} \ No newline at end of file diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/TouchTicTacToe.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/TouchTicTacToe.java new file mode 100644 index 0000000..7b80c05 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/TouchTicTacToe.java @@ -0,0 +1,35 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe; + +import net.rim.device.api.ui.UiApplication; +import nfc.sample.tictactoe.ui.StartGameScreen; + +public class TouchTicTacToe extends UiApplication { + + public static void main(String[] args) { + Utilities.initLogging(); + Utilities.log("XXXX "+Constants.MYAPP_NAME+" v"+Constants.MYAPP_VERSION); + TouchTicTacToe app = new TouchTicTacToe(); + app.enterEventDispatcher(); + } + + private TouchTicTacToe() { + StartGameScreen start_screen = new StartGameScreen(); + pushScreen(start_screen); + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/Utilities.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/Utilities.java new file mode 100644 index 0000000..9fbcc25 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/Utilities.java @@ -0,0 +1,62 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe; +import net.rim.device.api.system.EventLogger; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.component.Dialog; + +public class Utilities { + + private static final long MYAPP_ID = 0x4c38c8a7798397d1L; + + public static void log(String logMessage) { + boolean ok = EventLogger.logEvent(MYAPP_ID, logMessage.getBytes(), EventLogger.INFORMATION); + } + + public static void initLogging() { + EventLogger.register(MYAPP_ID, "TouchTicTacToe", EventLogger.VIEWER_STRING); + } + + public static boolean isOdd(int number) { + int remainder = number % 2; + return remainder == 1; + } + + public static byte[] toBytes(int value) { + byte [] bytes = new byte[4]; + bytes [0] = (byte) ((value >>> 24) & 0xFF); + bytes [1] = (byte) ((value >>> 16) & 0xFF); + bytes [2] = (byte) ((value >>> 8) & 0xFF); + bytes [3] = (byte) ( value & 0xFF); + return bytes; + } + + public static int toInt(byte[] bytes, int start) { + if((bytes.length - start) < 3) { + Utilities.log("XXXX toInt method received invalid length start position; insifficient bytes:" + bytes.length + "," + start); + return 0; + } + int i = ((bytes[start] & 0xFF) << 24) + ((bytes[start + 1] & 0xFF) << 16) + ((bytes[start + 2] & 0xFF) << 8) + (bytes[start + 3] & 0xFF); + return i; + } + + public static void popupMessage(String message) { + synchronized(UiApplication.getEventLock()) { + Dialog.inform(message); + } + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/commands/AboutCommand.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/commands/AboutCommand.java new file mode 100644 index 0000000..baf2bc0 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/commands/AboutCommand.java @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.commands; +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.command.ReadOnlyCommandMetadata; +import net.rim.device.api.ui.UiApplication; +import nfc.sample.tictactoe.Constants; +import nfc.sample.tictactoe.Utilities; + +public class AboutCommand extends AlwaysExecutableCommand { + + + public AboutCommand() { + } + + public void execute(ReadOnlyCommandMetadata metadata, Object context) { + + Utilities.log("XXXX AboutCommand - execute"); + + synchronized(UiApplication.getUiApplication().getEventLock()) { + synchronized (UiApplication.getEventLock()) { + Utilities.popupMessage("TouchTicTacToe V"+Constants.MYAPP_VERSION+"\n\n\nMartin Woolley (@mdwrim)\n\nJohn Murray (@jcmrim)"); + } + } + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/commands/ChooseCrossCommand.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/commands/ChooseCrossCommand.java new file mode 100644 index 0000000..15ff656 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/commands/ChooseCrossCommand.java @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.commands; +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.command.ReadOnlyCommandMetadata; +import net.rim.device.api.ui.UiApplication; +import nfc.sample.tictactoe.Constants; +import nfc.sample.tictactoe.Utilities; +import nfc.sample.tictactoe.ui.GameScreen; +import nfc.sample.tictactoe.ui.SymbolSelectionScreen; + +public class ChooseCrossCommand extends AlwaysExecutableCommand { + + + private SymbolSelectionScreen current_screen; + + public ChooseCrossCommand(SymbolSelectionScreen ss_screen) { + current_screen = ss_screen; + } + + public void execute(ReadOnlyCommandMetadata metadata, Object context) { + + Utilities.log("XXXX ChooseCrossCommand - execute"); + + // only ever called by player 1 from the symbol selection screen + GameScreen screen = GameScreen.getInstance(Constants.PLAYER_1,Constants.PLAYER_SYMBOL_CROSS); + + synchronized(UiApplication.getUiApplication().getEventLock()) { + synchronized (UiApplication.getEventLock()) { + UiApplication.getUiApplication().popScreen(current_screen); + UiApplication.getUiApplication().pushScreen(screen); + } + } + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/commands/ChooseNoughtCommand.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/commands/ChooseNoughtCommand.java new file mode 100644 index 0000000..a94bacf --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/commands/ChooseNoughtCommand.java @@ -0,0 +1,48 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.commands; +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.command.ReadOnlyCommandMetadata; +import net.rim.device.api.ui.UiApplication; +import nfc.sample.tictactoe.Constants; +import nfc.sample.tictactoe.Utilities; +import nfc.sample.tictactoe.ui.GameScreen; +import nfc.sample.tictactoe.ui.SymbolSelectionScreen; + +public class ChooseNoughtCommand extends AlwaysExecutableCommand { + + private SymbolSelectionScreen current_screen; + + public ChooseNoughtCommand(SymbolSelectionScreen ss_screen) { + current_screen = ss_screen; + } + + public void execute(ReadOnlyCommandMetadata metadata, Object context) { + + Utilities.log("XXXX ChooseNoughtCommand - execute"); + + // only ever called by player 1 from the symbol selection screen + GameScreen screen = GameScreen.getInstance(Constants.PLAYER_1,Constants.PLAYER_SYMBOL_NOUGHT); + + synchronized(UiApplication.getUiApplication().getEventLock()) { + synchronized (UiApplication.getEventLock()) { + UiApplication.getUiApplication().popScreen(current_screen); + UiApplication.getUiApplication().pushScreen(screen); + } + } + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/commands/SelectTileCommand.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/commands/SelectTileCommand.java new file mode 100644 index 0000000..1032c38 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/commands/SelectTileCommand.java @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.commands; +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.command.ReadOnlyCommandMetadata; +import nfc.sample.tictactoe.game.GameState; +import nfc.sample.tictactoe.tiles.MultiStateButtonField; + +public class SelectTileCommand extends AlwaysExecutableCommand { + + private int _symbol; + + public void execute(ReadOnlyCommandMetadata metadata, Object context) { + GameState game_state = GameState.getInstance(); + if (game_state.isBoardLocked()) { + return; + } + if (context instanceof MultiStateButtonField) { + int current_tile = game_state.getCurrent_tile(); + game_state.updateTileThisPlayer(current_tile,_symbol); + } + } + + public int get_symbol() { + return _symbol; + } + + public void set_symbol(int _symbol) { + this._symbol = _symbol; + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/game/GameState.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/game/GameState.java new file mode 100644 index 0000000..df019c9 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/game/GameState.java @@ -0,0 +1,356 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.game; + +import net.rim.device.api.ui.UiApplication; +import nfc.sample.tictactoe.Constants; +import nfc.sample.tictactoe.Utilities; +import nfc.sample.tictactoe.protocol.ProtocolMessageMasterBid; +import nfc.sample.tictactoe.tiles.MultiStateButtonField; +import nfc.sample.tictactoe.ui.TileChangedListener; + +public class GameState { + + public static final int GAME_STATE_CHANGE_MY_TURN_NOW=1; + public static final int GAME_STATE_CHANGE_THEIR_TURN_NOW=2; + public static final int GAME_STATE_CHANGE_GAME_OVER_WON=3; + public static final int GAME_STATE_CHANGE_GAME_OVER_STALE_MATE=4; + public static final int GAME_STATE_CHANGE_NEW_GAME_STARTED=5; + + private static GameState _game_state; + + private GameStateChangeListener game_state_change_listener; + private int current_game_state; + + private int current_tile = -1; + private MultiStateButtonField[] _tiles; + + private int tile_count_this_turn=0; + + // indicates whether a tile is 0=unoccupied,1=nought,2=cross + private int[] tile_states = new int[9]; + private boolean[] locked = new boolean[9]; + + private boolean board_locked; + + private boolean game_over = false; + private boolean bid_sent = false; + + private ProtocolMessageMasterBid my_bid_sent; + private ProtocolMessageMasterBid other_bid_received; + + // tracks the last tile updated during a turn so if the player changes their mind we can undo this update + private int last_turn; + + private TileChangedListener _listener; + + private GameState() { + last_turn = Constants.NO_PREV_TURN; + } + + public synchronized static GameState getInstance() { + if(_game_state == null) { + _game_state = new GameState(); + } + return _game_state; + } + + public void setGameStateChangeListener(GameStateChangeListener game_state_change_listener) { + this.game_state_change_listener = game_state_change_listener; + } + + public void initialiseGameState() { + for(int i = 0; i < 9; i++) { + tile_states[i] = Constants.TILE_STATE_BLANK; + locked[i] = false; + setUiState(i, Constants.TILE_STATE_BLANK, false); + } + current_tile = Constants.INITIAL_TILE;; + last_turn = Constants.NO_PREV_TURN; + game_over = false; + current_game_state=GAME_STATE_CHANGE_NEW_GAME_STARTED; + if (game_state_change_listener != null) { + game_state_change_listener.onGameStateChange(GAME_STATE_CHANGE_NEW_GAME_STARTED); + } + } + + public void setTileUiObjects(MultiStateButtonField[] tiles) { + _tiles = tiles; + } + + public void setTileChangedListener(TileChangedListener listener) { + _listener = listener; + } + + public void updateTileThisPlayer(int tile, int players_symbol) { + Utilities.log("XXXX updateTileThisPlayer(tile=" + tile + ",symbol=" + players_symbol + ",current tile state=" + tile_states[tile] + ",last_turn=" + last_turn); + boolean tile_set = false; + if(tile_states[tile] == Constants.TILE_STATE_BLANK) { + Utilities.log("XXXX updateTileThisPlayer setting tile to players symbol:" + players_symbol); + tile_states[tile] = players_symbol; + setUiState(tile, players_symbol, true); + tile_count_this_turn++; + Utilities.log("XXXX updateTileThisPlayer tile_count_this_turn=" + tile_count_this_turn); + _listener.tileChanged(tile); + tile_set = true; + if (hasWon(players_symbol)) { + current_game_state=GAME_STATE_CHANGE_GAME_OVER_WON; + game_over = true; + if (game_state_change_listener != null) { + game_state_change_listener.onGameStateChange(GAME_STATE_CHANGE_GAME_OVER_WON); + } + } else { + if (isBoardFull()) { + current_game_state=GAME_STATE_CHANGE_GAME_OVER_STALE_MATE; + game_over = true; + if (game_state_change_listener != null) { + game_state_change_listener.onGameStateChange(GAME_STATE_CHANGE_GAME_OVER_STALE_MATE); + } + } + } + } else { + if(tile_states[tile] == players_symbol && !locked[tile]) { + Utilities.log("XXXX updateTileThisPlayer setting tile to blank square"); + tile_states[tile] = Constants.TILE_STATE_BLANK; + setUiState(tile, Constants.TILE_STATE_BLANK, true); + tile_set = false; + tile_count_this_turn--; + _listener.tileChanged(tile); + Utilities.log("XXXX updateTileThisPlayer tile_count_this_turn=" + tile_count_this_turn); + } else { + Utilities.log("XXXX updateTileThisPlayer ignoring request as tile contains other player's symbol or is locked from previous turn"); + tile_set = false; + } + } + if(tile_set && last_turn != Constants.NO_PREV_TURN && last_turn != tile && !locked[tile]) { + Utilities.log("XXXX updateTileThisPlayer setting last turn's tile [" + last_turn + "] to BLANK"); + tile_states[last_turn] = Constants.TILE_STATE_BLANK; + setUiState(last_turn, Constants.TILE_STATE_BLANK, false); + } + if(tile_set) { + last_turn = tile; + } + } + + public void updateTileOtherPlayer(int tile, int players_symbol) { + Utilities.log("XXXX updateTileOtherPlayer(tile=" + tile + ",symbol=" + players_symbol + ",current tile state=" + tile_states[tile]); + // assume this was a valid move! + Utilities.log("XXXX updateTileOtherPlayer setting tile to players symbol:" + players_symbol); + tile_states[tile] = players_symbol; + locked[tile] = true; + setUiState(tile, players_symbol, true); + last_turn = Constants.NO_PREV_TURN; + current_game_state=GAME_STATE_CHANGE_MY_TURN_NOW; + if (game_state_change_listener != null) { + game_state_change_listener.onGameStateChange(GAME_STATE_CHANGE_MY_TURN_NOW); + } + } + + public void setGameState(int new_state) { + current_game_state = new_state; + if (game_state_change_listener != null) { + game_state_change_listener.onGameStateChange(new_state); + } + } + + private void setUiState(int tile, int symbol, boolean give_focus) { + _tiles[tile].setMsbState(symbol); + synchronized(UiApplication.getEventLock()) { + if(give_focus) { + _tiles[tile].setFocus(); + _tiles[tile].setFocusedImage(); + } else { + _tiles[tile].updateImage(false); + } + } + } + + public int getTileState(int tile) { + return tile_states[tile]; + } + + public void setStartOfTurn() { + last_turn = Constants.NO_PREV_TURN; + } + + public boolean isBoardLocked() { + return board_locked; + } + + public void setBoardLocked(boolean locked) { + board_locked = locked; + } + + public boolean isBoardFull() { + for(int i = 0; i < 9; i++) { + if(tile_states[i] == Constants.TILE_STATE_BLANK) { + return false; + } + } + return true; + } + + public boolean hasWon(int symbol) { + // horizontal lines + if(tile_states[0] == symbol && tile_states[1] == symbol && tile_states[2] == symbol) { + return true; + } + if(tile_states[3] == symbol && tile_states[4] == symbol && tile_states[5] == symbol) { + return true; + } + if(tile_states[6] == symbol && tile_states[7] == symbol && tile_states[8] == symbol) { + return true; + } + + // vertical lines + if(tile_states[0] == symbol && tile_states[3] == symbol && tile_states[6] == symbol) { + return true; + } + if(tile_states[1] == symbol && tile_states[4] == symbol && tile_states[7] == symbol) { + return true; + } + if(tile_states[2] == symbol && tile_states[5] == symbol && tile_states[8] == symbol) { + return true; + } + + // diagonal lines + if(tile_states[0] == symbol && tile_states[4] == symbol && tile_states[8] == symbol) { + return true; + } + + if(tile_states[2] == symbol && tile_states[4] == symbol && tile_states[6] == symbol) { + return true; + } + + return false; + } + + public int[] getWinningLine(int symbol) { + + int[] line = { -1, -1, -1 }; + + // horizontal lines + if(tile_states[0] == symbol && tile_states[1] == symbol && tile_states[2] == symbol) { + line[0] = 0; + line[1] = 1; + line[2] = 2; + } + if(tile_states[3] == symbol && tile_states[4] == symbol && tile_states[5] == symbol) { + line[0] = 3; + line[1] = 4; + line[2] = 5; + } + if(tile_states[6] == symbol && tile_states[7] == symbol && tile_states[8] == symbol) { + line[0] = 6; + line[1] = 7; + line[2] = 8; + } + + // vertical lines + if(tile_states[0] == symbol && tile_states[3] == symbol && tile_states[6] == symbol) { + line[0] = 0; + line[1] = 3; + line[2] = 6; + } + if(tile_states[1] == symbol && tile_states[4] == symbol && tile_states[7] == symbol) { + line[0] = 1; + line[1] = 4; + line[2] = 7; + } + if(tile_states[2] == symbol && tile_states[5] == symbol && tile_states[8] == symbol) { + line[0] = 2; + line[1] = 5; + line[2] = 8; + } + + // diagonal lines + if(tile_states[0] == symbol && tile_states[4] == symbol && tile_states[8] == symbol) { + line[0] = 0; + line[1] = 4; + line[2] = 8; + } + + if(tile_states[2] == symbol && tile_states[4] == symbol && tile_states[6] == symbol) { + line[0] = 2; + line[1] = 4; + line[2] = 6; + } + + return line; + } + + public int getCurrent_tile() { + return current_tile; + } + + public void setCurrent_tile(int current_tile) { + Utilities.log("XXXX GameState.setCurrent_tile:" + current_tile); + this.current_tile = current_tile; + } + + public void lockBoard() { + setBoardLocked(true); + for(int i = 0; i < 9; i++) { + if(tile_states[i] != Constants.TILE_STATE_BLANK) { + locked[i] = true; + } else { + locked[i] = false; + } + } + last_turn = Constants.NO_PREV_TURN; + } + + public boolean isGame_over() { + return game_over; + } + + public void setGame_over(boolean game_over) { + this.game_over = game_over; + } + + public int getTile_count_this_turn() { + return tile_count_this_turn; + } + + public void setTile_count_this_turn(int tile_count_this_turn) { + this.tile_count_this_turn = tile_count_this_turn; + } + + public boolean isBid_sent() { + return bid_sent; + } + + public void setBid_sent(boolean bid_sent) { + this.bid_sent = bid_sent; + } + + public ProtocolMessageMasterBid getMy_bid_sent() { + return my_bid_sent; + } + + public void setMy_bid_sent(ProtocolMessageMasterBid my_bid_sent) { + this.my_bid_sent = my_bid_sent; + } + + public ProtocolMessageMasterBid getOther_bid_received() { + return other_bid_received; + } + + public void setOther_bid_received(ProtocolMessageMasterBid other_bid_received) { + this.other_bid_received = other_bid_received; + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/game/GameStateChangeListener.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/game/GameStateChangeListener.java new file mode 100644 index 0000000..9aabe77 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/game/GameStateChangeListener.java @@ -0,0 +1,21 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.game; + +public interface GameStateChangeListener { + + public void onGameStateChange(int new_game_state); +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/nfc/NfcReceiver.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/nfc/NfcReceiver.java new file mode 100644 index 0000000..89415d2 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/nfc/NfcReceiver.java @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.nfc; + + +import net.rim.device.api.io.nfc.ndef.NDEFMessage; +import net.rim.device.api.io.nfc.ndef.NDEFMessageListener; +import net.rim.device.api.io.nfc.ndef.NDEFRecord; +import net.rim.device.api.util.ByteArrayUtilities; +import nfc.sample.tictactoe.Utilities; +import nfc.sample.tictactoe.protocol.GameMessageProcessor; +import nfc.sample.tictactoe.protocol.ProtocolMessage; + +public class NfcReceiver implements NDEFMessageListener { + + GameMessageProcessor _processor; + + public NfcReceiver(GameMessageProcessor processor) { + _processor = processor; + } + + public void onNDEFMessageDetected(NDEFMessage msg) { + NDEFRecord[] records = msg.getRecords(); + if (records.length > 0) { + byte[] payload = records[0].getPayload(); + Utilities.log("XXXX NfcReceiver payload=" + ByteArrayUtilities.byteArrayToHex(payload)); + ProtocolMessage pmsg = ProtocolMessage.makeMessage(payload); + _processor.gameMessage(pmsg); + } + + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/nfc/NfcSender.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/nfc/NfcSender.java new file mode 100644 index 0000000..7a43386 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/nfc/NfcSender.java @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.nfc; + +import net.rim.device.api.io.nfc.NFCException; +import net.rim.device.api.io.nfc.ndef.NDEFMessage; +import net.rim.device.api.io.nfc.ndef.NDEFMessageUtils; +import net.rim.device.api.io.nfc.push.NDEFMessageBuilder; +import net.rim.device.api.util.ByteArrayUtilities; +import nfc.sample.tictactoe.Constants; +import nfc.sample.tictactoe.Utilities; +import nfc.sample.tictactoe.protocol.ProtocolMessage; + +public class NfcSender implements NDEFMessageBuilder { + + private ProtocolMessage _message; + + public NfcSender(ProtocolMessage message) { + _message = message; + } + + public NDEFMessage[] buildNDEFMessages() { + + Utilities.log("XXXX NfcSender sending ProtocolMessage:" + _message); + + NDEFMessage[] ndef_messages = null; + NDEFMessage game_message; + + try { + + byte[] payload = _message.marshall(); + Utilities.log("XXXX NfcSender sending payload 0x" + ByteArrayUtilities.byteArrayToHex(payload)); + game_message = NDEFMessageUtils.createExternalTypeMessage(Constants.SNEP_DOMAIN, Constants.SNEP_TYPE, payload); + + ndef_messages = new NDEFMessage[] { game_message }; + + } catch(NFCException e) { + Utilities.log("XXXX NfcSender:" + e.getClass().getName() + ":" + e.getMessage()); + } + return ndef_messages; + } + + public ProtocolMessage get_message() { + return _message; + } + + public void set_message(ProtocolMessage _message) { + this._message = _message; + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/nfc/SnepCallBack.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/nfc/SnepCallBack.java new file mode 100644 index 0000000..228e933 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/nfc/SnepCallBack.java @@ -0,0 +1,59 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.nfc; + +import net.rim.device.api.io.nfc.ndef.NDEFMessage; +import net.rim.device.api.io.nfc.push.NDEFPushStatusCallback; +import nfc.sample.tictactoe.Utilities; +import nfc.sample.tictactoe.protocol.GameMessageProcessor; + +public class SnepCallBack implements NDEFPushStatusCallback { + + GameMessageProcessor _processor; + + public SnepCallBack(GameMessageProcessor processor) { + _processor = processor; + } + + public void onNDEFPushStatusUpdate(NDEFMessage message, int status) { + + String status_text; + + switch(status) { + + case NDEFPushStatusCallback.SUCCESS: + status_text = "Ready"; + break; + case NDEFPushStatusCallback.REJECTED: + status_text = "REJECTED"; + break; + case NDEFPushStatusCallback.PUSH_ERROR: + status_text = "PUSH_ERROR"; + break; + case NDEFPushStatusCallback.INVALID_DATA: + status_text = "INVALID_DATA"; + break; + case NDEFPushStatusCallback.DATA_TOO_LARGE: + status_text = "DATA_TOO_LARGE"; + break; + default: + status_text = "UNDEFINED"; + break; + } + Utilities.log("XXXX SNEP message status:"+status_text); + _processor.sentMessagestatusUpdate(message, status, status_text); + } +} \ No newline at end of file diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/GameMessageProcessor.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/GameMessageProcessor.java new file mode 100644 index 0000000..4cde9fb --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/GameMessageProcessor.java @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.protocol; + +import net.rim.device.api.io.nfc.ndef.NDEFMessage; + +public interface GameMessageProcessor { + + public void gameMessage(ProtocolMessage message); + + public void sentMessagestatusUpdate(NDEFMessage ndefMessage, int status, String status_text); + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/GameProtocol.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/GameProtocol.java new file mode 100644 index 0000000..3a5ca04 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/GameProtocol.java @@ -0,0 +1,125 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.protocol; + +import net.rim.device.api.io.nfc.NFCException; +import net.rim.device.api.io.nfc.ndef.NDEFRecord; +import net.rim.device.api.io.nfc.push.NDEFPushManager; +import net.rim.device.api.io.nfc.readerwriter.ReaderWriterManager; +import nfc.sample.tictactoe.Constants; +import nfc.sample.tictactoe.Utilities; +import nfc.sample.tictactoe.nfc.NfcReceiver; +import nfc.sample.tictactoe.nfc.NfcSender; +import nfc.sample.tictactoe.nfc.SnepCallBack; + +public class GameProtocol { + + private GameMessageProcessor game_message_processor; + private ReaderWriterManager nfc_manager; + private NDEFPushManager ndef_push_manager; + private SnepCallBack status_monitor; + private NfcSender sender; + private NfcReceiver receiver; + private int push_id; + private boolean listening = false; + private byte last_message_type_sent; + + public GameProtocol(GameMessageProcessor game_message_processor) throws NFCException { + this.game_message_processor = game_message_processor; + receiver = new NfcReceiver(game_message_processor); + ndef_push_manager = NDEFPushManager.getInstance(); + nfc_manager = ReaderWriterManager.getInstance(); + } + + public void sendMasterBid(ProtocolMessageMasterBid my_bid) throws NFCException { + Utilities.log("XXXX sending master bid:" + my_bid.toString()); + sender = new NfcSender(my_bid); + status_monitor = new SnepCallBack(game_message_processor); + push_id = ndef_push_manager.pushNDEF(sender, status_monitor); + last_message_type_sent = Constants.PROTOCOL_MASTER_BID; + Utilities.log("XXXX push_id=" + push_id); + } + + public void prepareTurnOver(ProtocolMessageTurnOver turn_over) throws NFCException { + Utilities.log("XXXX prepareTurnOver:" + turn_over.toString()); + nfc_manager.removeNDEFMessageListener(NDEFRecord.TNF_EXTERNAL, Constants.SNEP_DOMAIN + ":" + Constants.SNEP_TYPE); + listening = false; + sender = new NfcSender(turn_over); + status_monitor = new SnepCallBack(game_message_processor); + push_id = ndef_push_manager.pushNDEF(sender, status_monitor); + last_message_type_sent = Constants.PROTOCOL_TURN_OVER; + } + + public void resetBidState(ProtocolMessageResetBidState reset) throws NFCException { + Utilities.log("XXXX sending reset bid state message:" + reset.toString()); + sender = new NfcSender(reset); + status_monitor = new SnepCallBack(game_message_processor); + push_id = ndef_push_manager.pushNDEF(sender, status_monitor); + last_message_type_sent = Constants.PROTOCOL_RESET_BID_STATE; + Utilities.log("XXXX push_id=" + push_id); + } + + public void disableMessaging() throws NFCException { + Utilities.log("XXXX disabling NFC messaging"); + nfc_manager.removeNDEFMessageListener(NDEFRecord.TNF_EXTERNAL, Constants.SNEP_DOMAIN + ":" + Constants.SNEP_TYPE); + ndef_push_manager.cancelNDEFPush(push_id); + listening = false; + } + + public void cancelPushRegistration() throws NFCException { + Utilities.log("XXXX canceling push registration"); + ndef_push_manager.cancelNDEFPush(push_id); + } + + public void listenForMessages() { + Utilities.log("XXXX listenForMessages"); + try { + if(!listening) { + nfc_manager.addNDEFMessageListener(receiver, NDEFRecord.TNF_EXTERNAL, Constants.SNEP_DOMAIN + ":" + Constants.SNEP_TYPE); + listening = true; + } + } catch(NFCException e) { + Utilities.log("XXXX listenForMessages:" + e.getClass().getName() + ":" + e.getMessage()); + } + } + + public void stopListeningForMessages() { + Utilities.log("XXXX stopListeningForMessages"); + try { + nfc_manager.removeNDEFMessageListener(NDEFRecord.TNF_EXTERNAL, Constants.SNEP_DOMAIN + ":" + Constants.SNEP_TYPE); + listening = false; + } catch(NFCException e) { + Utilities.log("XXXX stopListeningForMessages:" + e.getClass().getName() + ":" + e.getMessage()); + } + } + + public boolean isListening() { + return listening; + } + + public void setListening(boolean listening) { + this.listening = listening; + } + + public byte getLast_message_type() { + return last_message_type_sent; + } + + public void setLast_message_type(byte last_message_type) { + this.last_message_type_sent = last_message_type; + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/ProtocolMessage.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/ProtocolMessage.java new file mode 100644 index 0000000..7a32dfd --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/ProtocolMessage.java @@ -0,0 +1,61 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.protocol; + +import nfc.sample.tictactoe.Constants; +import nfc.sample.tictactoe.Utilities; + +abstract public class ProtocolMessage { + + byte message_id; + + public static ProtocolMessage makeMessage(byte [] data) { + if(data.length >= 4) { + byte messageid = data[0]; + switch(messageid) { + case Constants.PROTOCOL_MASTER_BID: + ProtocolMessageMasterBid pmsg_mb = new ProtocolMessageMasterBid(); + pmsg_mb.demarshall(data); + Utilities.log("XXXX rcvd:"+pmsg_mb.toString()); + return pmsg_mb; + case Constants.PROTOCOL_TURN_OVER: + ProtocolMessageTurnOver pmsg_to = new ProtocolMessageTurnOver(); + pmsg_to.demarshall(data); + Utilities.log("XXXX rcvd:"+pmsg_to.toString()); + return pmsg_to; + } + } + return null; + + } + + + abstract public byte [] marshall(); + + abstract public void demarshall(byte [] bytes); + + public byte getMessage_id() { + return message_id; + } + public void setMessage_id(byte message_id) { + this.message_id = message_id; + } + + public String toString() { + return "message_id="+message_id; + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/ProtocolMessageMasterBid.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/ProtocolMessageMasterBid.java new file mode 100644 index 0000000..eae742d --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/ProtocolMessageMasterBid.java @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.protocol; + +import java.util.Random; + +import net.rim.device.api.util.ByteArrayUtilities; +import nfc.sample.tictactoe.Constants; +import nfc.sample.tictactoe.Utilities; + +public class ProtocolMessageMasterBid extends ProtocolMessage { + + private int bid; + + public ProtocolMessageMasterBid() { + message_id = Constants.PROTOCOL_MASTER_BID; + Random rand = new Random(System.currentTimeMillis()); + bid = rand.nextInt(1000000); + } + + public byte[] marshall() { + byte [] bid_bytes = Utilities.toBytes(bid); + byte [] bytes = new byte[1+bid_bytes.length]; + bytes [0] = message_id; + System.arraycopy(bid_bytes, 0, bytes, 1, bid_bytes.length); + return bytes; + } + + public void demarshall(byte[] bytes) { + Utilities.log("XXXX demarshalling:"+ByteArrayUtilities.byteArrayToHex(bytes)); + if (bytes.length != 5) { + Utilities.log("XXXX invalid parameter length passed to ProtocolMessageMasterBid demarshall:"+ bytes.length); + return; + } + message_id = bytes[0]; + bid = Utilities.toInt(bytes,1); + } + + public int getBid() { + return bid; + } + + public void setBid(int bid) { + this.bid = bid; + } + + public String toString() { + String string = super.toString() + ",ProtocolMessageMasterBid" + ",bid="+bid; + return string; + } +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/ProtocolMessageResetBidState.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/ProtocolMessageResetBidState.java new file mode 100644 index 0000000..e2dbda5 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/ProtocolMessageResetBidState.java @@ -0,0 +1,47 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.protocol; + +import net.rim.device.api.util.ByteArrayUtilities; +import nfc.sample.tictactoe.Constants; +import nfc.sample.tictactoe.Utilities; + +public class ProtocolMessageResetBidState extends ProtocolMessage { + + public ProtocolMessageResetBidState() { + message_id = Constants.PROTOCOL_RESET_BID_STATE; + } + + public byte[] marshall() { + byte [] bytes = new byte[1]; + bytes [0] = message_id; + return bytes; + } + + public void demarshall(byte[] bytes) { + Utilities.log("XXXX demarshalling:"+ByteArrayUtilities.byteArrayToHex(bytes)); + if (bytes.length != 1) { + Utilities.log("XXXX invalid parameter length passed to ProtocolMessageResetBidState demarshall:"+ bytes.length); + return; + } + message_id = bytes[0]; + } + + public String toString() { + String string = super.toString() + ",ProtocolMessageResetBidState"; + return string; + } +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/ProtocolMessageTurnOver.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/ProtocolMessageTurnOver.java new file mode 100644 index 0000000..7e9696f --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/protocol/ProtocolMessageTurnOver.java @@ -0,0 +1,72 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.protocol; + +import net.rim.device.api.util.ByteArrayUtilities; +import nfc.sample.tictactoe.Constants; +import nfc.sample.tictactoe.Utilities; + +public class ProtocolMessageTurnOver extends ProtocolMessage { + + private int _tile_changed; + private int _symbol_played; + + public ProtocolMessageTurnOver() { + message_id = Constants.PROTOCOL_TURN_OVER; + } + + public byte[] marshall() { + byte [] tile_changed_bytes = Utilities.toBytes(_tile_changed); + byte [] symbol_played_bytes = Utilities.toBytes(_symbol_played); + byte [] bytes = new byte[9]; + bytes [0] = message_id; + System.arraycopy(tile_changed_bytes, 0, bytes, 1, 4); + System.arraycopy(symbol_played_bytes, 0, bytes, 5, 4); + return bytes; + } + + public void demarshall(byte[] bytes) { + Utilities.log("XXXX demarshalling:"+ByteArrayUtilities.byteArrayToHex(bytes)); + if (bytes.length != 9) { + Utilities.log("XXXX invalid parameter length passed to ProtocolTurnOver demarshall:"+ bytes.length); + return; + } + message_id = bytes[0]; + _tile_changed = Utilities.toInt(bytes,1); + _symbol_played = Utilities.toInt(bytes,5); + } + + public String toString() { + String string = super.toString() + ",ProtocolMessageTurnOver" + ",tile_changed="+_tile_changed+",symbol_changed="+_symbol_played; + return string; + } + + public int get_tile_changed() { + return _tile_changed; + } + + public void set_tile_changed(int _tile_changed) { + this._tile_changed = _tile_changed; + } + + public int get_symbol_played() { + return _symbol_played; + } + + public void set_symbol_played(int _symbol_played) { + this._symbol_played = _symbol_played; + } +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/tiles/MsbConfig.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/tiles/MsbConfig.java new file mode 100644 index 0000000..a6177b7 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/tiles/MsbConfig.java @@ -0,0 +1,33 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.tiles; +import java.util.Hashtable; + +public class MsbConfig { + + private Hashtable states = new Hashtable(); + + public void addState(MsbState state) { + Integer key = new Integer(state.getState_id()); + states.put(key,state); + } + + public MsbState getState(int state_id) { + MsbState state = (MsbState) states.get(new Integer(state_id)); + return state; + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/tiles/MsbState.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/tiles/MsbState.java new file mode 100644 index 0000000..3d5ad88 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/tiles/MsbState.java @@ -0,0 +1,103 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.tiles; +import net.rim.device.api.system.Bitmap; + +public class MsbState { + + public static final int DEFAULT_STATE=0; + + private int state_id; // zero is the default state + private String state_description; // e.g. "Service is currently ON" + private String state_label; // for display on buttons e.g. "ON" + + private Bitmap bmp_unfocused; + private Bitmap bmp_focused; + private Bitmap bmp_clicked; + private Bitmap bmp_unclicked; + + public MsbState(int state_id, String state_description, String state_label) { + this.state_id = state_id; + this.state_description = state_description; + this.state_label = state_label; + } + + public boolean equals(Object obj) { + if (obj instanceof MsbState) { + if (((MsbState) obj).getState_id() == this.state_id) { + return true; + } + } + return false; + } + + public int getState_id() { + return state_id; + } + + public void setState_id(int state_id) { + this.state_id = state_id; + } + + public String getState_description() { + return state_description; + } + + public void setState_description(String state_description) { + this.state_description = state_description; + } + + public String getState_label() { + return state_label; + } + + public void setState_label(String state_label) { + this.state_label = state_label; + } + + public Bitmap getbmp_unfocused() { + return bmp_unfocused; + } + + public void setbmp_unfocused(Bitmap bmp_unfocused) { + this.bmp_unfocused = bmp_unfocused; + } + + public Bitmap getbmp_focused() { + return bmp_focused; + } + + public void setbmp_focused(Bitmap bmp_focused) { + this.bmp_focused = bmp_focused; + } + + public Bitmap getbmp_clicked() { + return bmp_clicked; + } + + public void setbmp_clicked(Bitmap bmp_clicked) { + this.bmp_clicked = bmp_clicked; + } + + public Bitmap getbmp_unclicked() { + return bmp_unclicked; + } + + public void setbmp_unclicked(Bitmap bmp_unclicked) { + this.bmp_unclicked = bmp_unclicked; + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/tiles/MultiStateButtonField.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/tiles/MultiStateButtonField.java new file mode 100644 index 0000000..1fe344a --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/tiles/MultiStateButtonField.java @@ -0,0 +1,169 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package nfc.sample.tictactoe.tiles; +import net.rim.device.api.command.AlwaysExecutableCommand; +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.Graphics; +import net.rim.device.api.ui.TouchEvent; +import nfc.sample.tictactoe.Utilities; +import nfc.sample.tictactoe.game.GameState; + +public class MultiStateButtonField extends Field { + + private GameState game_state; + private MsbConfig config; + private int current_state; + private Bitmap current_bitmap; + private AlwaysExecutableCommand command; + + public MultiStateButtonField(MsbConfig config, AlwaysExecutableCommand command, int initial_state, long style) { + super(style); + this.config = config; + this.command = command; + this.current_state = initial_state; + current_bitmap = config.getState(initial_state).getbmp_unfocused(); + game_state = GameState.getInstance(); + } + + protected void paint(Graphics graphics) { + if(current_bitmap != null) { + graphics.drawBitmap(0, 0, current_bitmap.getWidth(), current_bitmap.getHeight(), current_bitmap, 0, 0); + } else { + Utilities.log("XXXX " + config.getState(current_state).getState_label() + "-ERROR:current_bitmap=null"); + } + } + + protected void drawFocus(Graphics graphics, boolean on) { + } + + public void setMsbState(int state_id) { + current_state = state_id; + current_bitmap = config.getState(state_id).getbmp_unfocused(); + } + + public int getMsbState() { + return current_state; + } + + protected boolean navigationClick(int status, int time) { + if(!game_state.isGame_over()) { + setFocus(); + if(config.getState(current_state).getbmp_clicked() != null) { + current_bitmap = config.getState(current_state).getbmp_clicked(); + invalidate(); + } + } + return true; + } + + protected boolean navigationUnclick(int status, int time) { + if(!game_state.isGame_over()) { + if(config.getState(current_state).getbmp_unclicked() != null) { + current_bitmap = config.getState(current_state).getbmp_unclicked(); + invalidate(); + } + // pass button so we can check its state + command.execute(null, this); + } + return true; + } + + protected boolean touchEvent(TouchEvent message) { + if(!game_state.isGame_over()) { + if(message.getY(1) < 0) { + return false; + } + if(message.getY(1) > getHeight()) { + return false; + } + if(message.getX(1) < 0) { + return false; + } + if(message.getX(1) > getWidth()) { + return false; + } + + setFocus(); + if(message.getEvent() == TouchEvent.DOWN && config.getState(current_state).getbmp_clicked() != null) { + current_bitmap = config.getState(current_state).getbmp_clicked(); + invalidate(); + return true; + } + if(message.getEvent() == TouchEvent.UP && config.getState(current_state).getbmp_focused() != null) { + current_bitmap = config.getState(current_state).getbmp_unclicked(); + invalidate(); + // command.execute(null, null); + return true; + } + } + return false; + } + + protected void onFocus(int direction) { + if(!game_state.isGame_over()) { + if(config.getState(current_state).getbmp_focused() != null) { + current_bitmap = config.getState(current_state).getbmp_focused(); + invalidate(); + } + } + } + + protected void onUnfocus() { + if(!game_state.isGame_over()) { + if(config.getState(current_state).getbmp_unfocused() != null) { + current_bitmap = config.getState(current_state).getbmp_unfocused(); + invalidate(); + } + } + } + + public void setFocusedImage() { + current_bitmap = config.getState(current_state).getbmp_focused(); + invalidate(); + } + + public void setImage(Bitmap image) { + current_bitmap = image; + invalidate(); + } + + public void updateImage(boolean focused) { + if(focused) { + current_bitmap = config.getState(current_state).getbmp_focused(); + } else { + current_bitmap = config.getState(current_state).getbmp_unfocused(); + } + invalidate(); + } + + public boolean isFocusable() { + return true; + } + + protected void layout(int width, int height) { + setExtent(current_bitmap.getWidth(), current_bitmap.getHeight()); + } + + public int getPreferredWidth() { + return current_bitmap.getWidth(); + } + + public int getPreferredHeight() { + return current_bitmap.getHeight(); + } +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/BitmapFactory.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/BitmapFactory.java new file mode 100644 index 0000000..75f4873 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/BitmapFactory.java @@ -0,0 +1,87 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.ui; + +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.system.Display; +import net.rim.device.api.ui.Color; +import net.rim.device.api.ui.Graphics; +import nfc.sample.tictactoe.Constants; + +public class BitmapFactory { + + public static Bitmap getBackground(int width, int height) { + Bitmap bg = new Bitmap(width, height); + Graphics pen = Graphics.create(bg); + int x1 = width / 3; + int x2 = x1 * 2; + int y1 = height / 3; + int y2 = y1 * 2; + pen.setColor(Color.BLACK); + pen.drawLine(x1, 0, x1, height); + pen.drawLine(x2, 0, x2, height); + pen.drawLine(0, y1, width, y1); + pen.drawLine(0, y2, width, y2); + return bg; + } + + public static Bitmap getBlankUnfocused() { + int width = Display.getWidth(); + int height = Display.getHeight(); + UiConfig uiconfig = UiConfigFactory.getUiConfig(width,height); + Bitmap blank_unfocused = Bitmap.getBitmapResource(uiconfig.getTileNameBlankUnfocus()); + return blank_unfocused; + } + + public static Bitmap getNoughtUnfocused() { + int width = Display.getWidth(); + int height = Display.getHeight(); + UiConfig uiconfig = UiConfigFactory.getUiConfig(width,height); + Bitmap nought_unfocused = Bitmap.getBitmapResource(uiconfig.getTileNameNoughtUnfocus()); + return nought_unfocused; + } + + public static Bitmap getCrossUnfocused() { + int width = Display.getWidth(); + int height = Display.getHeight(); + UiConfig uiconfig = UiConfigFactory.getUiConfig(width,height); + Bitmap cross_unfocused = Bitmap.getBitmapResource(uiconfig.getTileNameCrossUnfocus()); + return cross_unfocused; + } + + public static Bitmap getNewGameScreen() { + int width = Display.getWidth(); + int height = Display.getHeight(); + UiConfig uiconfig = UiConfigFactory.getUiConfig(width,height); + Bitmap new_game = Bitmap.getBitmapResource(uiconfig.getNewGameScreenName()); + return new_game; + } + + public static Bitmap addStateIndicator(Bitmap unfocused_bmp, int color) { + int width=unfocused_bmp.getWidth(); + int height=unfocused_bmp.getHeight(); + int [] argb = new int[width * height]; + unfocused_bmp.getARGB(argb, 0, width, 0, 0, width, height); + Bitmap new_bmp = new Bitmap(width, height); + new_bmp.setARGB(argb, 0, width, 0, 0, width, height); + Graphics pen = Graphics.create(new_bmp); + pen.setGlobalAlpha(Constants.TRANSPARENCY); + pen.setColor(color); + pen.fillRect(0, 0, width, height); + return new_bmp; + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/GameScreen.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/GameScreen.java new file mode 100644 index 0000000..1932f9a --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/GameScreen.java @@ -0,0 +1,586 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package nfc.sample.tictactoe.ui; +import net.rim.device.api.command.Command; +import net.rim.device.api.io.nfc.NFCException; +import net.rim.device.api.io.nfc.ndef.NDEFMessage; +import net.rim.device.api.io.nfc.push.NDEFPushStatusCallback; +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.system.Display; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.FocusChangeListener; +import net.rim.device.api.ui.Graphics; +import net.rim.device.api.ui.MenuItem; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.container.AbsoluteFieldManager; +import net.rim.device.api.ui.container.MainScreen; +import net.rim.device.api.ui.decor.Background; +import net.rim.device.api.ui.decor.BackgroundFactory; +import net.rim.device.api.util.StringProvider; +import nfc.sample.tictactoe.Constants; +import nfc.sample.tictactoe.Utilities; +import nfc.sample.tictactoe.commands.AboutCommand; +import nfc.sample.tictactoe.commands.SelectTileCommand; +import nfc.sample.tictactoe.game.GameState; +import nfc.sample.tictactoe.game.GameStateChangeListener; +import nfc.sample.tictactoe.protocol.GameMessageProcessor; +import nfc.sample.tictactoe.protocol.GameProtocol; +import nfc.sample.tictactoe.protocol.ProtocolMessage; +import nfc.sample.tictactoe.protocol.ProtocolMessageMasterBid; +import nfc.sample.tictactoe.protocol.ProtocolMessageResetBidState; +import nfc.sample.tictactoe.protocol.ProtocolMessageTurnOver; +import nfc.sample.tictactoe.tiles.MsbConfig; +import nfc.sample.tictactoe.tiles.MsbState; +import nfc.sample.tictactoe.tiles.MultiStateButtonField; + +public class GameScreen extends MainScreen implements GameMessageProcessor, TileChangedListener, GameStateChangeListener { + + private static GameScreen _game_screen; + private GameState game_state; + private TimedLabelField status; + private static int _player_no; + private static int _symbol; + + private GameProtocol proto; + private ProtocolMessageTurnOver turn_over; + private ProtocolMessageMasterBid my_bid; + private ProtocolMessageMasterBid other_bid; + private ProtocolMessageResetBidState reset = new ProtocolMessageResetBidState(); + + private MultiStateButtonField[] tiles = new MultiStateButtonField[9]; + private UiConfig uiconfig; + + private SelectTileCommand cmd_select_tile; + + private int focused_tile = 0; + private int focused_tile_row = 0; + private int focused_tile_col = 0; + + private Bitmap win_line_bmp; + private Bitmap stale_mate_cross_bmp; + private Bitmap stale_mate_nought_bmp; + private Bitmap cross_unfocused; + private Bitmap nought_unfocused; + + private MenuItem mi_about = new MenuItem(new StringProvider("About"), 110, 10); + + public synchronized static GameScreen getInstance(int player_no) { + Utilities.log("XXXX GameScreen.getInstance(" + player_no + "): height=" + Display.getHeight() + ",width=" + Display.getWidth()); + _player_no = player_no; + if(_game_screen == null) { + _game_screen = new GameScreen(); + } + _game_screen.initialiseGame(); + return _game_screen; + } + + public synchronized static GameScreen getInstance(int player_no, int symbol) { + Utilities.log("XXXX GameScreen.getInstance(" + player_no + "," + symbol + "): height=" + Display.getHeight() + ",width=" + Display.getWidth()); + _player_no = player_no; + _symbol = symbol; + if(_game_screen == null) { + _game_screen = new GameScreen(); + } + _game_screen.initialiseGame(); + return _game_screen; + } + + private GameScreen() { + super(USE_ALL_HEIGHT | USE_ALL_WIDTH | FIELD_HCENTER | FIELD_VCENTER | NO_VERTICAL_SCROLL); + int width = Display.getWidth(); + int height = Display.getHeight(); + uiconfig = UiConfigFactory.getUiConfig(width, height); + + mi_about.setCommandContext(this); + mi_about.setCommand(new Command(new AboutCommand())); + addMenuItem(mi_about); + + + Bitmap blank_unfocused = BitmapFactory.getBlankUnfocused(); + Bitmap blank_focused = BitmapFactory.addStateIndicator(blank_unfocused, Constants.FOCUSED_COLOUR); + Bitmap blank_clicked = BitmapFactory.addStateIndicator(blank_unfocused, Constants.CLICKED_COLOUR); + + nought_unfocused = BitmapFactory.getNoughtUnfocused(); + Bitmap nought_focused = BitmapFactory.addStateIndicator(nought_unfocused, Constants.FOCUSED_COLOUR); + Bitmap nought_clicked = BitmapFactory.addStateIndicator(nought_unfocused, Constants.CLICKED_COLOUR); + + cross_unfocused = BitmapFactory.getCrossUnfocused(); + Bitmap cross_focused = BitmapFactory.addStateIndicator(cross_unfocused, Constants.FOCUSED_COLOUR); + Bitmap cross_clicked = BitmapFactory.addStateIndicator(cross_unfocused, Constants.CLICKED_COLOUR); + + stale_mate_cross_bmp = BitmapFactory.addStateIndicator(cross_unfocused, Constants.STALE_MATE_TILE_COLOUR); + stale_mate_nought_bmp = BitmapFactory.addStateIndicator(cross_unfocused, Constants.STALE_MATE_TILE_COLOUR); + + AbsoluteFieldManager abmgr = new AbsoluteFieldManager(); + + cmd_select_tile = new SelectTileCommand(); + + Background board = BackgroundFactory.createBitmapBackground(BitmapFactory.getBackground(width, height)); + abmgr.setBackground(board); + // Each button has 3 states : blank|nought|cross + int i = 0; + for(int r = 0; r < 3; r++) { + for(int c = 0; c < 3; c++) { + MsbConfig tile_btn_config = new MsbConfig(); + MsbState tile_btn_state_blank = new MsbState(Constants.TILE_STATE_BLANK, "Blank Tile", "Blank Tile"); + tile_btn_state_blank.setbmp_focused(blank_focused); + tile_btn_state_blank.setbmp_unfocused(blank_unfocused); + tile_btn_state_blank.setbmp_clicked(blank_clicked); + tile_btn_state_blank.setbmp_unclicked(blank_focused); + tile_btn_config.addState(tile_btn_state_blank); + MsbState tile_btn_state_nought = new MsbState(Constants.TILE_STATE_NOUGHT, "Nought", "Nought"); + tile_btn_state_nought.setbmp_focused(nought_focused); + tile_btn_state_nought.setbmp_unfocused(nought_unfocused); + tile_btn_state_nought.setbmp_clicked(nought_clicked); + tile_btn_state_nought.setbmp_unclicked(nought_focused); + tile_btn_config.addState(tile_btn_state_nought); + MsbState tile_btn_state_cross = new MsbState(Constants.TILE_STATE_CROSS, "Cross", "Cross"); + tile_btn_state_cross.setbmp_focused(cross_focused); + tile_btn_state_cross.setbmp_unfocused(cross_unfocused); + tile_btn_state_cross.setbmp_clicked(cross_clicked); + tile_btn_state_cross.setbmp_unclicked(cross_focused); + tile_btn_config.addState(tile_btn_state_cross); + + MultiStateButtonField msbf_tile = new MultiStateButtonField(tile_btn_config, cmd_select_tile, 0, Field.FIELD_HCENTER); + msbf_tile.setFocusListener(focus_listener); + tiles[i] = msbf_tile; + abmgr.add(msbf_tile, uiconfig.getTileX(i), uiconfig.getTileY(i)); + i++; + } + } + + add(abmgr); + + status = new TimedLabelField(this, "Touch devices to end turn!"); + status.setLabelText("You are player #" + _player_no); + + try { + proto = new GameProtocol(this); + } catch(NFCException e) { + setStatusMessage("Error initialising NFC messaging"); + Utilities.log("XXXX " + e.getClass().getName() + ":" + e.getMessage()); + } + + game_state = GameState.getInstance(); + game_state.setTileUiObjects(tiles); + game_state.setTileChangedListener(this); + game_state.setGameStateChangeListener(this); + + } + + private void initialiseGame() { + turn_over = new ProtocolMessageTurnOver(); + game_state.initialiseGameState(); + + // focus on central tile + focused_tile_row = 1; + focused_tile_col = 1; + + synchronized(UiApplication.getEventLock()) { + tiles[4].setFocus(); + } + game_state.setCurrent_tile(Constants.INITIAL_TILE); + + if(_player_no == Constants.PLAYER_1) { + cmd_select_tile.set_symbol(_symbol); + game_state.setGameState(GameState.GAME_STATE_CHANGE_MY_TURN_NOW); + } else { + game_state.setBoardLocked(true); + proto.listenForMessages(); + } + + } + + private void setStatusMessage(String msg) { + synchronized(UiApplication.getEventLock()) { + status.setLabelText(msg); + } + } + + private void setStatusMessage(String[] msg, boolean continuous) { + synchronized(UiApplication.getEventLock()) { + status.setLabelTexts(msg, continuous); + } + } + + private FocusChangeListener focus_listener = new FocusChangeListener() { + + public void focusChanged(Field field, int eventType) { + for(int i = 0; i < 9; i++) { + if(field == tiles[i] && !game_state.isGame_over()) { + focused_tile = i; + game_state.setCurrent_tile(i); + return; + } + } + } + }; + + protected boolean navigationMovement(int dx, int dy, int status, int time) { + if(!game_state.isGame_over()) { + Utilities.log("XXXX navigationMovement: dx=" + dx + ",dy=" + dy); + + int x_dir = 0; + int y_dir = 0; + + if(dx > 0) { + x_dir = 1; + } + if(dx < 0) { + x_dir = -1; + } + + if(dy > 0) { + y_dir = 1; + } + if(dy < 0) { + y_dir = -1; + } + setFocusedTile(x_dir, y_dir); + return true; + } else { + return false; + } + } + + private void setFocusedTile(int x_dir, int y_dir) { + focused_tile_col = focused_tile_col + x_dir; + focused_tile_row = focused_tile_row + y_dir; + if(focused_tile_col > 2) { + focused_tile_col = 2; + } + if(focused_tile_col < 0) { + focused_tile_col = 0; + } + if(focused_tile_row > 2) { + focused_tile_row = 2; + } + if(focused_tile_row < 0) { + focused_tile_row = 0; + } + focused_tile = focused_tile_row * 3 + focused_tile_col; + tiles[focused_tile].setFocus(); + } + + public void paint(Graphics graphics) { + super.paint(graphics); + if(!status.getText().equals("")) { + graphics.setColor(Constants.STATUS_COLOUR); + graphics.drawText(status.getText(), uiconfig.getStatusX(), uiconfig.getStatusY(), Graphics.HCENTER, Display.getWidth()); + } + } + + public void tileChanged(int tile) { + turn_over.set_tile_changed(tile); + turn_over.set_symbol_played(_symbol); + if(!game_state.isGame_over() && !game_state.isBoardFull()) { + Utilities.log("XXXX tileChanged tile_count_this_turn=" + game_state.getTile_count_this_turn()); + if(game_state.getTile_count_this_turn() == 1) { + // get ready to send the turn over message when players touch devices again + setStatusMessage("Touch devices to pass turn to other player"); + prepTurnOver(); + } else { + if(game_state.getTile_count_this_turn() == 0) { + // tile was unset so switch off messaging + try { + proto.disableMessaging(); + } catch(NFCException e) { + Utilities.log("XXXX " + e.getClass().getName() + ":" + e.getMessage()); + setStatusMessage("Error: please try again"); + } + } + } + } + } + + public void prepTurnOver() { + try { + proto.prepareTurnOver(turn_over); + proto.listenForMessages(); + } catch(NFCException e) { + Utilities.log("XXXX " + e.getClass().getName() + ":" + e.getMessage()); + setStatusMessage("Error: please try again"); + } + } + + public static int get_symbol() { + return _symbol; + } + + public void gameMessage(ProtocolMessage message) { + Utilities.log("XXXX gameMessage:" + message); + // should indicate it's now our turn + if(message instanceof ProtocolMessageTurnOver) { + // OK, it's our turn now! + ProtocolMessageTurnOver pmsg_to = (ProtocolMessageTurnOver) message; + Utilities.log("XXXX gameMessage: ProtocolMessageTurnOver"); + game_state.setBoardLocked(false); + int other_symbol = pmsg_to.get_symbol_played(); + // derive the symbol we're playing with from the one player 1 is using (they got to choose) + if(other_symbol == Constants.PLAYER_SYMBOL_CROSS) { + _symbol = Constants.PLAYER_SYMBOL_NOUGHT; + } else { + _symbol = Constants.PLAYER_SYMBOL_CROSS; + } + cmd_select_tile.set_symbol(_symbol); + int other_player_tile = pmsg_to.get_tile_changed(); + game_state.updateTileOtherPlayer(other_player_tile, other_symbol); + setStatusMessage("It's your turn now!"); + proto.stopListeningForMessages(); + return; + } + if(message instanceof ProtocolMessageMasterBid) { + // from this screen, this means "let's start a new game" + // we may or may not have already sent our bid + + Utilities.log("XXXX gameMessage: ProtocolMessageMasterBid: game_state.isBid_sent()=" + game_state.isBid_sent()); + boolean ok = true; + + other_bid = (ProtocolMessageMasterBid) message; + game_state.setOther_bid_received(other_bid); + // if we've received this message then one way or another it must be game over (maybe the other device has won) + game_state.setGame_over(true); + + if(!game_state.isBid_sent()) { + my_bid = new ProtocolMessageMasterBid(); + try { + proto.sendMasterBid(my_bid); + ok = true; + } catch(NFCException e1) { + ok = false; + Utilities.log("XXXX " + e1.getClass().getName() + ":" + e1.getMessage()); + setStatusMessage("Error - try again"); + } + } + + proto.stopListeningForMessages(); + + if(ok) { + checkBids(); + } + return; + } + if(message instanceof ProtocolMessageResetBidState) { + Utilities.log("XXXX gameMessage: ProtocolMessageResetBidState"); + proto.stopListeningForMessages(); + setStatusMessage("Please touch devices again"); + resetBidStateTracking(); + return; + } + + } + + private void checkBids() { + Utilities.log("XXXX checkBids: game_state.getMy_bid_sent()=" + game_state.getMy_bid_sent() + ",game_state.getOther_bid_received()=" + game_state.getOther_bid_received()); + if(game_state.getMy_bid_sent() == null || game_state.getOther_bid_received() == null) { + return; + } + int device_role = 0; + if(my_bid.getBid() > other_bid.getBid()) { + Utilities.log("XXXX won the bid: player 1"); + device_role = Constants.PLAYER_1; + } else { + if(my_bid.getBid() < other_bid.getBid()) { + Utilities.log("XXXX lost the bid: player 2"); + device_role = Constants.PLAYER_2; + } else { + setStatusMessage("It didn't work, please try again!"); + return; + } + } + + try { + proto.disableMessaging(); + } catch(NFCException e) { + Utilities.log("XXXX GameScreen:" + e.getClass().getName() + ":" + e.getMessage()); + setStatusMessage("It didn't work, try again!"); + return; + } + + resetBidStateTracking(); + + final int player_no = device_role; + final MainScreen next_screen; + + if(player_no == Constants.PLAYER_2) { + next_screen = GameScreen.getInstance(player_no); + } else { + next_screen = new SymbolSelectionScreen(); + } + + final GameScreen this_screen = this; + UiApplication.getUiApplication().invokeLater(new Runnable() { + public void run() { + UiApplication.getUiApplication().popScreen(this_screen); + } + }); + + UiApplication.getUiApplication().invokeLater(new Runnable() { + public void run() { + UiApplication.getUiApplication().pushScreen(next_screen); + } + }); + } + + public void resetBidStateTracking() { + game_state.setBid_sent(false); + game_state.setMy_bid_sent(null); + game_state.setOther_bid_received(null); + } + + public void sentMessagestatusUpdate(NDEFMessage ndefMessage, int status, String status_text) { + Utilities.log("XXXX push status=" + status_text + ",game_over=" + game_state.isGame_over()); + setStatusMessage(status_text); + if(status == NDEFPushStatusCallback.SUCCESS) { + if(proto.getLast_message_type() == Constants.PROTOCOL_TURN_OVER) { + // we've "told" the other device it is now its turn so we switch to listening + Utilities.log("XXXX push status=" + status_text + ",PROTOCOL_TURN_OVER"); + game_state.lockBoard(); + setStatusMessage("Board now locked"); + game_state.setGameState(GameState.GAME_STATE_CHANGE_THEIR_TURN_NOW); + try { + proto.cancelPushRegistration(); + } catch(NFCException e) { + Utilities.log("XXXX exception in cancelPushRegistration:" + e.getClass().getName() + ":" + e.getMessage()); + } + } + if(proto.getLast_message_type() == Constants.PROTOCOL_MASTER_BID) { + Utilities.log("XXXX push status=" + status_text + ",PROTOCOL_MASTER_BID"); + game_state.setMy_bid_sent(my_bid); + game_state.setBid_sent(true); + checkBids(); + try { + proto.cancelPushRegistration(); + } catch(NFCException e) { + Utilities.log("XXXX exception in cancelPushRegistration:" + e.getClass().getName() + ":" + e.getMessage()); + } + } + if(proto.getLast_message_type() == Constants.PROTOCOL_RESET_BID_STATE) { + Utilities.log("XXXX push status=" + status_text + ",PROTOCOL_RESET_BID_STATE"); + // allow user to try again + try { + setStatusMessage("Touch devices again"); + proto.sendMasterBid(my_bid); + } catch(NFCException e) { + Utilities.log("XXXX exception in sendMasterBid:" + e.getClass().getName() + ":" + e.getMessage()); + } + } + } else { + // realistically, any other status is worth retrying (DATA_TOO_LARGE not likely with this application) + if(proto.getLast_message_type() == Constants.PROTOCOL_MASTER_BID || proto.getLast_message_type() == Constants.PROTOCOL_RESET_BID_STATE) { + resetBidStateTracking(); + try { + proto.resetBidState(reset); + setStatusMessage("Failed - Please try again"); + } catch(NFCException e) { + Utilities.log("XXXX exception in resetBidState:" + e.getClass().getName() + ":" + e.getMessage()); + } + } + if(proto.getLast_message_type() == Constants.PROTOCOL_TURN_OVER) { + setStatusMessage("Touch devices again"); + prepTurnOver(); + } + } + } + + public void onGameStateChange(int new_game_state) { + switch(new_game_state) { + case GameState.GAME_STATE_CHANGE_THEIR_TURN_NOW: + Utilities.log("XXXX GAME_STATE_CHANGE_THEIR_TURN_NOW"); + proto.listenForMessages(); + break; + case GameState.GAME_STATE_CHANGE_MY_TURN_NOW: + Utilities.log("XXXX GAME_STATE_CHANGE_MY_TURN_NOW"); + myTurn(); + break; + case GameState.GAME_STATE_CHANGE_GAME_OVER_WON: + Utilities.log("XXXX GAME_STATE_CHANGE_GAME_OVER_WON"); + gameWon(); + break; + case GameState.GAME_STATE_CHANGE_GAME_OVER_STALE_MATE: + Utilities.log("XXXX GAME_STATE_CHANGE_GAME_OVER_STALE_MATE"); + staleMate(); + break; + case GameState.GAME_STATE_CHANGE_NEW_GAME_STARTED: + Utilities.log("XXXX GAME_STATE_CHANGE_NEW_GAME_STARTED"); + break; + } + } + + private void myTurn() { + game_state.setBoardLocked(false); + game_state.setTile_count_this_turn(0); + } + + private void gameWon() { + game_state.lockBoard(); + proto.stopListeningForMessages(); // we may already be listening so remove the NDEF listener in anticipation of adding it + // again shortly + setStatusMessage(Constants.WINNER_MESSAGE, true); + int[] win_line = game_state.getWinningLine(_symbol); + if(_symbol == Constants.PLAYER_SYMBOL_CROSS) { + win_line_bmp = BitmapFactory.addStateIndicator(cross_unfocused, Constants.WIN_LINE_COLOUR); + } else { + win_line_bmp = BitmapFactory.addStateIndicator(nought_unfocused, Constants.WIN_LINE_COLOUR); + } + for(int i = 0; i < 3; i++) { + tiles[win_line[i]].setImage(win_line_bmp); + } + game_state.setGame_over(true); + my_bid = new ProtocolMessageMasterBid(); + try { + proto.sendMasterBid(my_bid); + proto.listenForMessages(); + } catch(NFCException e) { + Utilities.log("XXXX " + e.getClass().getName() + ":" + e.getMessage()); + setStatusMessage("It didn't work, please try again"); + } + + Utilities.popupMessage("You have won!"); + + } + + private void staleMate() { + game_state.lockBoard(); + setStatusMessage(Constants.STALE_MATE_MESSAGE, true); + for(int i = 0; i < 9; i++) { + if (game_state.getTileState(i) == Constants.PLAYER_SYMBOL_CROSS) { + tiles[i].setImage(stale_mate_cross_bmp); + } else { + tiles[i].setImage(stale_mate_nought_bmp); + } + } + game_state.setGame_over(true); + my_bid = new ProtocolMessageMasterBid(); + try { + proto.sendMasterBid(my_bid); + proto.listenForMessages(); + } catch(NFCException e) { + Utilities.log("XXXX " + e.getClass().getName() + ":" + e.getMessage()); + setStatusMessage("It didn't work, please try again"); + } + Utilities.popupMessage("Stale mate!"); + } + + public boolean onClose() { + try { + proto.disableMessaging(); + } catch(NFCException e) { + } + return super.onClose(); + } +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/StartGameScreen.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/StartGameScreen.java new file mode 100644 index 0000000..f402b7d --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/StartGameScreen.java @@ -0,0 +1,143 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package nfc.sample.tictactoe.ui; +import net.rim.device.api.command.Command; +import net.rim.device.api.io.nfc.NFCException; +import net.rim.device.api.io.nfc.ndef.NDEFMessage; +import net.rim.device.api.io.nfc.push.NDEFPushStatusCallback; +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.MenuItem; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.container.AbsoluteFieldManager; +import net.rim.device.api.ui.container.MainScreen; +import net.rim.device.api.ui.decor.Background; +import net.rim.device.api.ui.decor.BackgroundFactory; +import net.rim.device.api.util.StringProvider; +import nfc.sample.tictactoe.Constants; +import nfc.sample.tictactoe.Utilities; +import nfc.sample.tictactoe.commands.AboutCommand; +import nfc.sample.tictactoe.protocol.GameMessageProcessor; +import nfc.sample.tictactoe.protocol.GameProtocol; +import nfc.sample.tictactoe.protocol.ProtocolMessage; +import nfc.sample.tictactoe.protocol.ProtocolMessageMasterBid; + +public class StartGameScreen extends MainScreen implements GameMessageProcessor { + + private GameProtocol proto; + private Bitmap new_game_screen; + private TimedLabelField status_message; + private MenuItem mi_about = new MenuItem(new StringProvider("About"), 110, 10); + + private ProtocolMessageMasterBid my_bid; + + public StartGameScreen() { + super(Field.USE_ALL_HEIGHT | Field.USE_ALL_WIDTH | Field.FIELD_HCENTER | Field.FIELD_VCENTER); + + mi_about.setCommandContext(this); + mi_about.setCommand(new Command(new AboutCommand())); + addMenuItem(mi_about); + + AbsoluteFieldManager abmgr = new AbsoluteFieldManager(); + new_game_screen = BitmapFactory.getNewGameScreen(); + Background bg_new_game = BackgroundFactory.createBitmapBackground(new_game_screen); + abmgr.setBackground(bg_new_game); + status_message = new TimedLabelField(this, ""); + abmgr.add(status_message); + add(abmgr); + } + + public void onUiEngineAttached(boolean attached) { + Utilities.log("XXXX onUiEngineAttached(" + attached + ")"); + if(attached) { + initNewGameMessaging(); + } + } + + public void onExposed() { + Utilities.log("XXXX onExposed()"); + initNewGameMessaging(); + } + + public void initNewGameMessaging() { + try { + // send bid message over SNEP + proto = new GameProtocol(this); + my_bid = new ProtocolMessageMasterBid(); + proto.sendMasterBid(my_bid); + proto.listenForMessages(); + } catch(NFCException e) { + Utilities.log("XXXX StartGameScreen:" + e.getClass().getName() + ":" + e.getMessage()); + Utilities.popupMessage("Error: separate devices and try again!"); + } + } + + public void gameMessage(ProtocolMessage message) { + if(message instanceof ProtocolMessageMasterBid) { + ProtocolMessageMasterBid other_bid = (ProtocolMessageMasterBid) message; + int device_status = 0; + boolean initialised = false; + if(my_bid.getBid() > other_bid.getBid()) { + Utilities.log("XXXX won the bid: player 1"); + device_status = Constants.PLAYER_1; + initialised = true; + } else { + if(my_bid.getBid() < other_bid.getBid()) { + Utilities.log("XXXX lost the bid: player 2"); + device_status = Constants.PLAYER_2; + initialised = true; + } else { + Utilities.popupMessage("It didn't work, try again!"); + } + } + if(initialised) { + try { + proto.disableMessaging(); + } catch(NFCException e) { + Utilities.log("XXXX StartGameScreen:" + e.getClass().getName() + ":" + e.getMessage()); + Utilities.popupMessage("We had a problem, please try again"); + } + final int player_no = device_status; + final MainScreen next_screen; + if(player_no == Constants.PLAYER_2) { + next_screen = GameScreen.getInstance(player_no); + } else { + next_screen = new SymbolSelectionScreen(); + } + UiApplication.getUiApplication().invokeLater(new Runnable() { + public void run() { + UiApplication.getUiApplication().pushScreen(next_screen); + } + }); + } + } + } + + public void sentMessagestatusUpdate(NDEFMessage ndefMessage, int status, String status_text) { + synchronized(UiApplication.getEventLock()) { + status_message.setLabelText(status_text); + } + if(status == NDEFPushStatusCallback.SUCCESS) { + try { + proto.cancelPushRegistration(); + } catch(NFCException e) { + Utilities.log("XXXX exception in cancelPushRegistration:" + e.getClass().getName() + ":" + e.getMessage()); + } + } + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/SymbolSelectionScreen.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/SymbolSelectionScreen.java new file mode 100644 index 0000000..ac20fb1 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/SymbolSelectionScreen.java @@ -0,0 +1,140 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.ui; +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.system.Display; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.FocusChangeListener; +import net.rim.device.api.ui.container.AbsoluteFieldManager; +import net.rim.device.api.ui.container.MainScreen; +import nfc.sample.tictactoe.Constants; +import nfc.sample.tictactoe.Utilities; +import nfc.sample.tictactoe.commands.ChooseCrossCommand; +import nfc.sample.tictactoe.commands.ChooseNoughtCommand; +import nfc.sample.tictactoe.game.GameState; +import nfc.sample.tictactoe.tiles.MsbConfig; +import nfc.sample.tictactoe.tiles.MsbState; +import nfc.sample.tictactoe.tiles.MultiStateButtonField; + +public class SymbolSelectionScreen extends MainScreen { + + MultiStateButtonField msbf_nought; + MultiStateButtonField msbf_cross; + private UiConfig uiconfig; + private int focused_tile = 0; + + public SymbolSelectionScreen() { + super(Field.USE_ALL_HEIGHT | Field.USE_ALL_WIDTH); + + GameState game_state = GameState.getInstance(); + game_state.setGame_over(false); + + uiconfig = UiConfigFactory.getUiConfig(Display.getWidth(), Display.getHeight()); + Bitmap nought_unfocused = BitmapFactory.getNoughtUnfocused(); + Bitmap nought_focused = BitmapFactory.addStateIndicator(nought_unfocused, Constants.FOCUSED_COLOUR); + Bitmap nought_clicked = BitmapFactory.addStateIndicator(nought_unfocused, Constants.CLICKED_COLOUR); + + Bitmap cross_unfocused = BitmapFactory.getCrossUnfocused(); + Bitmap cross_focused = BitmapFactory.addStateIndicator(cross_unfocused, Constants.FOCUSED_COLOUR); + Bitmap cross_clicked = BitmapFactory.addStateIndicator(cross_unfocused, Constants.CLICKED_COLOUR); + + MsbConfig nought_btn_config = new MsbConfig(); + MsbState btn_state_nought = new MsbState(Constants.SELECT_STATE_NOUGHT, "", ""); + btn_state_nought.setbmp_focused(nought_focused); + btn_state_nought.setbmp_unfocused(nought_unfocused); + btn_state_nought.setbmp_clicked(nought_clicked); + btn_state_nought.setbmp_unclicked(nought_focused); + nought_btn_config.addState(btn_state_nought); + + msbf_nought = new MultiStateButtonField(nought_btn_config, new ChooseNoughtCommand(this), 0, Field.FIELD_HCENTER); + msbf_nought.setFocusListener(focus_listener); + + MsbConfig cross_btn_config = new MsbConfig(); + MsbState tile_btn_state_cross = new MsbState(Constants.SELECT_STATE_CROSS, "", ""); + tile_btn_state_cross.setbmp_focused(cross_focused); + tile_btn_state_cross.setbmp_unfocused(cross_unfocused); + tile_btn_state_cross.setbmp_clicked(cross_clicked); + tile_btn_state_cross.setbmp_unclicked(cross_focused); + cross_btn_config.addState(tile_btn_state_cross); + + msbf_cross = new MultiStateButtonField(cross_btn_config, new ChooseCrossCommand(this), 0, Field.FIELD_HCENTER); + msbf_cross.setFocusListener(focus_listener); + + // we know icons are all the same dimensions and we can fit three across the screen + int icon_width=nought_focused.getWidth(); + int icon_height=nought_focused.getHeight(); + // spacer width must be 1/3 the width of an icon for even spacing + int width_spacer = icon_width / 3; + + int icon_x = width_spacer; + AbsoluteFieldManager mgr = new AbsoluteFieldManager(); + mgr.add(msbf_nought,icon_x,icon_height); + icon_x = icon_x + icon_width + width_spacer; + mgr.add(msbf_cross,icon_x,icon_height); + add(mgr); + } + + private FocusChangeListener focus_listener = new FocusChangeListener() { + + public void focusChanged(Field field, int eventType) { + if(field == msbf_nought) { + focused_tile = 0; + } else { + focused_tile = 1; + } + } + }; + + protected boolean navigationMovement(int dx, int dy, int status, int time) { + + Utilities.log("XXXX navigationMovement: dx=" + dx + ",dy=" + dy); + + int x_dir = 0; + + if(dx > 0) { + x_dir = 1; + } + if(dx < 0) { + x_dir = -1; + } + + setFocusedTile(x_dir); + return true; + } + + private void setFocusedTile(int x_dir) { + Utilities.log("XXX setFocusedTile x_dir=" + x_dir); + if (x_dir == 1) { + if (focused_tile == 0) { + focused_tile = 1; + } + } else { + if (x_dir == -1) { + if (focused_tile == 1) { + focused_tile = 0; + } + } + } + Utilities.log("XXX setFocusedTile focused_tile=" + focused_tile); + if (focused_tile == 0) { + msbf_nought.setFocus(); + } else { + msbf_cross.setFocus(); + } + } + + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/TileChangedListener.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/TileChangedListener.java new file mode 100644 index 0000000..0b3222d --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/TileChangedListener.java @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.ui; + +public interface TileChangedListener { + public void tileChanged(int tile); +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/TimedLabelField.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/TimedLabelField.java new file mode 100644 index 0000000..edf4ec4 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/TimedLabelField.java @@ -0,0 +1,102 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.ui; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.Manager; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.component.LabelField; +import nfc.sample.tictactoe.Constants; + +public class TimedLabelField extends LabelField implements Runnable { + + private String[] messages = new String[0]; + private Manager _container; + private boolean continuous = false; + + public TimedLabelField(Manager container, String[] values) { + super(values[0]); + messages = values; + _container = container; + continuous = false; + } + + public TimedLabelField(Manager container, String value) { + super(value, Field.FIELD_HCENTER); + messages = new String[1]; + messages[0] = value; + _container = container; + continuous = false; + } + + public void run() { + do { + for(int i = 0; i < messages.length; i++) { + // synchronized(UiApplication.getEventLock()) { + final int text_inx = i; + UiApplication.getUiApplication().invokeLater(new Runnable() { + public void run() { + setText(messages[text_inx]); + } + }); + + refresh(); + + try { + Thread.sleep(Constants.MESSAGE_TIME); + // synchronized(UiApplication.getEventLock()) { + UiApplication.getUiApplication().invokeLater(new Runnable() { + public void run() { + setText(""); + } + }); + refresh(); + } catch(final InterruptedException e) { + // synchronized(UiApplication.getEventLock()) { + UiApplication.getUiApplication().invokeLater(new Runnable() { + public void run() { + setText(e.getClass().getName() + ":" + e.getMessage()); + } + }); + } + } + } while(continuous); + } + + public void setLabelText(String text) { + continuous = false; + messages = new String[1]; + messages[0] = text; + Thread t = new Thread(this); + t.start(); + } + + public void setLabelTexts(String[] texts, boolean continuous) { + this.continuous = continuous; + messages = texts; + Thread t = new Thread(this); + t.start(); + } + + private void refresh() { + if(_container != null) { + _container.invalidate(); + } + } + + public void setContinuous(boolean continuous) { + this.continuous = continuous; + } +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/UiConfig.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/UiConfig.java new file mode 100644 index 0000000..5c3ccf8 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/UiConfig.java @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package nfc.sample.tictactoe.ui; + +abstract public class UiConfig { + + abstract public int getScreenHeight(); + abstract public int getScreenWidth(); + abstract public String getBackgroundName(); + abstract public String getTileNameBlankFocus(); + abstract public String getTileNameBlankUnfocus(); + abstract public String getTileNameBlankClicked(); + abstract public String getTileNameNoughtFocus(); + abstract public String getTileNameNoughtUnfocus(); + abstract public String getTileNameNoughtClicked(); + abstract public String getTileNameCrossFocus(); + abstract public String getTileNameCrossUnfocus(); + abstract public String getTileNameCrossClicked(); + abstract public String getNewGameScreenName(); + abstract public int getTileX(int tile_no); + abstract public int getTileY(int tile_no); + abstract public int getStatusX(); + abstract public int getStatusY(); +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/UiConfig480x360.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/UiConfig480x360.java new file mode 100644 index 0000000..6f23f53 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/UiConfig480x360.java @@ -0,0 +1,94 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.ui; + +public class UiConfig480x360 extends UiConfig { + + private int [] tile_x = {1, 161, 321, 1, 161, 321, 1, 161, 321}; + private int [] tile_y = {1, 1, 1, 121, 121, 121, 241, 241, 241}; + private int statusX = 0; + private int statusY = 320; + + + public int getScreenHeight() { + return 360; + } + + public int getScreenWidth() { + return 480; + } + + public String getBackgroundName() { + return "board_480x360.png"; + } + + public String getTileNameBlankFocus() { + return "blank_focus_160x120.png"; + } + + public String getTileNameBlankUnfocus() { + return "blank_unfocus_160x120.png"; + } + + public String getTileNameBlankClicked() { + return "blank_clicked_160x120.png"; + } + + public String getTileNameNoughtFocus() { + return "nought_focus_160x120.png"; + } + + public String getTileNameNoughtUnfocus() { + return "nought_unfocus_160x120.png"; + } + + public String getTileNameNoughtClicked() { + return "nought_clicked_160x120.png"; + } + + public String getTileNameCrossFocus() { + return "cross_focus_160x120.png"; + } + + public String getTileNameCrossUnfocus() { + return "cross_unfocus_160x120.png"; + } + + public String getTileNameCrossClicked() { + return "cross_clicked_160x120.png"; + } + + public String getNewGameScreenName() { + return "new_game_480x360.png"; + } + + public int getTileX(int tile_no) { + return tile_x[tile_no]; + } + + public int getTileY(int tile_no) { + return tile_y[tile_no]; + } + + public int getStatusX() { + return statusX; + } + + public int getStatusY() { + return statusY; + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/UiConfig640x480.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/UiConfig640x480.java new file mode 100644 index 0000000..63ec52e --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/UiConfig640x480.java @@ -0,0 +1,93 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.ui; + +public class UiConfig640x480 extends UiConfig { + + private int [] tile_x = {1, 215, 428, 1, 215, 428, 1, 215, 428}; + private int [] tile_y = {1, 1, 1, 162, 162, 162, 322, 322, 322}; + private int statusX = 0; + private int statusY = 440; + + public int getScreenHeight() { + return 360; + } + + public int getScreenWidth() { + return 480; + } + + public String getBackgroundName() { + return "board_640x480.png"; + } + + public String getTileNameBlankFocus() { + return "blank_focus_213x160.png"; + } + + public String getTileNameBlankUnfocus() { + return "blank_unfocus_213x160.png"; + } + + public String getTileNameBlankClicked() { + return "blank_clicked_213x160.png"; + } + + public String getTileNameNoughtFocus() { + return "nought_focus_213x160.png"; + } + + public String getTileNameNoughtUnfocus() { + return "nought_unfocus_213x160.png"; + } + + public String getTileNameNoughtClicked() { + return "nought_clicked_213x160.png"; + } + + public String getTileNameCrossFocus() { + return "cross_focus_213x160.png"; + } + + public String getTileNameCrossUnfocus() { + return "cross_unfocus_213x160.png"; + } + + public String getTileNameCrossClicked() { + return "cross_clicked_213x160.png"; + } + + public String getNewGameScreenName() { + return "new_game_640x480.png"; + } + + public int getTileX(int tile_no) { + return tile_x[tile_no]; + } + + public int getTileY(int tile_no) { + return tile_y[tile_no]; + } + + public int getStatusX() { + return statusX; + } + + public int getStatusY() { + return statusY; + } + +} diff --git a/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/UiConfigFactory.java b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/UiConfigFactory.java new file mode 100644 index 0000000..3c014f1 --- /dev/null +++ b/NFC/TouchTicTacToe/src/nfc/sample/tictactoe/ui/UiConfigFactory.java @@ -0,0 +1,32 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package nfc.sample.tictactoe.ui; + +public class UiConfigFactory { + + public static UiConfig getUiConfig(int width, int height) { + if(width == 480 && height == 360) { + return new UiConfig480x360(); + } else { + if(width == 640 && height == 480) { + return new UiConfig640x480(); + } else { + // default + return new UiConfig480x360(); + } + } + } +} diff --git a/README.md b/README.md index f947077..d6c0a03 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ The README for the Sample should be updated to indicate the new Author. ## Bug Reporting and Feature Requests -If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-for-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/Samples-for-Java/issues). +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-for-Java/issues) for the Sample. ## Disclaimer diff --git a/Simple Location API/README.md b/Simple Location API/README.md index 0239198..ac8aa34 100644 --- a/Simple Location API/README.md +++ b/Simple Location API/README.md @@ -15,7 +15,7 @@ The sample code for this application is Open Source under the [Apache 2.0 Licens **Author(s)** -* [Tim Windsor](https://github.com/timwindsor) +* [Shadid Haque](https://github.com/shaque) **Dependencies** @@ -34,7 +34,7 @@ Please see the [README](https://github.com/blackberry/Samples-for-Java) of the S ## Bug Reporting and Feature Requests -If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-for-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/Samples-for-Java/issues). +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-for-Java/issues) for the Sample. ## Disclaimer diff --git a/SocialApp/BlackBerry_App_Descriptor.xml b/SocialApp/BlackBerry_App_Descriptor.xml new file mode 100644 index 0000000..b10c4fa --- /dev/null +++ b/SocialApp/BlackBerry_App_Descriptor.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SocialApp/README.md b/SocialApp/README.md new file mode 100644 index 0000000..fee75f7 --- /dev/null +++ b/SocialApp/README.md @@ -0,0 +1,38 @@ +# The Social App + +SocialApp is a sample that demonstrates how BlackBerry Java Apps can integrate with native social apps such as Facebook, Twitter etc. + +The sample code for this application is Open Source under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0.html). + +**Applies To** + +* [BlackBerry Java SDK for Smartphones](http://us.blackberry.com/developers/javaappdev/) + + +**Author(s)** + +* [Shadid Haque](https://github.com/shaque) + + +**Dependencies** + +1. BlackBerry Java SDK 7.0.0 or higher required. +2. Application Icon (License: Free for commercial use) courtesy of (http://www.graphicrating.com/) + + +**To contribute code to this repository you must be [signed up as an official contributor](http://blackberry.github.com/howToContribute.html).** + + +## Contributing Changes + +Please see the [README](https://github.com/blackberry/Samples-for-Java) of the Samples-for-Java repository for instructions on how to add new Samples or make modifications to existing Samples. + + +## Bug Reporting and Feature Requests + +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-for-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/Samples-for-Java/issues). + + +## Disclaimer + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/SocialApp/res/border.png b/SocialApp/res/border.png new file mode 100644 index 0000000..c750570 Binary files /dev/null and b/SocialApp/res/border.png differ diff --git a/SocialApp/res/icon.png b/SocialApp/res/icon.png new file mode 100644 index 0000000..764c459 Binary files /dev/null and b/SocialApp/res/icon.png differ diff --git a/SocialApp/src/mypackage/SendDialog.java b/SocialApp/src/mypackage/SendDialog.java new file mode 100644 index 0000000..ae6d02d --- /dev/null +++ b/SocialApp/src/mypackage/SendDialog.java @@ -0,0 +1,36 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package mypackage; + +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.ui.Color; +import net.rim.device.api.ui.XYEdges; +import net.rim.device.api.ui.component.Dialog; +import net.rim.device.api.ui.decor.BackgroundFactory; +import net.rim.device.api.ui.decor.BorderFactory; + +public class SendDialog extends Dialog{ + public SendDialog(int type, String message, int defaultChoice, Bitmap bitmap){ + super(type, message, defaultChoice, bitmap, Dialog.NO_HORIZONTAL_SCROLL); + setBackground(BackgroundFactory.createSolidTransparentBackground(Color.BLACK, 200)); + setBorder(BorderFactory.createBitmapBorder(new XYEdges(9, 9, 9, 9), Bitmap.getBitmapResource("border.png"))); + } + + public static void inform(int type, String message, int defaultChoice, Bitmap bitmap){ + new SendDialog(type, message, defaultChoice, bitmap).show(); + } +} diff --git a/SocialApp/src/mypackage/SocialApp.java b/SocialApp/src/mypackage/SocialApp.java new file mode 100644 index 0000000..7b4ff4f --- /dev/null +++ b/SocialApp/src/mypackage/SocialApp.java @@ -0,0 +1,48 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package mypackage; + +import net.rim.device.api.ui.UiApplication; + +/** + * This class extends the UiApplication class, providing a + * graphical user interface. + */ +public class SocialApp extends UiApplication +{ + /** + * Entry point for application + * @param args Command line arguments (not used) + */ + public static void main(String[] args) + { + // Create a new instance of the application and make the currently + // running thread the application's event dispatch thread. + SocialApp theApp = new SocialApp(); + theApp.enterEventDispatcher(); + } + + + /** + * Creates a new SocialApp object + */ + public SocialApp() + { + // Push a screen onto the UI stack for rendering. + pushScreen(new SocialScreen()); + } +} diff --git a/SocialApp/src/mypackage/SocialScreen.java b/SocialApp/src/mypackage/SocialScreen.java new file mode 100644 index 0000000..0a7d6a5 --- /dev/null +++ b/SocialApp/src/mypackage/SocialScreen.java @@ -0,0 +1,218 @@ +/* +* Copyright (c) 2012 Research In Motion Limited. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package mypackage; + +import net.rim.blackberry.api.sendmenu.SendCommand; +import net.rim.blackberry.api.sendmenu.SendCommandContextKeys; +import net.rim.blackberry.api.sendmenu.SendCommandException; +import net.rim.blackberry.api.sendmenu.SendCommandRepository; +import net.rim.device.api.system.Bitmap; +import net.rim.device.api.system.Display; +import net.rim.device.api.ui.DrawStyle; +import net.rim.device.api.ui.Field; +import net.rim.device.api.ui.UiApplication; +import net.rim.device.api.ui.XYEdges; +import net.rim.device.api.ui.component.ButtonField; +import net.rim.device.api.ui.component.Dialog; +import net.rim.device.api.ui.component.EditField; +import net.rim.device.api.ui.component.LabelField; +import net.rim.device.api.ui.component.SeparatorField; +import net.rim.device.api.ui.container.MainScreen; +import net.rim.device.api.ui.decor.BorderFactory; +import net.rim.device.api.ui.picker.FilePicker; + +import org.json.me.JSONException; +import org.json.me.JSONObject; + +/** + * A class extending the MainScreen class, which provides default standard + * behavior for BlackBerry GUI applications. + */ +public final class SocialScreen extends MainScreen { + /** Figured out by experimentation with SendCommand.getId(). */ + private final String TWITTER_TEXT_ID = "Twitter_text"; + private final String TWITTER_PATH_ID = "Twitter_path"; + private final String FACEBOOK_TEXT_ID = "Facebook_text"; + private final String FACEBOOK_PATH_ID = "Facebook_path"; + + private ButtonField shareTextButton; + private EditField textField; + private ButtonField filePickButton; + private SendCommand[] commandsAll; + private SendCommand[] commands; + + /** + * Creates a new MyScreen object + */ + public SocialScreen() { + setBorder(BorderFactory.createBitmapBorder(new XYEdges(9, 9, 9, 9), Bitmap.getBitmapResource("border.png"))); + setTitle(new LabelField("(: The Social App :)", DrawStyle.HCENTER|Field.FIELD_HCENTER)); + + filePickButton = new ButtonField("Photo Share", Field.FIELD_HCENTER) { + protected boolean navigationClick(int status, int time) { + FilePicker picker = FilePicker.getInstance(); + picker.setFilter(".jpg:.png"); + picker.setView(FilePicker.VIEW_PICTURES); + String path = picker.show(); + + if (path != null) { + // Creating the data context as a JSONObject + JSONObject context = new JSONObject(); + try { + context.put(SendCommandContextKeys.PATH, path); + /** + * Since we are sharing a file path, you CANNOT add a + * SUBJECT or TEXT type data. Only PATH seems to be + * allowed. + */ + } catch (JSONException e) { + + } + + /** + * Getting the available SendCommand(s) for our SendCommand + * type TYPE_TEXT by providing our data context. The 3rd + * parameter is a boolean that indicates whether you want + * all results or just the results that are possible based on the context. + * Ideally this boolean param would be set to false, + * but there seems to be a bug with BBM as it throws an + * exception during the query. As a workaround, I am getting + * all first and then filtering out the ones I dont need. + */ + commandsAll = SendCommandRepository.getInstance().get(SendCommand.TYPE_PATH, context, true); + commands = new SendCommand[2]; + + for (int i = 0; i < commandsAll.length; i++) { + if (commandsAll[i].getId().equals(TWITTER_PATH_ID)) { + commands[0] = commandsAll[i]; + } + if (commandsAll[i].getId().equals(FACEBOOK_PATH_ID)) { + commands[1] = commandsAll[i]; + } + } + // Displays our SendCommands to the user. + displayCommands(); + } + + return true; + } + + public int getPreferredWidth() { + return Display.getWidth()/2; + } + }; + + add(filePickButton); + + add(new SeparatorField()); + add(new SeparatorField()); + add(new SeparatorField()); + + // An EditField to let the user type in the text to share. + textField = new EditField("", "Share this please."); + textField.setBorder(BorderFactory.createRoundedBorder(new XYEdges(3, 3, 3, 3))); + + // A button that initiates the Text Share + shareTextButton = new ButtonField("Text Share", Field.FIELD_HCENTER) { + protected boolean navigationClick(int arg0, int arg1) { + // Creating the data context as a JSONObject + JSONObject context = new JSONObject(); + try { + context.put(SendCommandContextKeys.TEXT, textField.getText()); + /** + * For text sharing, you can also add a subject as follows. This is useful for sharing via email. + * context.put(SendCommandContextKeys.SUBJECT, "your subject"); + */ + } catch (JSONException e) { + + } + + commandsAll = SendCommandRepository.getInstance().get(SendCommand.TYPE_TEXT, context, true); + commands = new SendCommand[2]; + + for (int i = 0; i < commandsAll.length; i++) { + if (commandsAll[i].getId().equals(TWITTER_TEXT_ID)) { + commands[0] = commandsAll[i]; + } + if (commandsAll[i].getId().equals(FACEBOOK_TEXT_ID)) { + commands[1] = commandsAll[i]; + } + } + // Displays our SendCommands to the user. + displayCommands(); + + return true; + } + + public int getPreferredWidth() { + return Display.getWidth()/2; + } + }; + + add(textField); + add(shareTextButton); + + } + + /** + * Displays our SendCommands to the user. Note that you can also use the + * prebuilt SendCommandScreen or SendCommandMenu to show the SendCommands. + * But I wanted to demo how you can add the SendCommands in a Screen that + * you own. + * + */ + private void displayCommands() { + SendDialog dialog = new SendDialog(Dialog.D_OK, "Lets be social!", Dialog.OK, null); + + if(commands[0]!=null){ + dialog.add(new ButtonField("Twitter") { + protected boolean navigationClick(int status, int time) { + try { + commands[0].run(); + } catch (SendCommandException e) { + SendDialog.inform(Dialog.D_OK, e.toString(), Dialog.OK, null); + } + UiApplication.getUiApplication().popScreen(getScreen()); + return true; + } + + public int getPreferredWidth() { + return Display.getWidth(); + } + }); + } + + if(commands[1]!=null){ + dialog.add(new ButtonField("Facebook") { + protected boolean navigationClick(int status, int time) { + try { + commands[1].run(); + } catch (SendCommandException e) { + SendDialog.inform(Dialog.D_OK, e.toString(), Dialog.OK, null); + } + UiApplication.getUiApplication().popScreen(getScreen()); + return true; + } + + public int getPreferredWidth() { + return Display.getWidth(); + } + }); + } + + UiApplication.getUiApplication().pushScreen(dialog); + } +} diff --git a/Titlebar/README.md b/Titlebar/README.md index a046b72..ff599bd 100644 --- a/Titlebar/README.md +++ b/Titlebar/README.md @@ -89,7 +89,7 @@ Please see the [README](https://github.com/blackberry/Samples-for-Java) of the S ## Bug Reporting and Feature Requests -If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-for-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/Samples-for-Java/issues). +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-for-Java/issues) for the Sample. ## Disclaimer diff --git a/YouTube Client/README.md b/YouTube Client/README.md index 799fec9..1ac6cc9 100644 --- a/YouTube Client/README.md +++ b/YouTube Client/README.md @@ -33,7 +33,7 @@ Please see the [README](https://github.com/blackberry/Samples-for-Java) of the S ## Bug Reporting and Feature Requests -If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-for-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/Samples-for-Java/issues). +If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/Samples-for-Java/issues) for the Sample. ## Disclaimer