latest posts

Working on the Android port of jcBENCH today and ran into a question:
How to accurately detect the number of CPUs on a particular Android Device running at least Android version 4.0?

This led me to search around, I found a pretty intuitive native Java call: [csharp] Runtime.GetRuntime().AvailableProcessors(); [/csharp] But this was returning 1 on my dual core Android devices. So I continued searching, one such suggestion on Stack Overflow was to count the number of files listed in the /sys/devices/system/cpu folder that began with cpu followed by a number. I ported the Java code listed in the Stack Overflow answer into C# and ran it on all 4 Android devices I own - all of them returned 3 (and looking at the actual listing only actually found a CPU0).

This got me thinking, I wonder if the traditional C# approach would work in this case? Xamarin afterall is built off of Mono....

Sure enough: [csharp] System.Environment.ProcessorCount [/csharp] Returned properly on each device. Hopefully that helps someone out there.
Something I am used to checking in my Windows Phone apps that utilize your WiFi or 3G/4G/LTE signal is an active connection. Nothing is worse as an end user than an app that immediately crashes because you don't have a connection. Sad part at least for me, when I encounter a crash in an app that isn't my own, my first inclination is to check that I have a signal. Why have we gotten "programmed" to do this? I think the main reason, often when testing your own app, especially if you're a one person team, you never check the worse case scenarios. Most likely not intentionally, you're just focused on delivering your app on time (and budget if applicable). Luckily enough in MonoDroid (and Windows Phone 8), it is very easy to check for an active internet connection. In MonoDroid: [csharp] public bool HasInternetConnection { get { var connectivityManager = (ConnectivityManager)GetSystemService(Context.ConnectivityService); return connectivityManager.ActiveNetworkInfo != null && connectivityManager.ActiveNetworkInfo.IsConnectedOrConnecting; } } [/csharp] And in Windows Phone 8: [csharp] public bool HasInternetConnection { get { return NetworkInterface.GetIsNetworkAvailable(); } } [/csharp] One thing to note on MonoDroid, if you do not have the ACCESS_NETWORK_STATE permission checked under your Project's Properties -> Android Manifest -> Required Permissions: [caption id="attachment_1964" align="aligncenter" width="300"]Android Manifest - ACCESS_NETWORK_STATE required for checking Internet Connectivity Android Manifest - ACCESS_NETWORK_STATE required for checking Internet Connectivity[/caption] You will get the following exception: [caption id="attachment_1966" align="aligncenter" width="300"]Android Exception when there is no permission to check Network Connectivity Android Exception when there is no permission to check Network Connectivity[/caption] Simply check the ACCESS_NETWORK_STATE, rebuild, deploy and you will have detection working properly.
Jumping back into MonoDroid development the last couple days at work after having not touched it in almost a year, I knew I was going to be rusty. Interestingly enough I'm finding it much closer to Windows Phone development than I remembered. Having had no luck in finding MonoDroid for Windows Phone Developers I figured I'd start an ongoing post.

Open a Browser

In Windows Phone you would open a Web Browser with the following function: [csharp] private void openBrowser(string url) { var task = new WebBrowserTask(); task.Uri = new Uri(url); task.Show(); } [/csharp] However in MonoDroid you have to do this: [csharp] private void openBrowser(string url) { var browserIntent = new Intent(Intent.ActionView, Android.Net.Uri.Parse(url)); StartActivity(browserIntent); } [/csharp]

New Line in TextView

In Windows Phone in your XAML you'd do something like this to insert a new line into your TextBlock: [csharp] <TextBlock>This line is awesome<LineBreak/>but this one is better</TextBlock> [/csharp] However in MonoDroid you need to be sure to set the singleLine property to false like so: [csharp] <TextView android:layout_width="fill_parent" android:singleLine="false" android:text="This line is awesome\r\nbut this one is better" /> [/csharp]

Login form (aka tapping enter goes to next field, with the last field hiding the keyboard)

In your XAML on Windows Phone you might have something like the following: [csharp] <StackPanel Orientation="Vertical"> <TextBox x:Name="TextBoxUsername" /> <TextBox x:Name="TextBoxPassword" /> </StackPanel> [/csharp] And then in your code behind: [csharp] public LoginPage() { InitializeComponent(); TextBoxUsername.KeyDown += TextBoxUsername_KeyDown; TextBoxPassword.KeyDown += TextBoxPassword_KeyDown; } void TextBoxUsername_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { TextBoxPassword.Focus(); } } void TextBoxPassword_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { Focus(); } } [/csharp] Basically upon hitting the enter key while in the TextBoxUsername field it will set the focus to the TextBoxPassword field. Upon hitting enter in the TextBoxPassword field, it will set the focus to the main page and close the keyboard. For MonoDroid, it is a little different. In your axml: [csharp] <EditText android:id="@+id/TextBoxUsername" android:imeOptions="actionNext" android:singleLine="true" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <EditText android:id="@+id/TextBoxPassword" android:imeOptions="actionDone" android:singleLine="true" android:layout_width="fill_parent" android:layout_height="wrap_content" /> [/csharp] The key part is the android:imeOptions values, actionNext will move the focus to the next EditText field and the actionDone will send the done command back to your keylisteners etc. In your Activity code behind, you need to add this override. Update the Resource.Id.xxxxxxx with the name of the field you want the keyboard to hide upon hitting enter: [csharp] public override bool DispatchKeyEvent(KeyEvent e) { if (CurrentFocus.Id == Resource.Id.TextBoxPasswordKey && (e.KeyCode == Keycode.NumpadEnter || e.KeyCode == Keycode.Enter)) { var imm = GetSystemService(Context.InputMethodService) as InputMethodManager; if (imm != null) { imm.HideSoftInputFromWindow(this.CurrentFocus.WindowToken, 0); } return true; } return base.DispatchKeyEvent(e); } [/csharp] I should also note you'll need the using Android.Views.InputMethods; line added to your code behind as well.

Capturing Images via the Camera

In Windows Phone capturing images from your Library or Taking a new picture is pretty trivial, assuming you have a Button to choose/take the picture: [csharp] PhotoChooserTask _pcTask = null; private byte[] _pictureBytes; public PictureUpload() { InitializeComponent(); _pcTask = new PhotoChooserTask(); _pcTask.Completed += new EventHandler<PhotoResult>(_pcTask_Completed); } void _pcTask_Completed(object sender, PhotoResult e) { if (e.TaskResult == TaskResult.OK) { MemoryStream ms = new MemoryStream(); e.ChosenPhoto.CopyTo(ms); _pictureBytes = ms.ToArray(); ms.Dispose(); } } private void btnChooseImage_Click(object sender, RoutedEventArgs e) { _pcTask.ShowCamera = true; _pcTask.Show(); } [/csharp] From there just upload the _pictureBytes to your WCF Service or wherever. In MonoDroid as expected is a little different, assuming you have a button click event to take the picture and an ImageView to display the image: [csharp] private string _imageUri; // Global variable to access the image's Uri later void btnChooseImage_Click(object sender, EventArgs e) { var uri = ContentResolver.Insert(isMounted ? Android.Provider.MediaStore.Images.Media.ExternalContentUri : Android.Provider.MediaStore.Images.Media.InternalContentUri, new ContentValues()); _imageUri = uri.ToString(); var i = new Intent(Android.Provider.MediaStore.ActionImageCapture); i.PutExtra(Android.Provider.MediaStore.ExtraOutput, uri); StartActivityForResult(i, 0); } protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { if (resultCode == Result.Ok && requestCode == 0) { imageView = FindViewById<ImageView>(Resource.Id.ivThumbnail); imageView.DrawingCacheEnabled = true; imageView.SetImageURI(Android.Net.Uri.Parse(_imageUri)); } } [/csharp] At this point you have the picture taken and the Uri of the image. In your Layout: [csharp] <Button android:text="Choose Image" android:id="@+id/btnChooseImage" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <ImageView android:id="@+id/ivThumbnail" android:layout_width="300dp" android:layout_height="150dp" /> [/csharp]

Loading a picture from local storage and avoiding the dreaded java.lang.outofmemory exception

A fairly common scenario, maybe pulling an image from the code described above, now you want to upload it some where? In the Windows Phone above in addition to taking/capturing the picture, we have a byte[] with the data, on MonoDroid it is a little different. A situation I ran into on my HTC Vivid was a java.lang.outofmemory exception. Further investigation, apparently Android has a 24mb VM limit per app (and some devices it is set to 16mb). Doing some research, I came across Twig's post. As expected it was in Java, so I converted it over to MonoDroid and added some additional features to fit my needs. So literally this function will return a scaled Bitmap object for you to turn around and convert to a Byte[]. The function: [csharp] private Android.Graphics.Bitmap loadBitmapFromURI(Android.Net.Uri uri, int maxDimension) { var inputStream = ContentResolver.OpenInputStream(uri); var bfOptions = new Android.Graphics.BitmapFactory.Options(); bfOptions.InJustDecodeBounds = true; var bitmap = Android.Graphics.BitmapFactory.DecodeStream(inputStream, null, bfOptions); inputStream.Close(); var resizeScale = 1; if (bfOptions.OutHeight > maxDimension || bfOptions.OutWidth > maxDimension) { resizeScale = (int)Math.Pow(2, (int)Math.Round(Math.Log(maxDimension / (double)Math.Max(bfOptions.OutHeight, bfOptions.OutWidth)) / Math.Log(0.5))); } bfOptions = new Android.Graphics.BitmapFactory.Options(); bfOptions.InSampleSize = resizeScale; inputStream = ContentResolver.OpenInputStream(uri); bitmap = Android.Graphics.BitmapFactory.DecodeStream(inputStream, null, bfOptions); inputStream.Close(); return bitmap; } [/csharp] For a practical use, loading the image, scaling if necessary and then getting a Byte[]: [csharp] var bitmap = loadBitmapFromURI(Android.Net.Uri.Parse(_imageUri), 800); var ms = new MemoryStream(); bitmap.Compress(Android.Graphics.Bitmap.CompressFormat.Jpeg, 100, ms); [/csharp] At this point doing a ms.ToArray() will get you to the same point the Windows Phone code above did, so if you had a WCF Service, you could at this point upload the byte array just as you could with a Windows Phone above.

Transparent Background on a ListView, LayoutView etc?

In Windows Phone you can set the Background or Foreground properties to simply Transparent like so: [csharp] <StackPanel Background="Transparent" Orientation="Vertical"> <TextBlock>Transparentcy is awesome</TextBlock> </StackPanel> [/csharp] In MonoDroid it's simply "@null" like so for the ListView [csharp] <ListView android:background="@null" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:text="Transparentcy is awesome" android:gravity="center" /> [/csharp]

Locking Orientation

In Windows Phone you can set your page's orientation to be forced into Landscape or Portrait in your xaml like so: [csharp] <phone:PhoneApplicationPage SupportedOrientations="Portrait" Orientation="Portrait"> [/csharp] In MonoDroid I couldn't figure out a better way to do it than the following line inside your Activity's OnCreate function like so: [csharp] protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); RequestedOrientation = ScreenOrientation.Portrait; } [/csharp] On a side note, you'll need to add this line to the top of your Activity if it isn't already there: using Android.Content.PM;
Had a fun time today getting a picture taken from an Android 2.3.4 HTC Vivid to my Mobile WCF Platform. Oddly enough, I could not find any tutorials on it for Monodroid like there are for MonoTouch. Piecing together several stackoverflow posts, I finally figured it out. Here is a possible solution (most likely not the best): At the top of your class, add the following: [csharp] private string _imageUri; private ImageView imageView; private Boolean isMounted { get { return Android.OS.Environment.ExternalStorageState.Equals(Android.OS.Environment.MediaMounted); } } [/csharp] Inside your Button Click Event: [csharp] var uri = ContentResolver.Insert(isMounted ? Android.Provider.MediaStore.Images.Media.ExternalContentUri : Android.Provider.MediaStore.Images.Media.InternalContentUri, new ContentValues()); _imageUri = uri.ToString(); var i = new Intent(Android.Provider.MediaStore.ActionImageCapture); i.PutExtra(Android.Provider.MediaStore.ExtraOutput, uri); StartActivityForResult(i, 0); [/csharp] Right below your Click Event function (or anywhere inside the Activity Class you're in): [csharp] protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { if (resultCode == Result.Ok && requestCode == 0) { imageView = FindViewById(Resource.Id.ivThumbnail); imageView.DrawingCacheEnabled = true; imageView.SetImageURI(Android.Net.Uri.Parse(_imageUri)); btnUploadImage.Visibility = ViewStates.Visible; } } [/csharp] Then inside your "Upload Button Click" function: [csharp] Bitmap bitmap = imageView.GetDrawingCache(true); MemoryStream ms = new MemoryStream(); // Note anything less than 50 will result in very pixelated images from what I've seen bitmap.Compress(Android.Graphics.Bitmap.CompressFormat.Jpeg, 100, ms); // At this point set your Byte[] variable/property with ms.ToArray(); // for instance I have a SyncFile object with a FileData Property, so I use // SyncFile sFile = new SyncFile() { FileData = ms.ToArray(); }; [/csharp] Effectively this code captures a picture, puts it in an ImageView as a thumbnail on the Activity and then upon hitting your Upload Button it converts the image into a Byte Array after compressing it (or not like in my case) and from there call your WCF service upload function. Hopefully that helped someone out.
After some additional work getting used to the XAML-ish layout I'm done with the initial jcBENCH Android port. You can download it from here. You will need Android 2.2 or higher for it to run. [caption id="attachment_874" align="aligncenter" width="244" caption="jcBENCH Android"][/caption] I've only tested this on a Dual 1.2ghz HTC Vivid. However, the results were interesting. Comparing single-threaded and multi-threaded operations was curious. Running it in multi-threaded mode was actually 3 times slower. I'm not sure if the way the Task Parallel Library was implemented on Monodroid was done poorly or if there is a bug in the detection for how many cores/cpus there are inside the Mono implementation or not, but something isn't right. Single threaded versus my HTC Titan 1.5ghz SnapDragon it lost out by ~23%. Which makes sense, 300mhz difference or 20% comparing single cores to each other. All that being said I'm content with jcBENCH for the moment until I hear feedback or come up with more features to add.
Those that have seen an IIS 404 error on a file that is known to exist will know right off the bat, a lack of mime type. A quick trip to Google found it, but for posterity's sake: application/vnd.android.package-archive