tweet search – one code, three mobile platforms (wp7, monodroid, monotouch)
Here is the presentation and the source code from the speech I held at the Norwegian .Net User Group last wednesday.
tweet search
‘tweet search’ is a mobile twitter search app written in c# for Windows Phone 7, iPhone and Android. All three apps share the same twitter search code, but they have custom gui code (WP7=Silverlight, iPhone=MonoTouch, Android=MonoDroid).

Go to the bottom of this article to find links to the source code & presentation.
Shared twitter-code:
public class Twitter
{
public event EventHandler twitteSearchCompleted;
public Twitter()
{
}
public void search(string searchText)
{
if (searchText != "")
{
WebClient client = new WebClient();
client.DownloadStringAsync(new Uri("http://search.twitter.com/search.atom?q=" + searchText));
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
}
}
private void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
List twitteList = new List();
XDocument xml = XDocument.Parse(e.Result);
XNamespace atomNS = "http://www.w3.org/2005/Atom";
var tempList = (from entry in xml.Descendants(atomNS + "entry")
select new TwitterObject()
{
ID = entry.Element(atomNS + "id").Value,
Title = entry.Element(atomNS + "title").Value,
Date = DateTime.Parse(entry.Element(atomNS + "published").Value),
AuthorName = entry.Descendants(atomNS + "author").Elements(atomNS + "name").FirstOrDefault().Value,
AuthorUri = entry.Descendants(atomNS + "author").Elements(atomNS + "uri").FirstOrDefault().Value,
AuthorImage = (from imgElement in entry.Elements(atomNS + "link")
where imgElement.Attribute("rel") != null
&& imgElement.Attribute("rel").Value.Contains("image")
&& imgElement.Attribute("href") != null
select imgElement.Attribute("href").Value).FirstOrDefault()
}).ToList();
twitteList = tempList.ToList();
twitteSearchCompleted(twitteList, null);
}
}
}
public class TwitterObject
{
public string ID { get; set; }
public string Title { get; set; }
public DateTime Date { get; set; }
public string AuthorName { get; set; }
public string AuthorUri { get; set; }
public string AuthorImage { get; set; }
}
WP7 code:
namespace tweet_search_wp7
{
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
}
#region UI
private void txtSearch_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
this.Focus();
}
}
private void txtSearch_LostFocus(object sender, RoutedEventArgs e)
{
search();
}
private void lboTwitte_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
lboTwitte.SelectedIndex = -1;
}
private void imgSearch_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
search();
}
#endregion
#region Twitter
private void search()
{
lblLoading.Visibility = Visibility.Visible;
lboTwitte.Opacity = 0.3;
Twitter twitter = new Twitter();
twitter.twitteSearchCompleted += new EventHandler(twitter_downloadCompleted);
twitter.search(txtSearch.Text);
}
private void twitter_downloadCompleted(object sender, EventArgs e)
{
List list = (List)sender;
lboTwitte.ItemsSource = list;
lblLoading.Visibility = Visibility.Collapsed;
lboTwitte.Opacity = 1;
}
#endregion
}
}
MonoTouch code:
namespace tweetsearchiphone
{
public partial class MainPage : UIViewController
{
#region Constructors
// The IntPtr and initWithCoder constructors are required for items that need
// to be able to be created from a xib rather than from managed code
public MainPage (IntPtr handle) : base(handle)
{
Initialize ();
}
[Export("initWithCoder:")]
public MainPage (NSCoder coder) : base(coder)
{
Initialize ();
}
public MainPage () : base("MainPage", null)
{
Initialize ();
}
void Initialize ()
{
}
#endregion
#region UI
public override void ViewDidLoad()
{
base.ViewDidLoad();
lblTwitter.Text = "";
txtSearch.ShouldReturn = delegate
{
txtSearch.ResignFirstResponder();
search();
return true;
};
imgSearch.TouchUpInside += HandleImgSearchTouchUpInside;
}
void HandleImgSearchTouchUpInside (object sender, EventArgs e)
{
search();
}
#endregion
#region Twitter
private void search()
{
Twitter twitter = new Twitter();
twitter.twitteSearchCompleted += twitter_downloadCompleted;
twitter.search(txtSearch.Text);
}
void twitter_downloadCompleted (object sender, EventArgs e)
{
List list = (List) sender;
BeginInvokeOnMainThread (delegate {
foreach(TwitterObject tweet in list)
{
lblTwitter.Text += tweet.Date.ToString() + Environment.NewLine + tweet.Title + Environment.NewLine + Environment.NewLine;
}
});
}
#endregion
}
}
MonoDroid code:
namespace tweet_search_android
{
[Activity (Label = "tweet search", MainLauncher = true)]
public class ButtonActivity : Activity
{
List list = new List();
Android.Widget.Button btnSearch;
TextView lblTwitter;
EditText txtSearch;
private List photo_ids = new List() { Resource.drawable.bird };
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SetContentView(Resource.layout.main);
ImageView btnSearch = FindViewById(Resource.id.btnSearch);
btnSearch.SetImageResource(photo_ids[0]);
btnSearch.Click += new EventHandler(btnSearch_Click);
txtSearch = FindViewById(Resource.id.txtSearch);
lblTwitter = FindViewById(Resource.id.lblTwitter);
}
void btnSearch_Click(object sender, EventArgs e)
{
if (list.Count == 0)
{
Twitter twitter = new Twitter();
twitter.twitteSearchCompleted += new EventHandler(twitter_twitteSearchCompleted);
twitter.search("nnug");
}
else
{
foreach (TwitterObject twitter in list)
{
lblTwitter.Text += twitter.Date.ToString() + System.Environment.NewLine + twitter.Title + System.Environment.NewLine + System.Environment.NewLine;
}
list = new List();
}
}
void twitter_twitteSearchCompleted(object sender, EventArgs e)
{
list = (List)sender;
}
}
}
- Media coverage « Sigurd Snørteland pingbacked on 2 years, 5 months ago
- Tweet search – one code, three mobile platforms (wp7, monodroid, monotouch) (via Sigurd Snørteland) « TechTrends pingbacked on 2 years, 5 months ago
- ひとつのC#ソースを使ってWP7・iPhone・Androidアプリを作る - ななふぉ pingbacked on 2 years, 5 months ago
- For Developers: Write Once, Run Everywhere pingbacked on 2 years, 5 months ago
- Use .NET to build Windows Phone, iPhone, iPad and Droid Apps | Mike Hacker pingbacked on 2 years, 4 months ago
- Tweet Search | AllGraphicsOnline.com pingbacked on 2 years ago
Trackbacks & Pingbacks
Trackbacks & Pingbacks
Trackbacks & Pingbacks
Trackbacks & Pingbacks
Trackbacks & Pingbacks
Trackbacks & Pingbacks
Comments
Very interesting, cool if you can do the talk in Oslo as well
Hi,
Great job and a great proof of the strengths of .Net.
However, I’d be surprised but this app would pass the AppStore submission. It looks to WP7 and not enough iPhone(ish) to be accepted.
We do something relatively similar for WP7/iPhone but we do code the UI specific to each platform and try to share the controllers (as much as possible)
WP7: Silverlight
iPhone: Interface Builder + custom view layer.
- Haven’t tried Android yet.
It’s a bit more work but it allows you to make the app feel ‘native’ on each platform instead of strangely different.
Anyway, fantastic work.
Corneliu.







I’ve been writing Windows apps for nearly 25 years, make a living now doing WPF work, and do some iPhone/iPad and WP7 work on the side (but haven’t taken the MonoTouch plunge completely yet), and all I can say is “This just rocks.” Truly, .NET everywhere. Thanks!
| Posted 2 years, 5 months ago