Peer Communication on Windows Phone 7

Written against pre-release information

One of the new things that we get with Windows Phone 7 is socket support. While I expected to be able to open sockets to other machines with servers running on them one thing caught me by surprised; that you can also send communication from phone to phone using UDP. I’ve got to give credit to Ricky_T for pointint out the presence of this feature and posting a code sample. I wanted to try this out myself. So I made a version of the code sample that would run on both Windows Phone and on the desktop (Silverlight 4 in Out of Browser mode). I was pleasantly surprised to that I was able to open up peer communication between the desktop and phone without a problem. This capability provides a number of solutions for other problems that I’ve been considering, such as automatic discovery and configuration for communicating with services hosted on a user’s local network. 

Most of the code used in the desktop and phone version of this example are identical; I’ve shared some of the same files between projects. From the files that are not shared the counterparts in the phone and desktop version are still similar.  The core of the code is in a class called Peer. Let’s take a look at part of the body of that class. 

 

//Define the port and multicast address to be used for communication
private string _channelAddress = "224.0.0.1";
private int _channelPort = 3007;

//The event to be raised when a message comes in
public event EventHandler<MessageReceivedEventArgs> MessageReceived; 

//the UDP channel over which communication will occur.
private UdpAnySourceMulticastClient _channel;

//Create tje cjamme;
public void Initialize()
{
    _channel = new UdpAnySourceMulticastClient(IPAddress.Parse(_channelAddress), _channelPort);
}

//Open the channel and start listening
public void Open()
{
    if (_channel == null)
        Initialize();
    ClientState = ClientStatesEnum.Opening;
            

    _openResult = _channel.BeginJoinGroup((result) =>
                                                {
                                                    _channel.EndJoinGroup(result);
                                                    ClientState = ClientStatesEnum.Opened;
                                                }, null);   
            
    Receive();
}


 

//The receive method is recursive. At the end of a call to receive it calls itself 
//so that the class can continue listening for incoming requests.
void Receive()
{
    byte[] _receiveBuffer = new byte[1024];

    _channel.BeginReceiveFromGroup(_receiveBuffer, 0, _receiveBuffer.Length, (r) =>
    {
        if(ClientState!=ClientStatesEnum.Closing)
        {
            try
            {
            IPEndPoint source;
            int size= _channel.EndReceiveFromGroup(r, out source);
            OnMessageReceived(_receiveBuffer, size,  source);                                                                                   
            }
            catch (Exception )
            {
            }
            finally
            {
                this.Receive();
            }
        }
    }, null);
}
public void Send(byte[] data)
{
    if(ClientState==ClientStatesEnum.Opened)
    {
        _channel.BeginSendToGroup(data, 0, data.Length, (r) => _channel.EndSendToGroup(r),null);
    }
}

This class only sends and receives byte arrays. My only goal here was to see the code work so there are other considerations that I have decided to overlook for now. I made a client to use this code too. The client sends and receives plain text. Before sending a block of text it is necessary to convert the text to a byte array. The encoding classes in .Net will take care of this for me. When a message comes in I can also use an encoder to convert the byte array back to a string.

For this program I am adding the incoming message to a list along with the IP address from which it came

void _peer_MessageReceived(object sender, MessageReceivedEventArgs e)
{
    Action a = () =>
                    {
                        string message = System.Text.UTF8Encoding.Unicode.GetString(e.Data, 0, e.Size);
                        MessageList.Add(String.Format("{0}:{1}", e.Endpoint.Address.ToString(), message));
                        OnIncomingMessageReceived(message, e.Endpoint.Address.ToString());
                    };
    if (UIDispatcher == null)
        a();
    else
        UIDispatcher.BeginInvoke(a);
}

public void SendMessage(string message)
{
    byte[] encodedMessage= UTF8Encoding.Unicode.GetBytes(message);
    _peer.Send(encodedMessage);
}

When the code is run on any combination of multiply phones or computers a message types on any one of the devices appears on all of them. Nice! Now to start making use of it.

John Conway’s Game of Life part 1 of N

The Game of Life is a refinement of an idea from John von Newman in the 1940’s. The refinement was done by John Conway and appeared in Scientific America in October 1970. I’ll skip over the details of why such a program is of interest. But the program produces some interesting patterns.

The typical version of the game is composed of a grid of cells where some number of cells are initially marked as having life. The grid of cells is evaluated and cells get marked as alive or dead based on a small set of rules based on it’s neighbors. Two cells are neighbors with each other if they touch diagonally or side-by-side.

  1. Any live cell with fewer than two live neighbours dies, as if caused by under-population.
  2. Any live cell with two or three live neighbours lives on to the next generation.
  3. Any live cell with more than three live neighbours dies, as if by overcrowding.
  4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

The above algorithm enough and the program is easy to implement. The challenge is more in creating a decent user interface for the program. I decided to make this program myself. The first step in making the program was to implement the algorithm. I wanted to make sure the algorithm worked so I created a simple XNA program that would allow me to see the algorithm work. It’s non-interactive so you can only see the program run but not impact the outcome.

Theres a small amount of data that needs to be tracked for each cell. I need to know if a cell is alive and whether or not it should be alive during the next cycle. The cell will also need to interact with other cells in the community. Some time in the future I plan to allow the cells to express something about the parent from which it came. Though I won’t be doing that for this first version.

public class Cell
{
     public CellCommunity  Community   { get; set; }
     public bool           IsAlive     { get; set; }
     public bool           WillSurvive { get; set; }
     public Gene           GeneList { get; set; }
}

The community of cells themselves will be saved in a two dimensional array. The cell community class has two methods that will do the work of calculating whether or not a cell should be alive the next cycle and another for applying the results of those calculations.

public void EvaluateNewGeneration()
{
    ++GenerationCount;

    for (var cx = 0; cx < CellGrid.GetUpperBound(0); ++cx)
    {
        for (var cy = 0; cy  MAX_NEIGHBOR_COUNT) || (neighborsneighborList.Length < MIN_NEIGHBOR_COUNT))
                    KillCell(cx, cy);
                else
                    KeepCellAlive(cx, cy);
            }
            else
            {
                if ((neighborsneighborList.Length ==3))
                {
                    KeepCellAlive(cx, cy);
                }
            }
        }
    }
}

public void ApplySurvival()
{
    for (var cx = 0; cx < CellGrid.GetUpperBound(0); ++cx)
    {
        for (var cy = 0; cy < CellGrid.GetUpperBound(1); ++cy)
        {
            var cell = CellGrid[cx, cy];
            if (cell != null)
            {
                cell.IsAlive = cell.WillSurvive;
            }
        }
    }
}

I decided to make the UI in XNA. I have an idea on how to visualize a cell changing state and I can more easily implement it using a 3D API. Since the "world" of the Game of Life is in a grid I’m going to represent the state of a cell with a square that is either black (if the cell is not alive) or some other color (if the cell is alive). I’m drawing the squares by rendering vertices instead of writing sprites. This give me greater liberty in changing the color or shape of a cell. The following will draw one of the squares.

const int _squareWidth = 5;
const int _squareHeight = 5;
private const int _offsetX = -_squareWidth*30;
private const int _offsetY = -_squareHeight*18;

void DrawSquare(int x, int y, Color c)
{
    _vertices[0].Color = c;
    _vertices[1].Color = c;
    _vertices[2].Color = c;
    _vertices[3].Color = c;

    _vertices[0].Position.X = _offsetX + _squareWidth * x + _squareWidth;
    _vertices[0].Position.Y = _offsetY + _squareHeight * y;

    _vertices[1].Position.X = _offsetX + _squareWidth*x;
    _vertices[1].Position.Y = _offsetY + _squareHeight*y;

    _vertices[2].Position.X = _offsetX + _squareWidth * x + _squareWidth;
    _vertices[2].Position.Y = _offsetY + _squareHeight * y + _squareHeight;

    _vertices[3].Position.X = _offsetX + _squareWidth * x;
    _vertices[3].Position.Y = _offsetY + _squareHeight * y +_squareHeight;

    graphics.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, _vertices, 0, _vertices.Length-2);     
}

With the ability to draw the square completed it’s easy to iterate through the collection of cells and render them to the screen according to whether or not they are alive.

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    var effect = new BasicEffect(GraphicsDevice);
    effect.World = _world;
    effect.Projection = _projection;
    effect.View = _view;
    effect.VertexColorEnabled = true;
    effect.TextureEnabled = false;
    effect.LightingEnabled = false;

    foreach(var effectPass in effect.CurrentTechnique.Passes)
    {
        effectPass.Apply();
        for (int cx = 0; cx < 60;++cx )
        {
            for(int cy=0;cy<36;++cy)
            {
                Color c = _community.IsAlive(cx, cy) ? Color.Red : Color.Black;
                DrawSquare(cx,cy,c);
            }
        }                    
    }
    base.Draw(gameTime);
}

I manually populated the grid and let it run. I’m happy to say it seems to be working. Now onto designing and making the user interface.

Screen Shot

What’s Coming to Windows Phone in 2011?

With more that 13,000 applications in their Marketplace Microsoft came out on stage today to make some new announcements about what’s coming to Windows Phone 7. We’ll see a major upgrade on all Windows Phone devices by the end of the year and developers are getting access to a lot of new APIs enabling new application scenarios.

Here is a summary list of the new features.

  • Multitasking – in addition to faster application switching multitasking will allow applications to continue processing in the background.
  • Live Tile Functionality Enhancements
  • Sensor Library Enhancements – You’ll have enhanced access to the sensor library and
      Access to the camera and compass-! Reality augmentation is possible!
    • Sockets – This needs no explanation
    • Database
    • IE9 – with hardware acceleration
    • Silverlight+XNA – you can use Silverlight and XNA in the same application
    • Twitter in the People Hub
    • Background Transfers
    • Profile
    • Silverlight 4 Runtime

    Several new countries are being added to the Marketplace. This brings up the total count from 17 to 35. The new countries are listed below with *.

    • Australia
    • Austria
    • Belgium
    • Brazil*
    • Canada
    • Chile*
    • Columbia*
    • Czech Republic*
    • Denmark*
    • Finland*
    • France
    • Germany
    • Greece*
    • Hong Kong
    • Hungary*
    • India*
    • Ireland
    • Italy
    • Japan*
    • Mexico
    • Netherlands*
    • New Zealand
    • Norway*
    • Poland*
    • Portugal*
    • Russia*
    • Singapore
    • South Africa*
    • South Korea*
    • Spain
    • Sweden*
    • Switzerland
    • Taiwan*
    • UK
    • USA /

Streaming from the Microphone to Isolated Storage

Last week I posted a sample voice recorder on CodeProject. The application would buffer the entire recording in memory before writing it to a file. A rather astute reader asked me what would happen if the user let the recording go long enough to fill up memory. The answer to that question is the application would crash due to an exception being trhown when it fails to allocate more memory and all of the recordingwould be lost. I had already been thinking of a sime reusable solution for doing this but I also offered to the user the following code sample to handle streaming directly to IsolatedStorage.
My two goals in writing it were to keep it simple and keep it portable/reusable. As far as usage goes I can’t think of any ways to make it any easier.
   //To start a recording
   StreamingRecorder myRecorder  = new StreamingRecorder();
   myRecorder.Start("myFileName");

  //To stop a recording();
  myRecorder.Stop();
After the code has run you will have a WAVE file with a proper header ready to be consumed by a SoundEffect, MediaElement, or whatever it is that you want to do with it.

In implementing this I must say that I have a hiher appreciation for how MediaElement‘s interface is designed. The starting and stopping process are not immediate. In otherwords when you call Start() or Stop() it is not until a few moments later that the request is fully processed. Because of the asynchronous nature of these processes I’ve implemented the event RecordingStateChanged and the property RecordingState so that I would know when a state change was complete. If you are familiar with the media element class then your recognize the similarity of this pattern.
I’ll go into further details on how this works along with implemeting some other functionality (such as a Pause method) in a later post. But the code is in a working state now so I’m sharing it. ๐Ÿ™‚
Here is the source:
public class StreamingRecorder :INotifyPropertyChanged,  IDisposable
{


    object SyncLock = new object();

    private Queue<MemoryStream> _availablBufferQueue;        
    private Queue<MemoryStream> _writeBufferQueue;

    private int _bufferCount;
    private byte[] _audioBuffer;

    //private int _currentRecordingBufferIndex;
        

    private TimeSpan _bufferDuration;
    private int _bufferSize;
    private Stream _outputStream;
    private Microphone _currentMicrophone;
    private bool _ownsStream = false;
    private long _startPosition;

    

    public  StreamingRecorder(TimeSpan? bufferDuration = null, int bufferCount=2)
    {
        _bufferDuration = bufferDuration.HasValue ? bufferDuration.Value : TimeSpan.FromSeconds(0);
        _bufferCount = bufferCount;
        _currentMicrophone= Microphone.Default;   
    }

    private MemoryStream CurrentBuffer
    {
        get; set;
    }

    public void Start(string fileName)
    {
        var isoStore = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication();
        var targetFile = isoStore.OpenFile(fileName, FileMode.Create);
        Start(targetFile, true);
    }

    public void Start(Stream outputStream, bool ownsStream=false)
    {
        _outputStream = outputStream;
        _ownsStream = ownsStream;
        _startPosition = outputStream.Position;

        Size = 0;

        //Create our recording buffers
        _availablBufferQueue = new Queue<MemoryStream>();
        _writeBufferQueue = new Queue<MemoryStream>();
        _audioBuffer = new byte[_currentMicrophone.GetSampleSizeInBytes(_currentMicrophone.BufferDuration)];
        _bufferSize = _currentMicrophone.GetSampleSizeInBytes(_bufferDuration + _currentMicrophone.BufferDuration);
        for (var i = 0; i < _bufferCount; ++i)
        {
            _availablBufferQueue.Enqueue(new MemoryStream(_bufferSize));
        }

        CurrentBuffer = _availablBufferQueue.Dequeue();
        //Stuff a bogus wave header in the output stream as a space holder.
        //we will come back and make it valid later. For now the size is invalid.
        //I could have just as easily stuffed any set of values here as long as 
        //the size of those values equaled 0x2C
        WaveHeaderWriter.WriteHeader(CurrentBuffer, -1, 1, _currentMicrophone.SampleRate);
        Size += (int)CurrentBuffer.Position;

        //Subscribe to the Microphone's buffer ready event and start listening.
        _currentMicrophone.BufferReady += new EventHandler<EventArgs>(_currentMicrophone_BufferReady);            
        _currentMicrophone.Start();
    }


    void _currentMicrophone_BufferReady(object sender, EventArgs e)
    {
        _currentMicrophone.GetData(_audioBuffer);
        //If the recorder is paused (not implemented) then don't add this audio chunk to
        // the output. If HasFlushed is set then the recording is actually ready to shut
        //down and we shouldn't accumulate anything more. 
        if ((CurrentState != RecordingState.Paused))
        {
            //Append the audio chunk to our current buffer
            CurrentBuffer.Write(_audioBuffer, 0, _audioBuffer.Length);
            //Increment the size of the recording.
            Size += _audioBuffer.Length;
            //If the buffer is full or if we are shutting down then we need to submit
            //the buffer to be written to the output stream.
            if ((CurrentBuffer.Length > _bufferSize)||(CurrentState==RecordingState.Stopping))
            {

                SubmitToWriteBuffer(CurrentBuffer);
                //If we were shutting down then set a flag so that it is known that the last audio
                //chunk has been written. 
                if (CurrentState == RecordingState.Stopping)
                {
                    _currentMicrophone.Stop();
                    _currentMicrophone.BufferReady -= _currentMicrophone_BufferReady;
                }
                CurrentBuffer = _availablBufferQueue.Count > 0 ? _availablBufferQueue.Dequeue() : new MemoryStream();
            }
        }
    }

                

    // CurrentState - generated from ObservableField snippet - Joel Ivory Johnson

    private RecordingState _currentState;
    public RecordingState CurrentState
    {
        get { return _currentState; }
        set
        {
            if (_currentState != value)
            {
                _currentState = value;
                OnPropertyChanged("CurrentState");
                OnRecordingStateChanged(value);
            }
        }
    }
    //-----


    void WriteData(object a )
    {

        lock(SyncLock)
        {                
            while (_writeBufferQueue.Count > 0)
            {
                var item = _writeBufferQueue.Dequeue();
                var buffer = item.GetBuffer();
                _outputStream.Write(buffer, 0,(int) item.Length);
                item.SetLength(0);

                _availablBufferQueue.Enqueue(item);

                if (CurrentState == RecordingState.Stopping)
                {
                    //Correct the information in the wave header. After it is
                    //written set the file pointer back to the end of the file.
                    long prePosition = _outputStream.Position;
                    _outputStream.Seek(_startPosition, SeekOrigin.Begin);
                    WaveHeaderWriter.WriteHeader(_outputStream,Size-44,1,_currentMicrophone.SampleRate);
                    _outputStream.Seek(prePosition, SeekOrigin.Begin);
                    _outputStream.Flush();
                    if (_ownsStream)
                        _outputStream.Close();
                    CurrentState = RecordingState.Stopped;
                }
            }
        }
    }

    void SubmitToWriteBuffer(MemoryStream target)
    {
        //Do the writing on another thread so that processing on this thread can continue. 
        _writeBufferQueue.Enqueue(target);
        ThreadPool.QueueUserWorkItem(new WaitCallback(WriteData));
    }

    public void Pause()
    {
        if ((CurrentState != RecordingState.Paused) && (CurrentState != RecordingState.Recording))
        {
            throw new Exception("you can't pause if you are not recording");
        }
        CurrentState = RecordingState.Paused;
    }

    public void Stop()
    {
        CurrentState = RecordingState.Stopping;
    }


    // Size - generated from ObservableField snippet - Joel Ivory Johnson

    private int  _size;
    public int Size
    {
        get { return _size; }
        set
        {
            if (_size != value)
            {
                _size = value;
                OnPropertyChanged("Size");
            }
        }
    }
    //-----

    public long RemainingSpace
    {
        get
        {                
            return System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication().AvailableFreeSpace;
        }
    }

    public TimeSpan RecordingDuration
    {
        get
        {
            return _currentMicrophone.GetSampleDuration((int)Size);
        }
    }

    public TimeSpan RemainingRecordingTime
    {
        get
        {
            return _currentMicrophone.GetSampleDuration((int)RemainingSpace);
        }
    }

    //-------

    public event EventHandler<RecordingStateChangedEventArgs> RecordingStateChanged;
    protected void OnRecordingStateChanged(RecordingState newState)
    {
        if(RecordingStateChanged!=null)
        {
            RecordingStateChanged(this, new RecordingStateChangedEventArgs(){NewState = newState});
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public void Dispose()
    {
        Stop();
    }
}

 

Voice Memo Source for WP7

This question keeps coming up in the forums so I decided to put the application together and make it publically available. If you head over to CodeProject you’ll find a small article that I uploaded on making a voice memo application on Windows Phone 7. Among other things is demonstrates how to convert the raw recording bytes to a proper wave file, simple serialization, and a few other tid bits. For the sake of the article I did send the code through certification.

However the application looks ugly right now. I’ve got a graphic artist that I’ll be paying to design the UI for me and since I’m paying her for this I’ve decided not to include the graphic assets that she is producing in the code that I’m gicing away for free.

There’s no obligations attached to the code. But if you use it in your own products I would appreciate a heads up just so that I know where it’s being used.

Share photos on twitter with Twitpic

Tracking High Scores on Windows Phone

Another frequent question I come across in the user forums is related to how some one implements local high scores. The question has come up frequently enough for me to conclude that its to the benifit of the community to have an implementation available that can be used in Silverlight or XNA that is ready to be used with very little setup.

So I’ve made a solution for others to use. By default the component will keep track of up to 10 high scores and will take care of loading and saving itself. If you add a score the component will take care of ensuring the score is in it’s proper place and removing scores that are nolonger one of the top. For persisting the score information I’ve made use of the DataSaver<T> code from a previous blog post. I hope others will find the solution easy to use.

To get started with using the component add a reference to my component to your project. You’ll want to instantiate HighScoreList passing an optional file name that it will use to save score information. It’s possible to keep track of more than one high score list as long as your instances have different file names. One might want to do this if they keep track of scores in different modes separately from each other (Ex: a score list for Difficult mode, a score list for Easy mode, and so on).

HighScoreList _highScoreList = new HighScoreList("MyScores");

Upon instantiation the component will take care of loading any previous high scores without you doing anything more.

To add a score create a new instance of ScoreInfo and populate its PlayerName and Score fields. (There is also a ScoreDate field that automatically gets populated with the current date and time). Then use the AddScore(ScoreInfo) method on the HighScoreList instance to add it to the score list.

ScoreInfo scoreInfo = new ScoreInfo(){PlayerName = "Jack", Score = 1048576};
_highScoreList.AddScore(scoreInfo);

And that’s it, there’s nothing more for you to do. When you make that call the score gets added to the high score list, scores that are no longer in the top 10 (or what ever you set the limit to be) will fall off the list, and the list will automatically be persisted back to IsolatedStorage so that it is available the next time your game runs. Easy, right?

As a test project I’ve created a Silverlight application that allows you to enter new scores and see the behaviour of the component.

Score Keeper Screenshot

The main bits of the source code are below. First the ScoreInfo class which is nothing more than a serializable collection of three properties

/// <summary>
/// ScoreInfo contains information on a single score
/// </summary>
[DataContract]
public class ScoreInfo : INotifyPropertyChanged
{

    // PlayerName - generated from ObservableField snippet - Joel Ivory Johnson
        private string _playerName = String.Empty;

    /// <summary>
    /// The name of the player that made this score
    /// </summary>
        [DataMember]
        public string PlayerName
        {
        get { return _playerName; }
            set
            {
                if (_playerName != value)
                {
                    _playerName = value;
                    OnPropertyChanged("PlayerName");
                }
            }
        }
        //-----

    // Score - generated from ObservableField snippet - Joel Ivory Johnson
        private int _score = 0;

    /// <summary>
    /// The score that the player made
    /// </summary>
        [DataMember]
        public int Score
        {
        get { return _score; }
            set
            {
                if (_score != value)
                {
                    _score = value;
                    OnPropertyChanged("Score");
                }
            }
        }
        //-----

    // ScoreDate - generated from ObservableField snippet - Joel Ivory Johnson
        private DateTime _scoreDate = DateTime.Now;

    /// <summary>
    /// The date and time that the player made the score. If this field is not
    /// assigned a value it will automatically be assigned with the date and time
    /// that the score isntance was created
    /// </summary>
        [DataMember]
        public DateTime ScoreDate
        {
        get { return _scoreDate; }
            set
            {
                if (_scoreDate != value)
                {
                    _scoreDate = value;
                    OnPropertyChanged("ScoreDate");
                }
            }
        }
        //-----
    protected void OnPropertyChanged(String propertyName)
    {
        if(PropertyChanged!=null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #region INotifyPropertyChanged Members

    public  event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

And then the HighScoreList class, which is a collection class that contains the .

using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.Serialization; namespace J2i.Net.ScoreKeeper { public class HighScoreList : ObservableCollection<ScoreInfo>, INotifyPropertyChanged { static DataSaver<HighScoreList> MyDataSaver = new DataSaver<HighScoreList>(); public HighScoreList() { } public HighScoreList(string fileName):this() { this.ScoreFileName = fileName; HighScoreList temp = MyDataSaver.LoadMyData(fileName); if(temp!=null) { foreach(var item in temp) { Add(item); } } } // MaxScoreCount - generated from ObservableField snippet - Joel Ivory Johnson private int _maxScoreCount = 10; [DataMember] public int MaxScoreCount { get { return _maxScoreCount; } set { if (_maxScoreCount != value) { _maxScoreCount = value; OnPropertyChanged("MaxScoreCount"); } } } //----- // ScoreFileName - generated from ObservableField snippet - Joel Ivory Johnson private string _scoreFileName = "DefaultScores"; [DataMember] public string ScoreFileName { get { return _scoreFileName; } set { if (_scoreFileName != value) { _scoreFileName = value; OnPropertyChanged("ScoreFileName"); } } } //----- // AutoSave - generated from ObservableField snippet - Joel Ivory Johnson private bool _autoSave = true; [DataMember] public bool AutoSave { get { return _autoSave; } set { if (_autoSave != value) { _autoSave = value; OnPropertyChanged("AutoSave"); } } } //----- static int ScoreComparer(ScoreInfo a, ScoreInfo b) { return b.Score - a.Score; } public void SortAndDrop() { List<ScoreInfo> temp = new List<ScoreInfo>(this.Count); foreach(var item in this) { temp.Add(item); } if (temp.Count > MaxScoreCount) { temp.RemoveRange(MaxScoreCount - 1, (temp.Count) - (MaxScoreCount)); } temp.Sort(ScoreComparer); this.Clear(); temp.ForEach((o)=>Add(o)); } public void Save() { if(String.IsNullOrEmpty(ScoreFileName)) throw new ArgumentException("A file name wasn't provided"); MyDataSaver.SaveMyData(this, ScoreFileName); } public void AddScore(ScoreInfo score) { this.Add(score); SortAndDrop(); if(AutoSave) Save(); } protected void OnPropertyChanged(String propertyName) { if(PropertyChanged!=null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; #endregion } } 

File x.inf contains DirIDs, which are not supported

I was compiling a cab for a Windows Mobile install when I came across an unexpected error.

Windows CE CAB Wizard    ?Error: Line  92 - unsupported DirID 0  Error: File c:\users\joeljo~1\appdata\local\temp\wizb912.inf contains DirIDs, which are not supported

It took a little while to figure out what this means. Searching on the web I found this can happen if you package more than 1000 files in a cab (or more than 262 in some cases). That wasn’t the cause of the problem that I was encountering though. It took a little while and I finally figured out what was causing it. One of the registry keys had a typographical error in it. I had typed “%InstallDir” instead of “%InstallDir%”. So if you ever encounter this problem remember to double check your registry key names.


From the Blog Engine Archives

Posts may contain products with affiliate links. When you make purchases using these links, we receive a small commission at no extra cost to you. Thank you for your support.

Mastodon: @j2inet@masto.ai
Instagram: @j2inet
Facebook: @j2inet
YouTube: @j2inet
Telegram: j2inet
Twitter: @j2inet

Handling Cookies with Redirects and HttpWebRequest

The HttpWebRequest handles redirects automatically. That’s usually a nice feature but it can actually get in the way when the web server is setting cookies in the same response in which it is sending a redirect. For some odd reason the HttpWebRequest object will totally discard cookies that are set with a redirect response. I ran into a problem with this when I was working in some code that interfaced to Google Voice and it was driving me crazy since I didn’t know where the problem was coming from.

Once I figured out what was happening the solution to the problem was simple. The first step is to disable the class’s automatic response to redirect request. When a response is returned from the class it’s necessary to check the response to see if it includes a redirect and if so create a new request. Since a redirect could occur more than once it is necessary to do this in a loop. With each new WebRequest that is created it is necessary to set the CookiesContainer member.

A simplified version of my code looks like the following:

using System.Net;

HttpWebRequest GetNewRequest(string targetUrl) { 
	HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(targetUrl); 
	request.CookieContainer = SessionCookieContainer; 
	request.AllowAutoRedirect = false; 
	return request; 
}
HttpWebRequest request = GetNewRequest(targetUrl); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
while (response.StatusCode == HttpStatusCode.Found)
{
	response.Close(); 
	request = GetNewRequest(response.Headers["Location"]); 
	response = (HttpWebResponse)request.GetResponse();
}
//--At this point the redirected response is ready to be used  

Trying to perform this same thing on the .Net Compact Framework is a little more challenging since it doesn’t support cookies at all. I’ll discuss the solution I used in another post within the next few days.


From the Blog Engine Archives

Posts may contain products with affiliate links. When you make purchases using these links, we receive a small commission at no extra cost to you. Thank you for your support.

Mastodon: @j2inet@masto.ai
Instagram: @j2inet
Facebook: @j2inet
YouTube: @j2inet
Telegram: j2inet
Twitter: @j2inet

Making Designer Friendly Controls

I discovered this blog entry by way ofย SmartMobiDevice.comย and thought that it was something I should share. If you’ve ever made your own controls for Windows Mobile you know that if the control is making any P/Invoke calls to native methods then it will not render in the designer. Simon Hart has aย simple solutionย for this. The identity of the application domain is different on the desktop and in Windows Mobile devices and using that identity he conditionally makes the P/Invoke call which results in a design friendly control. To see his example source codeย read on.


From the BlogEngine Archives

Posts may contain products with affiliate links. When you make purchases using these links, we receive a small commission at no extra cost to you. Thank you for your support.

Mastodon: @j2inet@masto.ai
Instagram: @j2inet
Facebook: @j2inet
YouTube: @j2inet
Telegram: j2inet
Twitter: @j2inet

Popular Misconception: The override that was not

I was interviewing for jobs this past week and at all of the interviews I was presented with questions about object oriented techniques and C#. When asked abouit overriding a method on a class that wasn’t marked as virtual I informed the interviewers that it can’t be done. I didn’t realize that the interviewers were considering my answer to be wrong until yesterday when an interviewer presented to me the answer that he was looking for. He told me that I could override an otherwise unoverridable method by using the new keyword on it. That started a discussion which resulted in the interviewer wondering whether or not the method was really effectively overridden. After I had the discussion with him I realized the earlier interviewers may have also thought that my answer was incorrect.

The misconception comes from an observation of what happens when one uses the new keyword on a method. To make this discussion a little more concrete I’ll share some example code.

class MyBase
{
    public virtual string MethodA() 
    { 
        return "Hello from MethodA"; 
    }
    public string MethodB() 
    { 
        return "Hello from MethodB"; 
    }
}

What this class does is obvious.It has two methods both of which return a unique string. The class is simple enough that I’m sure you’ll trust me when I say it reliably does its job without error. One of the methods is marked as virtual, so it is overridable. The other is not. So now I derrive a class from this base class.

class Derived : MyBase 
{ 
	public override string MethodA() 
	{ 
		return "Hello from Derrived::MethodA"; 
	} 
	public new string MethodB() { 
		return "Hello from Derived::MethodB"; 	
	} 
}

In this derrived class I have overriddenย MethodA. Sinceย MethodBย is not marked as virtual I could not override it so I used theย newย keyword. Let’s test the program to see what type of output it produces.

using System;

static void Main(string[] args) 
{ 
	var a = new Derived(); 
	var b = new MyBase(); 
	Console.Out.WriteLine(b.MethodA()); 
	Console.Out.WriteLine(b.MethodB()); 
	Console.Out.WriteLine(a.MethodA()); 
	Console.Out.WriteLine(a.MethodB()); 
}

The output from running this is what one would expect. When I callย MethodAย andย MethodBย the the strings derrived in the derrived class are displayed.

Hello from MethodA  
Hello from MethodB
Hello from Derrived::MethodA
Hello from Derived::MethodB

Upon seeing this behaviour it seems that the developers I spoke to last week thought this to be the functional equivalent of overriding. But the difference shows up when the instance of the class is handled through either an interface or a base class reference. Let’s say I appended the following to the above code.

var c = a as MyBase;    
Console.Out.WriteLine(c.MethodA());  
Console.Out.WriteLine(c.MethodB());  

The output is not consistent with what we would expect an overridden method would produce.

Hello from Derrived::MethodA  
Hello from MethodB

The above output demonstrates that when a method has been overridden then the method will be called regardless of the interface used to interact with the object instance. MethodA had been overridden so even though a variable whose type is of the base class is used the overridden implementation is invoked. MethodB was never truly overriden so when a base class reference is used the base class implementation is called.

So then what did the new keyword really do? It allowed some one to create a method that has the same signature and name as an existing method. While the method is called with the same notation that would have been used to call the original method it is not actually performing an override. It is only hiding it. For confirmation one can also look at the C# documentation for the new keyword on MSDN which refers to this as name hidinghttp://msdn.microsoft.com/en-us/library/51y09td4(VS.71).aspx#vclrfnew_newmodifier

Name hiding through inheritance takes one of the following forms:

  • A constant, field, property, or type introduced in a class or struct hides all base class members with the same name.
  • A method introduced in a class or struct hides properties, fields, and types, with the same name, in the base class. It also hides all base class methods with the same signature. For more information, seeย 3.6 Signatures and overloading.
  • An indexer introduced in a class or struct hides all base class indexers with the same signature.

Digging deeper into the documentation we find the following:

The scope of an entity typically encompasses more program text than the declaration space of the entity. In particular, the scope of an entity may include declarations that introduce new declaration spaces containing entities of the same name. Such declarations cause the original entity to become hidden. Conversely, an entity is said to be visible when it is not hidden.The conclusion: The new keyword is not performing an override, it is a scoping operator.


From the BlogEngine Archive

Posts may contain products with affiliate links. When you make purchases using these links, we receive a small commission at no extra cost to you. Thank you for your support.

Mastodon: @j2inet@masto.ai
Instagram: @j2inet
Facebook: @j2inet
YouTube: @j2inet
Telegram: j2inet
Twitter: @j2inet

Landing Page Removed

I’ve had a landing page on my site for some time now that would allow you to get to either the old site content or the newer site content. I’m going to remove that page now and just post the link to the old site content here. Eventually the old site content will go away. Some of the more popular content with in it has already been replaced with redirects to repost of the same content within the newer site. You can get to the old site content here:ย http://j2i.net/blogs/blogs/home/default.aspx.


From the BlogEngine Archives

Posts may contain products with affiliate links. When you make purchases using these links, we receive a small commission at no extra cost to you. Thank you for your support.

Mastodon: @j2inet@masto.ai
Instagram: @j2inet
Facebook: @j2inet
YouTube: @j2inet
Telegram: j2inet
Twitter: @j2inet

Caxixi now available for the Omnia II

Samsung has a percussion application for their phones known as Caxixi (pronounced Ca-shee-shee) . The application makes use of the touch screen and the accelerometer to allow you to control up to 5 percussion instruments at once. If you’ve never seen it before take a look at thisย YouTubeย video.

Samsung has recently updated the application so it is now available for the Omnia II. You can download it from samsungcaxixi.com.


From the BlogEngine Archives

Posts may contain products with affiliate links. When you make purchases using these links, we receive a small commission at no extra cost to you. Thank you for your support.

Mastodon: @j2inet@masto.ai
Instagram: @j2inet
Facebook: @j2inet
YouTube: @j2inet
Telegram: j2inet
Twitter: @j2inet

WCF Guidance for Windows Mobile on Codeplex

I was looking for a Windows Mobile specific WCF reference since I knew that the Compact Framework doesn’t support all of the same WCF profiles that the desktop framework does. I was searching for a webcast that was done on the topic when I stumbled upon a document that had the information I was seeking on the CodePlex. You can see the document for yourself here. The document was created by Michele Bustamante aka That Indigo Girl.

The document contains a lot of good information and is written for the developer that has no experience with the compact framework or WCF. Only experience with the .Net framework is required. It will walk one through the steps of setting up their development environment for mobile development.

By the way, I did find a listing of the limitations for which I was looking.

FeatureSupport
StreamingNot Supported. Contract can use Stream parameters but they will not be buffered or streamed.
SessionsTransport sessions not supported. Service contract can use SessionMode.Allowed. Service should use InstanceContextMode.PerCall behaviour.
DuplexServices designed for duplex communications with callback contracts cannot be called by mobile clients. Duplex requires a transport session.
TransactionsService contract cannot require transaction for any service operations.
Data Contracts and Serializable TypesCan freely use. The mobile client will use XmlSerializer types that are wire compatible
Message ContractsCan freely use. If the message contract includes custom headers proxy generation will not work. Mobile client requires additional custom code to work with headers.
Fault ContractsCan include in the service contract. Proxy generation will not include fault contracts so additional custom code for mobile client is required to work with faults.

There are quite a few more limitations to know about for WCF in the Compact Framework. I won’t name all of them here since I think the document does an excellent job of detailing the limitations. At a length of only 72 pages including diagrams its a document that a developer should be able to easily get through.


From the BlogEngine Archives

Posts may contain products with affiliate links. When you make purchases using these links, we receive a small commission at no extra cost to you. Thank you for your support.

Mastodon: @j2inet@masto.ai
Instagram: @j2inet
Facebook: @j2inet
YouTube: @j2inet
Telegram: j2inet
Twitter: @j2inet

Provoking Post

For any mobile operating system that you can name you can find some one that will point out what they feel to be a flaw in the operating System.ย  Mikeย  Calligaro of the Windows Embedded team knows this all to well.ย  If you read through the reader responses to many of his post you’ll find a plethora of emotionally charged responsesย  For some of the responses I get the feeling the reader didn’t actually read the entire post.ย  For others some readers make pretty good arguments. In either case I decided to collect what I thought to be the most interesting post addressing features of Windows Mobile that many have questioned.

Interesting Post

Quotes from Mike:

In response to “why can’t you fix the damn bugs

As much as I love the job, there are certainly frustrations as well. One of them is that more than half of the code on one of our phones is written by other people (OEMs, ISVs contracted by OEMs, ISVs contracted by Mobile Operators, etc) and any failing in any of that code is usually blamed on us.


From the BlogEngine Archives

Posts may contain products with affiliate links. When you make purchases using these links, we receive a small commission at no extra cost to you. Thank you for your support.

Mastodon: @j2inet@masto.ai
Instagram: @j2inet
Facebook: @j2inet
YouTube: @j2inet
Telegram: j2inet
Twitter: @j2inet

Why Can’t I Create a Smart Device Project?

So you’ve installed Visual Studio and you are ready to create a Smart Device project for your Windows Mobile device.  But when you go to create a new project the Smart Device templates are no where to be found.  Why is that?  Let’s look at the possible causes for this problem. 

Is your Visual Studio Version an Express Edition?

Presently Microsoft doesn’t have a version of Visual Studio Express that can be used to create smart device projects. If you are running an Express Edition of Visual Studio you will need to replace it with a professional version to develop for Windows Mobile. 


From the BlogEngine Archives

Posts may contain products with affiliate links. When you make purchases using these links, we receive a small commission at no extra cost to you. Thank you for your support.

Mastodon: @j2inet@masto.ai
Instagram: @j2inet
Facebook: @j2inet
YouTube: @j2inet
Telegram: j2inet
Twitter: @j2inet