Showing posts with label Xamarin. Show all posts
Showing posts with label Xamarin. Show all posts

Thursday, July 18, 2013

Using Intents in Xamarin to catch "Send to" and "Open with" file prompts

In Xamarin for Android you don't directly edit the AndroidManifest.xml file which means you need to create code that will generate the necessary portions of the manifest which direct your application to make itself available to handle incoming file hand-offs.  This is done using an IntentFilter which you place at the top of the class for the activity which you want to handle the incoming data.  In my case, I chose a neutral splashscreen as the loading activity so that the user will see my app's loading screen while I determine and load the true activity that will be handling the file.

namespace MyApp

{

 [Activity (Label="MyAppName", MainLauncher = true, Icon="@drawable/icon", Theme = "@style/ThemeBase.Splash", NoHistory = true)]

 [IntentFilter (new[]{Intent.ActionView},

 Categories=new[]{Intent.ActionDefault, Intent.CategoryBrowsable, Intent.ActionSend, Intent.ActionSendMultiple},

 DataScheme="mimetype",

 DataPathPattern="*/*",

 DataHost="*.*")]

 public class SplashActivity : Activity

 {

  protected override void OnCreate (Bundle bundle)

  {

   base.OnCreate (bundle);



   Intent intent = Intent;

   String action = intent.Action;

   String type = intent.Type;

   if (Intent.ActionSend.Equals(action) && type != null) {

    if (type.StartsWith("image/")) {

     handleSendImage(intent); // Handle single image being sent

    }

   } else if (Intent.ActionSendMultiple.Equals(action) && type != null) {

    if (type.StartsWith("image/")) {

     handleSendMultipleImages(intent); // Handle multiple images being sent

    }

   } 

   else

   {
    // Start our real activity if no acceptable file received

    StartActivity (typeof (MainActivity));

   }

  }

    }

}

The above code allows me to handle any filetype at all (DataHost="*.*") and will cause my application to appear as an option in the "Send" link of any other app.  If you only need to handle a specific filetype you would change the second * in DataHost to the filetype you need, such as (DataHost="*.png") would only handle PNG (Portable Network Graphics) files.  

In my case, since I am accepting all filetypes, I need to determine what type of file I was given and handle it appropriately.  You can see this occurring in the operations with the data derived from intent (intent, action, type), which is the incoming file details and requested action by the other app.  The action type gives a hint on what needs to be done with the file being sent (Send, Open, View, etc.) and the type tells you the MIME type information for the file, whether it's a PDF, image file, APK, MP3, webpage, etc.  If you aren't sure what file type you need to receive, set your DataHost to *.* then set a breakpoint, debug your app and inspect the intent.type after opening the desired file.

Sunday, June 16, 2013

Example of Deleting from SQLite DB using C# in Xamarin Android

I tried to use LINQ syntax to delete my objects from a table like shown here, but got an error "Cannot store type:  MyObject":

private static void DeleteOldObjects()
{
 string path = Path.Combine (System.Environment.GetFolderPath (System.Environment.SpecialFolder.MyDocuments), "MyDatabase.db");
 var db = new SQLiteConnection(path,password,false);
 var query = db.Table<MyObject>().Where(rt => rt.Date < DateTime.Now.AddDays(-3));

 if (query != null) {
  foreach (var object in query.ToList<MyObject>()) {
   db.Delete<MyObject>(object);
  }
 }
 db.Commit ();
}

From what I could determine by looking at the SQLite.cs code, it seems like this error is when it's trying to bind my object as a parameter:


internal static void BindParameter (IntPtr stmt, int index, object value)
{
  if (value == null) {
    SQLite3.BindNull (stmt, index);
  } else {
    if (value is Int32) {
      SQLite3.BindInt (stmt, index, (int)value);
    } else if (value is String) {
      SQLite3.BindText (stmt, index, (string)value, -1, NegativePointer);
    } else if (value is Byte || value is UInt16 || value is SByte || value is Int16) {
      SQLite3.BindInt (stmt, index, Convert.ToInt32 (value));
    } else if (value is Boolean) {
      SQLite3.BindInt (stmt, index, (bool)value ? 1 : 0);
    } else if (value is UInt32 || value is Int64) {
      SQLite3.BindInt64 (stmt, index, Convert.ToInt64 (value));
    } else if (value is Single || value is Double || value is Decimal) {
      SQLite3.BindDouble (stmt, index, Convert.ToDouble (value));
    } else if (value is DateTime) {
      SQLite3.BindText (stmt, index, ((DateTime)value).ToString ("yyyy-MM-dd HH:mm:ss"), -1, NegativePointer);
    } else if (value.GetType ().IsEnum) {
      SQLite3.BindInt (stmt, index, Convert.ToInt32 (value));
    } else if (value is byte[]) {
      SQLite3.BindBlob (stmt, index, (byte[])value, ((byte[])value).Length, NegativePointer);
    } else {
      throw new NotSupportedException ("Cannot store type: " + value.GetType ());
    }
  }
}

That seemed to me like the most intuitive way to perform that task since it's the same syntax used to insert objects, but since it didn't work I found you actually need to pass the primary key of the object you want to delete, like this:

private static void DeleteOldObjects()
{
 string path = Path.Combine (System.Environment.GetFolderPath (System.Environment.SpecialFolder.MyDocuments), "MyDatabase.db");
 var db = new SQLiteConnection(path,password,false);
 DateTime expireDate = DateTime.Now.AddDays(-3));
 var query = db.Table<MyObject>().Where(rt => rt.Date < expireDate );

 if (query != null) {
  foreach (var object in query.ToList<MyObject>()) {
   db.Delete<MyObject>(object.PrimaryKeyId);
  }
 }
 db.Commit ();
}

Saturday, June 15, 2013

Efficient Custom ListView Adapter Selections

A customer requested I create a ListView of their business objects using custom graphics and text based on the status of the object.  I had no problem creating it but they complained that it took too long to refresh when making selections.  After puzzling over the code for awhile trying to determine how to speed it up, I realized that the convertView paramter passed in to the GetView method that I was overriding in my custom listview adapter was actually the existing view of the object, and if it wasn't null I didn't have to recreate it.

So now in my code I check first and I only create the view from scratch if it's null.  Otherwise, I only modify the existing view to change the background color to signify that it has been selected.  I also store the two Drawables that are the backgrounds so they don't have to be retrieved and assigned memory for each object.  This allows the ListView to refresh quickly as it doesn't have to reacquire the underlying objects and rebuild the entire view based on the object's properties each time the selection is changed.  This seems like a simple thing, but maybe someone else that is struggling with ListView performance will happen across my post.

namespace Droid
{
 public class ListViewObjectAdapter : BaseAdapter<MyObject> {
  List<MyObject> items;
  public int selectedListItem = -1;
  Activity context;
  Drawable bgDefault;
  Drawable bgHighlight;

  public ListViewobjectAdapter(Activity context, List<MyObject> items)
   : base()
  {
   this.context = context;
   this.items = items;
   Drawable bgDefault = context.Resources.GetDrawable(Resource.Drawable.gray_button_focused);
   Drawable bgHighlight = context.Resources.GetDrawable(Resource.Drawable.gray_button_default);
  }

  public override long GetItemId(int position)
  {
   return position;
  }

  public void SetItems(List<MyObject> items)
  {
   this.items = items;
   this.NotifyDataSetInvalidated ();
  }

  public override MyObject this[int position]
  {
   get { return items[position]; }
  }

  public override int Count
  {
   get { return items.Count; }
  }

  public override View GetView(int position, View convertView, ViewGroup parent)
  {
   View view = convertView;

   if (view == null)
   {
    string SENT_PREFIX = context.Resources.GetString(Resource.String.sent_object_prefix);
    string UNSENT_PREFIX = context.Resources.GetString(Resource.String.unsent_object_prefix);

    MyObject item = items[position];
    Subobject subobject = Helper.GetSubobjectById (item.SubobjectId);

    view = context.LayoutInflater.Inflate (Resource.Layout.ListViewObjectItem, null);
    view.FindViewById<TextView> (Resource.Id.tvTitle).Text = Helper.GetInfoBySubOject (SubObject);

    if (item.Date.Date.Equals (DateTime.Now.Date))
     view.FindViewById<TextView> (Resource.Id.tvobjectId).Text = item.Date.ToShortTimeString ();
    else
     view.FindViewById<TextView> (Resource.Id.tvobjectId).Text = item.Date.ToShortDateString ();

    view.FindViewById<TextView> (Resource.Id.tvobjectIdText).Text = "";

    if (item.IsValid) {
     view.FindViewById<ImageView> (Resource.Id.Image2).SetImageResource (Resource.Drawable.icon_accept);
     view.FindViewById<TextView> (Resource.Id.tvDescription).Text = "Extra Info: " + Helper.GetAdditionalInfoByObjectId(item.MyObjectId);
    } else {
     view.FindViewById<ImageView> (Resource.Id.Image2).SetImageResource (Resource.Drawable.icon_reject);
     ValidSubobject SubobjectMeasure = Helper.GetValidSubObjectByObjectId (item.MyObjectId);
     view.FindViewById<TextView> (Resource.Id.tvDescription).Text = "MyInfo: " + SubobjectMeasure.Info.ToString () + ";
    }
   }
   RelativeLayout rlListViewItem = (RelativeLayout)view.FindViewById (Resource.Id.rlListViewItem);
   if(position == selectedListItem) {  
    rlListViewItem.SetBackgroundDrawable(bgHighlight);
   } else {
    rlListViewItem.SetBackgroundDrawable(bgDefault );
   }

   return view;
  }
 }
}

Monday, May 27, 2013

Print Hub Update.

  

 Spent a bit of time on making the interface better for Print Hub.  Have a ton of features that are.. "Developed", but can't quite be released yet.  Yeah, it's 3:00am in the morning.  Life is brutal.

Sometimes, I feel like Thulsa Doom, talking to my inner Conan.



Saturday, April 27, 2013

Gotta say, it's all about the App Store SEO.

I haven't been posting app figures, because they became abysmal. However, I think this release today will fix the course.  Also, did some upgrades on appearance, and had Jared help me out with some splash screens.  (Jared is awesome, he needs to do some posts on Android theming).



Pretty much have my next feature set lined up, along with the SEO tweaks for my next "attempt" at this brutal store environment.  The reason I can post this stuff, is because it takes so long to get your app approved.  See, I submitted my app last weekend.  So I have all week to make my next given set of features.  When the app is approved (I test pretty powerfully, so failure isn't really a big chance), then I have my next release ready.  I will play with the app tonight after the boys are in bed, and see if I can do anything more.. and then I'll submit. Anyways, time to give them a bath. See ya next post. : )

Tuesday, April 23, 2013

Creating Custom Overlays in Xzing Barcode Scanner using Xamarin Studio and C#



I've recently had need to customize the UI overlay of the excellent and free barcode scanning plugin Zxing.   While gathering material for this post I discovered that an example is provided of customizing the overlay via XML, but when I initially searched the first example I came across was the C# method - so that's the route I took.  The C# version did not have the ability to turn the flash on/off which was a feature I needed to access, so I figured out how to add that while styling.  I'm going to go over how I modified the example class created by Redth to help anyone else who might attempt the same thing for their own Android app.

For starters, you need to modify your call to Zxing to specify the use of a custom overlay:

var scanner = new ZXing.MobileMobileBarcodeScanner();
scanner.UseCustomOverlay = true;
myCustomOverlayInstance = new ZxingOverlayView(this, scanner);
scanner.CustomOverlay = myCustomOverlayInstance;
scanner.Scan().ContinueWith(t => { //Handle Result });

After that, you just need to customize the properties and methods of the ZxingOverlayView example class file.  In my example I added the ability to control the torch (flashlight) and display bitamaps so that I could have my own custom buttons.  I specified a default color and a pressed color, along with boolean flags so I could change the buttons to confirm to the user that they had pressed a button while waiting for a response:

namespace MyProject
{
 public class ZxingOverlayView : View 
 {
  private Paint defaultPaint;
  private Paint pressedPaint;
  private Android.Graphics.Bitmap resultBitmap;
  private Android.Graphics.Bitmap litTorchIcon;
                private Android.Graphics.Bitmap unlitTorchIcon;
  private Rect torchIconDimRect;
  private bool hasTorch = false;
  private bool torchOn = false;
  private bool cancelPressed = false;
  private bool problemPressed = false;
...
public ZxingOverlayView(Context context, MobileBarcodeScanner scanner) : base(context)
{
 this.context = context;
 this.scanner = scanner;
 
 SetDisplayValues ();
}
...
private void SetDisplayValues ()
{
 //Determine if device has flash/torch
 hasTorch = this.Context.PackageManager.HasSystemFeature (PackageManager.FeatureCameraFlash);
 if (hasTorch) {
  //Load button icons
  var metrics = Resources.DisplayMetrics;
  int iconHeight = metrics.HeightPixels * 2 / 9;
  int iconWidth = iconHeight * 7 / 10;
  torchIconDimRect = new Rect (0, 0, iconWidth, iconHeight);
  litTorchIcon = ImageHelper.DecodeSampledBitmapFromResource (Resources, Resource.Drawable.bulb_lit, iconWidth, iconHeight);
  unlitTorchIcon = ImageHelper.DecodeSampledBitmapFromResource (Resources, Resource.Drawable.bulb_unlit, iconWidth, iconHeight);
 }
 // Initialize these once for performance rather than calling them every time in onDraw()
 defaultPaint = new Paint (PaintFlags.AntiAlias);
 pressedPaint = new Paint (PaintFlags.AntiAlias);
 pressedPaint.Color = new Color (96, 97, 104);
 buttonFontColor = Color.White;

For each of my buttons I had to specify a rectangle on the screen.  It's best if you specify not in static pixels, but in percentage of the total screen available.  This will ensure your overlay renders the same on any size of screen.  I created three buttons, plus a rectangle to hold my torch icon bitmap.  Notice that the TorchIconDimRect was created as part of SetDisplayValues() above as we decoded and resized the bitmap icon for it at the same time:

Rect GetProblemButtonRect()
{
 
 var metrics = Resources.DisplayMetrics;
 int width = metrics.WidthPixels * 7 / 16 ;
 int height = metrics.HeightPixels * 2 / 9;
 int leftOffset = metrics.WidthPixels * 33 / 64;
 int topOffset = metrics.HeightPixels * 3 / 4;
 var problemRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
 
 return problemRect;
}

Rect GetCancelButtonRect()
{
 var metrics = Resources.DisplayMetrics;
 int width = metrics.WidthPixels * 7 / 16 ;
 int height = metrics.HeightPixels * 2 / 9;
 int leftOffset = metrics.WidthPixels / 22;
 int topOffset = metrics.HeightPixels * 3 / 4;
 var cancelRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
 
 return cancelRect;
}

Rect GetTorchIconDimRect()
{
 return torchIconDimRect;
}

Rect GetTorchIconRect()
{
 var metrics = Resources.DisplayMetrics;
 int height = metrics.HeightPixels / 8;
 int width = height * 7 / 10;
 int leftOffset = metrics.WidthPixels / 2 - ( width / 2);
 int topOffset = metrics.HeightPixels /18;
 var torchRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
 
 return torchRect;
}

Rect GetTorchButtonRect()
{
 var metrics = Resources.DisplayMetrics;
 int width = metrics.WidthPixels * 3 / 8 ;
 int height = metrics.HeightPixels * 3 / 16;
 int leftOffset = metrics.WidthPixels / 2 - (width / 2);
 int topOffset = metrics.HeightPixels / 64;
 var torchRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
 
 return torchRect;
}

Here is the ImageHelper class file which you will only need if you are using bitmaps on your overlay.  This helper class will resize your bitmap to the desired height to prevent image distortion:

internal static class ImageHelper
{
 public static int CalculateInSampleSize(BitmapFactoryOptions options, int reqWidth, int reqHeight)
 {
  // Raw height and width of image
  var height = (float)options.OutHeight;
  var width = (float)options.OutWidth;
  var inSampleSize = 1D;
  
  if (height > reqHeight || width > reqWidth)
  {
   inSampleSize = width > height
    ? height/reqHeight
     : width/reqWidth;
  }
  
  return (int) inSampleSize;
 }
 
 public static Bitmap DecodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight)
 {
  // First decode with inJustDecodeBounds=true to check dimensions
  var options = new BitmapFactoryOptions { InJustDecodeBounds = true };
  BitmapFactory.DecodeResource(res, resId, options); 
  
  // Calculate inSampleSize
  options.InSampleSize = CalculateInSampleSize(options, reqWidth, reqHeight);
  
  // Decode bitmap with inSampleSize set
  options.InJustDecodeBounds = false;
   Bitmap optimalSize = BitmapFactory.DecodeResource (res, resId, options);
   return Bitmap.CreateScaledBitmap (optimalSize, reqWidth, reqHeight, false);
 }
}

So now that all the colors, shapes and bitmaps have been defined you just need to draw them to the screen.  This is done through the OnDraw() method:

protected override void OnDraw (Canvas canvas)
{
 var scale = Resources.DisplayMetrics.Density;
 
 var frame = GetFramingRect();
 if (frame == null)
  return;
 
 var probBtn = GetProblemButtonRect();
 var cancelBtn = GetCancelButtonRect();
 var torchBtn = GetTorchButtonRect();
 
 var width = canvas.Width;
 var height = canvas.Height;
 var textPaint = new TextPaint();
 textPaint.Color = buttonFontColor;
 textPaint.AntiAlias = true;
 textPaint.BgColor = Color.Gray;
 textPaint.TextSize = 16 * scale;
 
 //Draw mask
 defaultPaint.Color = resultBitmap != null ? resultColor : maskColor;
 defaultPaint.Alpha = 245;
 canvas.DrawRect(0, 0, width, frame.Top, defaultPaint);
 canvas.DrawRect(0, frame.Bottom + 1, width, height, defaultPaint);
 
 //Draw button outlines
 defaultPaint.Color = buttonFontColor;
 defaultPaint.Alpha = 255;
 pressedPaint.Color = Color.Black;
 canvas.DrawRect (probBtn.Left+1, probBtn.Top +1, probBtn.Right + 1, probBtn.Bottom + 1, problemPressed ? pressedPaint : defaultPaint);
 canvas.DrawRect (cancelBtn.Left+1, cancelBtn.Top +1, cancelBtn.Right + 1, cancelBtn.Bottom + 1, cancelPressed ? pressedPaint : defaultPaint);
 if (hasTorch)
  canvas.DrawRect (torchBtn.Left + 1, torchBtn.Top + 1, torchBtn.Right + 1, torchBtn.Bottom + 1, torchOn ? pressedPaint : defaultPaint);
 
 //Draw buttons
 defaultPaint.Color = buttonColor;
 defaultPaint.Alpha = 255;
 pressedPaint.Color = new Color(96, 97, 104);
 canvas.DrawRect (probBtn, problemPressed ? pressedPaint : defaultPaint);
 canvas.DrawRect (cancelBtn, cancelPressed ? pressedPaint : defaultPaint);
 if (hasTorch)
 {
  canvas.DrawRect (torchBtn, torchOn ? pressedPaint : defaultPaint);
  //Draw button icons
  canvas.DrawBitmap ((torchOn ? litTorchIcon : unlitTorchIcon), GetTorchIconDimRect(), GetTorchIconRect(), defaultPaint);
 }
 
 //Draw button text
 var btnText = new StaticLayout("Scan problems?", textPaint, probBtn.Width(), Android.Text.Layout.Alignment.AlignCenter, 1.0f, 0.0f, false);
 canvas.Save();
 canvas.Translate(probBtn.Left, probBtn.Top + (probBtn.Height ()/3)+ (btnText.Height / 2));
 btnText.Draw(canvas);
 canvas.Restore();
 btnText = new StaticLayout("Cancel Scan", textPaint, cancelBtn.Width(), Android.Text.Layout.Alignment.AlignCenter, 1.0f, 0.0f, false);
 canvas.Save();
 canvas.Translate(cancelBtn.Left, cancelBtn.Top + (cancelBtn.Height ()/3) + (btnText.Height / 2));
 btnText.Draw(canvas);
 canvas.Restore();

If your buttons are pressed, you can capture that event by overriding the OnTouchEvent method.  Notice that in each button touch event I call this.Invalidate().  This call causes the screen to refresh and without it the OnDraw() method would not be invoked, and the screen would not reflect our buttons change in display when pressed.

public override bool OnTouchEvent(MotionEvent me)
{
 if (me.Action == MotionEventActions.Down)
 {
  if (GetCancelButtonRect().Contains((int)me.RawX, (int)me.RawY))
  {
   cancelPressed = true;
   this.Invalidate();
   OnUnload();
   scanner.Cancel();
  }
  else if (GetTorchButtonRect().Contains ((int)me.RawX, (int)me.RawY))
  {
   scanner.ToggleTorch();
   torchOn = !torchOn;
   this.Invalidate();
  }
  else if (GetProblemButtonRect().Contains ((int)me.RawX, (int)me.RawY))
  {
   problemPressed = true;
   this.Invalidate();
   
   if (parentActivity == null)
   {
    Intent intent = new Intent();
    intent.SetClass(context, typeof(ManualEntryActivity));
    context.StartActivity(intent);
   }
   else
   {
    parentActivity.GetManualEntry();
   }
   OnUnload();
   scanner.Cancel();
  }
  return true;
 }
 else
  return false;
}

Lastly, I read on a stackoverflow post that graphics and bitmaps are two objects which you must take care to properly dispose of when they are no longer needed  If you don't properly dispose of the bitmaps created for your custom overlay then there is a potential for a memory leak.  I dispose of my bitmaps by calling this OnUnload() method that I use at all points of exit:

private void OnUnload()
{
 if (hasTorch)
 {
  litTorchIcon.Dispose();
  unlitTorchIcon.Dispose();
 }
}

This is how my custom overlay turned out.  (Ignore the black & white checkerboard with green square which is just a test display for the android emulator's camera)


Hopefully my post helped you.  Feel free to post questions if you are having problems, or need an explanation on any of my code.

Wednesday, April 10, 2013

Google Cloud Print Component is now live.

Victory dance!

EVOLVE CONFERENCE!!!!1111!!!!

Looks like I'm headed to Evolve.  The Xamarin Conference.

I'm excited.  I think I only got the free pass, because I threatened to camp outside the conference rooms. : )

I had a plane ticket.. because I had to pay for it from a previous employer.  I will end up staying in a hostel, because the budget is tight.

I am happy. Things are going well at work, and I'll have quite a few use cases to finish to go to this conference, but to be honest.. I know even right now.. that it won't get in my way.  This person I am now, isn't the same person that was around even 4-5 months ago.  I don't know whether to feel bad about that, or to enjoy it.  My obligation is the same as it always was, I just feel differently about the weight of it.  I now do what I do, for the enjoyment of it, not because it must be done.

This conference was everything I wanted.  Very grateful right now.


Saturday, March 30, 2013

Print Hub Feature upgrade. Thoughts about Search Terms for apps.


I added Social Sharing for Twitter, Facebook, and Flickr for image file types today.  Didn't take long using Xamarin.Social.   I'll probably add a lot more every couple weeks.  Build my code up for integration and then spend a couple hours actually doing it.


I realized what my problem was.. on my app.  I had a very very weak search term base.  So, I opened it up this for this next upcoming release to a much wider set of terms.  This might end up being something I have to experiment with in order to get to the right place.  You only have 100 characters to use in your terms for your application.  Knowing what words to use is probably an entire industry in this microcosm.

In a lot of ways I get to experiment here.

Wednesday, March 27, 2013

Reflections.



Currently, I'm on a free trial of "Appfigures.com".

So in 6 days, without any app marketing, I've gotten $8.23. 

Think here soon, I might have some 0 download days if I don't start getting aggressive.

I'm waiting on a Review for my next deployment.  Only added Printer Sharing.  This weekend, should add at least 3-4 new features, if I want to get serious, before I start going to app review sites, etc.  

Frankly, if I really want to get serious, I should just build a new more "useful" app.  That incorporates the google cloud printing functionality.  I have the cash currently to get myself quite a few useful components from the store.  I could make a real business application.  

I've talked with a lot of people about this, and it seems I'm almost at a kind of impasse.  It might be time to get Unity3D.  I have enough cash from side projects, to make a gaming studio.  I have the dedication to advance my skill set in short periods of time.  If you look, I haven't been coding in Xamarin that long.   Honestly, in a lot of ways, I don't have to do anything more, I have enough right now.  I have a permanent position that takes care of my needs.  I have Kelly (Yeah, I have a girlfriend), and really, that makes me for the most part happy.  What I guess I'm looking for now, is pretty simple really.  I just want to grow.  I want to feel like I'm not just wasting oxygen until I retire.  

Anyways folk.  Just another post of a small time mobile app developer.  -smiles-  

Saturday, January 19, 2013

Login for Mono Touch.


So folks.  Looks like making good code still has some worth.  Ipad / Iphone app, with Login functionality now.  This code is placed in the AppDelegate.cs in Mono Touch for the interface on app start.


            RootElement re = new RootElement("Login");
            Section creds = new Section("Credentials");
            Section welcome = new Section("Welcome to Youth Impact!");
            UIImageView ie;
            if(UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone) ie = new UIImageView(UIImage.FromBundle("resized.png"));
            else ie = new UIImageView(UIImage.FromBundle("small2.png"));
            welcome.Add(ie);
            login = new EntryElement("Login","Enter your Email", "");
            password = new EntryElement("Password","","",true);

            creds.Add(login);
            creds.Add(password);
            Section button = new Section();
            button.Add(new StringElement("Sign In",delegate { Validate();}));

            re.Add(welcome);
            re.Add(creds);
            re.Add(button);

            window = new UIWindow (UIScreen.MainScreen.Bounds);
            DialogViewController dialog = new DialogViewController(re);


            window.RootViewController = new DialogViewController(re);

I only put in a bit of logic for swapping the image out for IPhone / Ipad.  There is some code to do for when the app shifts Orientation.  As your properly sized image needs to be replaced with an image with the proper width / height due to the orientation change.

Using that if(UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone), should provide you the ability to handle that.. and maybe I'll just update this post later.

In the Validate method, I check the two Entries, one for password, and one for Login.. and use my web service call to validate the user.. if the response comes back as valid credentials, then I load the default ViewController that was generated when you create a "Universal" iphone / ipad app in Mono Touch.

Most of this code was taken as ill-gotten gains from this great recipe on Xamarin:

Xamarin Login Window Recipe.


Friday, January 18, 2013

Monotouch Development.


Yeah, if you've been here because of my links, you'll notice that the title of the blog changed.

Mobile Development.  Started working a bit in Mono Touch.

The great thing about working in Xamarin, is that you can re-use almost all your data access, if you started in Android.

I imported my model classes.  I imported my service call methods.



Made a nice little MasterViewController, and a DetailView where I could render custom data from the data made in my calls. Sorry, I had to blur the names.. because those kids don't deserve to have some stupid developer expose the fact that they are in a program at an address that can be found pretty easily.

Creating this app, took about 30 minutes.   (I had to read a little).  I can actually say nowadays, that my new personality is stronger / faster / happier, than I can easily explain and I'm going to take advantage of that.





Monday, January 14, 2013

Preferences in Monodroid.

Jared, a coder that's helping me out sometimes, went and found this gem.

Been trying to get him to post on here, but instead I'll post his code that he dug up for me.

Had to tweak what he put in, to work a bit cleaner in the app, but it was great research done,
and I really needed it for a deployment about a week ago.

            ISharedPreferences prefs = GetPreferences (FileCreationMode.Append);
            ISharedPreferencesEditor editor = prefs.Edit ();
            editor.PutString ("LoginName", creds);
            editor.Commit ();

This code will let you pretty much append anything you need via code into your preferences.

You just need to put in your string for the preference name.. and the value.  You can, of course, change the type a bit there in that editor variable.

User Management for Mobile Worlds.

Simple App Management Model.

I always like to start things out simply.  So, I've been working on this User Management Service, for mobile applications.  There are some columns missing.  Like LastLogin on the User.. etc.  Probably some tables for Application, if I were building an auto-updating Mobile Application service.  *coughs* Don't really want to get too much into the things I've left out on here at points.

The great thing about cloud work, is that you have no infrastructure.  I've seen a whole pile of nerds go gabby over how many servers etc that they manage, but once you commit capital to those resources, in a lot of ways it's like buying a new car.. just driving them off the lot, you lose value.  Not even that, if you have capital for those assets, then even worse from a business aspect, you have to have nerds to take care of that new ferrari server you've got parked in that rack.  That rack probably has AC cooling.  Why do the rack if you aren't going to cool your hardware off and risk component damage?  Then you need a locked room.  Not a great idea to have a ferrari, if you can't stop who takes it for a spin, right?  That's the problem with infrastructure, it starts to own you.

By staying up in the cloud, my servers get cheaper, the more competition there is for pricing, which happens pretty dang often (Thank you microsoft and amazon for being in a world domination tour, oh, Amazon is winning, MS, you better start making stuff as cheap as the competition, or you'll find that only C# sharp survives).

I'm going to throw some examples up here for components. I frequently use :

SendGrid.  Great service in Azure.  It's pretty much an add-in for your Azure account, and once you add that service to your account, you'll have the credentials to send your emails for your applications.

            SendGrid myMessage = SendGrid.GenerateInstance();
            myMessage.AddTo(u.UserEmail);
            myMessage.From = new System.Net.Mail.MailAddress("youremail", "youremaildisplayname");
            myMessage.Subject = "Welcome to {System}";
            string greeting = string.Format("Hello, {0}", u.FirstName);

            myMessage.Text = greeting + "\r\n" + "We are glad to have you in {System}.";

            // Create credentials, specifying your user name and password.
            var credentials = new NetworkCredential("credentialsgiveninsignupprocess", "");

            // Create an REST transport for sending email.
            var transportREST = SendGridMail.Transport.SMTP.GenerateInstance(credentials);

            // Send the email.
            transportREST.Deliver(myMessage);

Next comes to security.  I can't afford to have passwords in my account management system.  I can afford a salt and a hash.  So, here is the code for that.

        private static byte[] Hash(string value, string salt)
        {
            return Hash(Encoding.UTF8.GetBytes(value), Encoding.UTF8.GetBytes(salt));
        }

       private static byte[] Hash(byte[] value, byte[] salt)
        {
            byte[] saltedValue = value.Concat(salt).ToArray();
            
            return new SHA256Managed().ComputeHash(saltedValue);
        }

Oh, the return on that SHA-256, I just saved as varbinary (32).  I'm sure there are many different types you could use, but I was up at 1am in the morning, and when I finally got it working properly, I just called it quits for the night.

Two more simple utilities that I've found necessary, and are working quite well for me.  Remember to post on https folks.


Sunday, December 23, 2012

Simple Mono Droid Entry point for new features.


One of the things I've needed, in order to create a rapid development environment, is an entry point that is extensible.    Using this setup, I was able to easily throw in new features at a running pace.


public static class Selector
    {
        public static void Selected (string component,Activity act,int Id)
        {
            switch (component) 
            {
                case "Participant List":
                    var intent = new Intent();
                    intent.SetClass(act, typeof (ParticipantListActivity));
                    intent.PutExtra("Type","");
                    intent.PutExtra("Id","");
                    act.StartActivity(intent);
                break;
                case "Child Detail":
                    var childintent = new Intent();
                    childintent.SetClass(act, typeof (ChildDetailsActivity));
                    childintent.PutExtra("currentChildId",Id);
                    act.StartActivity(childintent);
                break;
                case "Parent List":
                    var parentintent = new Intent();
                    parentintent.SetClass(act, typeof (ParentListActivity));
                    act.StartActivity(parentintent);
                break;
                case "Scanner":
                var scannerintent = new Intent();
                scannerintent.SetClass(act,typeof(ScannerActivity));
                act.StartActivity(scannerintent);
                break;
                case "School List":
                    var schoolintent = new Intent();
                    schoolintent.SetClass(act,typeof(SchoolListActivity));
                    act.StartActivity (schoolintent);
                break;
                case "Kiosk":
                var kioskintent = new Intent();
                kioskintent.SetClass(act,typeof(LocationListActivity));
                act.StartActivity(kioskintent);
                break;
                default:
                break;


            }
        }
    }


public class Main : ListActivity
    {
        ProgressDialog progress;

        string[] Entries = { "Participant List","Parent List","Scanner","Kiosk"};

        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);
            SetContentView (Resource.Layout.TextViewItem);

            this.ListAdapter = new ArrayAdapter<string>(this,Android.Resource.Layout.SimpleListItem1,Entries);

        }

        protected override void OnStart ()
        {
            base.OnStart ();
        }

        protected override void OnResume ()
        {
            base.OnResume();
        }

        protected override void OnListItemClick (ListView l, View v, int position, long id)
        {

            string place = ((ArrayAdapter<string>)this.ListAdapter).GetItem(position);
        
            Selector.Selected(place,this,0);
        }
    }

Rest Sharp MonoDroid, Post in Body.

   I needed to add an item in the body of a post via RestSharp in Mono Droid.  Luckily, the way I've built things, doesn't really expose any endpoints via code, for this reference.  So here is the code.. if you want to know how to post an object in the body of a Rest Sharp request.

public static Credentials Login(Credentials credentials)
        {
            var client = new RestClient();
            var request = new RestRequest();
            request.Method = Method.POST;
            var json = JsonConvert.SerializeObject(credentials);
            request.AddParameter("application/json; charset=utf-8", json, ParameterType.RequestBody);
            request.Resource = ServiceBase+string.Format(Data.Service.Login);

            RestResponse<Credentials> response = (RestResponse<Credentials>)client.Execute<Credentials>(request);
            Credentials item = new Credentials();
            JsonConvert.PopulateObject(response.Content,item);
            return item;
        }

Pretty simple, yes? -smiles-

On Boot Receiver in MonoDroid.



Sometimes your samples, for the technology you are using don't have a great example for what you need to accomplish.

Here is a working example for a class that uses a BroadcastReceiver to receive the On Boot Completed Event, and then start an Activity.

Get into your solution.  Right click on your Project, select Options. Go to Mono for Android Applications :



This is your class. Feel free to tweak the Intent to your own Activity class that you wish to start.

    [BroadcastReceiver] 
    [IntentFilter(new string[] { Intent.ActionBootCompleted }, Priority = (int)IntentFilterPriority.HighPriority)]
    public class BootBroadcastReceiver : BroadcastReceiver {

        public override void OnReceive(Context context, Intent intent) {
            Intent startServiceIntent = new Intent();

            startServiceIntent.SetClass(context, typeof(Login));
            startServiceIntent.AddFlags(ActivityFlags.NewTask);
            context.StartActivity(startServiceIntent);
        }
    }

I thought I needed to modify the AndroidManifest.xml.  Boy, was that wrong.  Just use the Attributes.  They will make your broadcast receiver automatically respond to the event.

A good link to check out. Blue Stacks. Android on PC and Mac.

Friday, December 21, 2012

Some cross platform projects for Mono Develop.

I have to be careful with this blog, as it is labeled Android Development, however, I have made an application that works for both Android and IOS.  Now, keep in mind, you won't get all the features in Xamarin from this project in comparison to their Mono Droid / Mono Touch sdk's, but it does provide enough to make real applications.  MVC Style.

The Monocross Project

What I have found is, the best way to implement this sweet layer, is to make sure that your web services are truly restful.  If you are in .net land, and I assume you are, this means RIA Web Services, or the new .net 4.5 API, which is supported in Azure.. with the October 2012 Azure SDK.

In order to utilize this tool, I'll have to do some extensive reworking on my web service side.

I've already planned on doing it, but it will be delayed a little bit, due to side projects currently ongoing.

I've also looked at Cross platform Mobile Game Development environment.  Now, the real winner in this arena is Unity. Hands down.  They have the gear, and the right environment for full game development, but that comes at an expensive price tag.  A lot of people like doing homebrew in the XNA platform.  Currently, Mono Game.. supports 2D games.  It's working up for 3D games, but for my purposes.. Mono Game.. being free and all, works well enough to get my feet wet.  So I've been playing around there.

The Mono Game Project.

Thursday, December 20, 2012

Useful Mono Droid Snippets.


Nowdays, everybody loves JSON.  Truth is.. I feel it is much easier to use in some regards for Web, and Mobile projects than XML, but there is something to be said for both data formats.

This is a snippet for retrieving any web response in JSON, via Rest Sharp in a Mono Droid, or Mono Touch environment, that you can then parse with your JSON Deserializer (Whatever flavor you prefer, hopefully one that supports AsParallel()).

This isn't the code I am using anymore.  As the first security layer is in place.  Below I have a post semi-related to the 2nd security layer, which is semi in-progress.. involving X509 certificates.

I also have made a model for a web service that will provide all User Application management functions for all mobile applications that I'll be developing.  I prefer the cloud.  It's cheap, I don't need anyone other than myself.  (Even though I'm a pretty decent sys admin).

        private static RestClient CutDownBloat()
        {
            var client = new RestClient();
            client.AddHandler("application/json; charset=utf-8",new RestSharp.Deserializers.JsonDeserializer());
            return client;
        }
        private static RestResponse<Object> CutDownCode(string url)
        {
            var request = new RestRequest();
            request.Method = Method.GET;
            request.Resource = url;
            var client = CutDownBloat();
            RestResponse<Object> response = (RestResponse<Object>)client.Execute<Object>(request);
            return response;
        }


In order to make a true secure system for a mobile application, you need a unique ID for the device attempting to access your services.

Just getting a unique device ID is a key component.


This is a snippet that will return a Unique Device ID for Android devices.


public static class DeviceData
    {
        public static string getDeviceID(Context context)
        {
            TelephonyManager tm = (TelephonyManager) context.GetSystemService(Context.TelephonyService);
            return tm.DeviceId;
        }
    }