Saturday, October 19, 2013

Azure Deployments.

Eventually, a project makes it to End Game.. as we call it.


You start having customers.  Right? If you've been working in Azure, that means, you'll need at least a few things.

#1).  You'll need an "A Record" in DNS.. pointing to your azure deployment url's IP.  This will make your site.. resolve to the IP address for your load balancer.

#2) You'll need to make a CName record, for "www".  So that www.yourdomaingoeshere.com will resolve for your customers.  Use your azure production deployment URL.

#3), You'll need to get your https certificate.  Make sure to import it, with the private key.. and then export it back out.  Upload that cert to your azure deployment.  Attach it in your project via the screen shots above.. by right clicking on your web role.

Very quickly, you'll realize: Cloud work is just like regular development.  There isn't any magic here.




Thursday, September 12, 2013

Creating and using sliding menus in Xamarin.Android

I needed a stylish way to navigate menu options in my app and by piecing together different examples from documentation and online forums I was able to get my menu to slide forward when traversing deeper into my menus, and slide backwards when backing up.

In my Menu layout I specify a ViewFlipper as the parent view, and then underneath that I list all of the views I'll be sliding between.  I've used TableLayouts as my child views since I think they work well for buttons, but you can use LinearLayouts or whatever you prefer.  Make sure you give each view a unique ID and then place the file in the Resources\layout folder of your project.

MySlidingMenu.axml:
<?xml version="1.0" encoding="utf-8"?>
<ViewFlipper xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/viewFlipper"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <TableLayout
  android:id="@+id/tlMainMenu"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
  <Button
   android:id="@+id/btnSubmenu1"
   android:text="To Submenu1"
   android:minWidth="25px"
   android:minHeight="25px"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content" />
  <Button
   android:id="@+id/btnSubmenu2"
   android:text="To Submenu2"
   android:minWidth="25px"
   android:minHeight="25px"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content" />
 </TableLayout>
 <TableLayout
  android:id="@+id/tlSubmenu1"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
  <Button
   android:id="@+id/btnAction1"
   android:text="Action One"
   android:minWidth="25px"
   android:minHeight="25px"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content" />
  <Button
   android:id="@+id/btnCancel1"
   android:text="Cancel"
   android:minWidth="25px"
   android:minHeight="25px"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content" />
 </TableLayout>
 <TableLayout
  android:id="@+id/tlSubmenu2"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
  <Button
   android:id="@+id/btnAction2"
   android:text="Action Two"
   android:minWidth="25px"
   android:minHeight="25px"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content" />
  <Button
   android:id="@+id/btnSubSubmenu"
   android:text="To Sub-Submenu"
   android:minWidth="25px"
   android:minHeight="25px"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content" />
  <Button
   android:id="@+id/btnCancel2"
   android:text="Cancel"
   android:minWidth="25px"
   android:minHeight="25px"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content" />
 </TableLayout>
 <TableLayout
  android:id="@+id/tlSubSubmenu"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
  <Button
   android:id="@+id/btnAction3"
   android:text="Action Three"
   android:minWidth="25px"
   android:minHeight="25px"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content" />
  <Button
   android:id="@+id/btnCancel3"
   android:text="Cancel"
   android:minWidth="25px"
   android:minHeight="25px"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content" />
 </TableLayout>
</ViewFlipper>
Next, you'll need four animation XML files that tell the screen how to transition.  Create these four files and then place them in the Resources\anim\ folder in your project.  You will probably need to create the anim folder if it doesn't already exist.

slide_in_left.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
 <translate android:fromXDelta="-50%p" android:toXDelta="0"
            android:duration="@android:integer/config_mediumAnimTime"/>
 <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>
slide_in_right.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
 <translate android:fromXDelta="50%p" android:toXDelta="0"
            android:duration="@android:integer/config_mediumAnimTime"/>
 <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>
slide_out_left.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
 <translate android:fromXDelta="0" android:toXDelta="-50%p"
            android:duration="@android:integer/config_mediumAnimTime"/>
 <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>
slide_out_right.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
 <translate android:fromXDelta="0" android:toXDelta="50%p"
            android:duration="@android:integer/config_mediumAnimTime"/>
 <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>
Now you have all of the XML files, the last thing you need is the code added to your activity.  I suggest declaring the variables that hold the ViewFlipper, Views and Buttons at the top of your Activity like so:
private ViewFlipper vf;
private TableLayout tlMainMenu; 
private TableLayout tlSubmenu1; 
private TableLayout tlSubmenu2;
private TableLayout tlSubSubmenu;
private Button btnSubmenu1;
private Button btnSubmenu2;
private Button btnSubSubmenu;
private Button btnCancel1;
private Button btnCancel2;
private Button btnCancel3;
I didn't include the Action buttons because those are just placeholders for whatever it is you want to display on your own menu so I don't need to show you how to configure those.  Next, the following goes in your OnCreate method:
SetContentView (Resource.Layout.MySlidingMenu);

vf = FindViewById<ViewFlipper> (Resource.Id.viewFlipper);
tlMainMenu = FindViewById<TableLayout> (Resource.Id.tlMainMenu);
tlSubmenu1 = FindViewById<TableLayout> (Resource.Id.tlSubmenu1);
tlSubmenu2 = FindViewById<TableLayout> (Resource.Id.tlSubmenu2);
tlSubSubmenu = FindViewById<TableLayout> (Resource.Id.tlSubSubmenu);
btnSubmenu1 = FindViewById<Button> (Resource.Id.btnSubmenu1);
btnSubmenu2 = FindViewById<Button> (Resource.Id.btnSubmenu2);
btnSubSubmenu = FindViewById<Button> (Resource.Id.btnSubSubmenu);
btnCancel1 = FindViewById<Button> (Resource.Id.btnCancel1);
btnCancel2 = FindViewById<Button> (Resource.Id.btnCancel2);
btnCancel3 = FindViewById<Button> (Resource.Id.btnCancel3);

btnSubmenu1.Click += delegate {
 vf.SetInAnimation(this, Resource.Animation.slide_in_right);
 vf.SetOutAnimation(this, Resource.Animation.slide_out_left);
 vf.DisplayedChild = vf.IndexOfChild(tlSubmenu1);
};
btnSubmenu2.Click += delegate {
 vf.SetInAnimation(this, Resource.Animation.slide_in_right);
 vf.SetOutAnimation(this, Resource.Animation.slide_out_left);
 vf.DisplayedChild = vf.IndexOfChild(tlSubmenu2);
};
btnSubmenu3.Click += delegate {
 vf.SetInAnimation(this, Resource.Animation.slide_in_right);
 vf.SetOutAnimation(this, Resource.Animation.slide_out_left);
 vf.DisplayedChild = vf.IndexOfChild(tlSubmenu3);
};
btnSubSubmenu.Click += delegate {
 vf.SetInAnimation(this, Resource.Animation.slide_in_right);
 vf.SetOutAnimation(this, Resource.Animation.slide_out_left);
 vf.DisplayedChild = vf.IndexOfChild(tlSubSubmenu);
};
btnCancel1.Click += delegate {
 vf.SetInAnimation(this, Resource.Animation.slide_in_left);
 vf.SetOutAnimation(this, Resource.Animation.slide_out_right);
 vf.DisplayedChild = vf.IndexOfChild(tlMainMenu);
};
btnCancel2.Click += delegate {
 vf.SetInAnimation(this, Resource.Animation.slide_in_left);
 vf.SetOutAnimation(this, Resource.Animation.slide_out_right);
 vf.DisplayedChild = vf.IndexOfChild(tlMainMenu);
};
btnCancel3.Click += delegate {
 vf.SetInAnimation(this, Resource.Animation.slide_in_left);
 vf.SetOutAnimation(this, Resource.Animation.slide_out_right);
 vf.DisplayedChild = vf.IndexOfChild(tlSubmenu2);
};
Notice that the submenu buttons all have an InAnimation of slide_in_right and an OutAnimation of slide_out_left, while the cancel buttons all have an InAnimation of slide_in_left and an OutAnimation of slide_out_right.  This gives the illusion that submenus are further to the right, and your parents menus are to the left via the sliding animation.

Lastly, you'll want to add support for using the back button to navigate your menus.  Since the back button should do something different based on where you are at on the menu I suggest using the following method to capture the use of the back key, determine where you are and simulate the click of the cancel/back button on that portion of the menu.  Also, this is the reason for declaring the ViewFinder/Views/Buttons outside of the OnCreate method, because if we declared them locally we'd have to re-declare them for this method:
public override bool OnKeyDown (AndroidViewsKeycode keyCode, AndroidViewsKeyEvent e)
{
 if (keyCode == Keycode.Back) {
  if (vf.DisplayedChild == vf.IndexOfChild (tlSubmenu2))
   btnCancel1.PerformClick ();
  else if (vf.DisplayedChild == vf.IndexOfChild (tlSubmenu3))
   btnCancel2.PerformClick ();
  else if (vf.DisplayedChild == vf.IndexOfChild (tlSubSubmenu))
   btnCancel3.PerformClick ();
  return true;
 }
 else
  return base.OnKeyDown (keyCode, e);
}
That's it!  You now have everything you need to create the illusion of sliding menus, and the ability to traverse them at will.  Please leave me a comment if this was helpful for you, or if you have any questions.  Thank you!

Saturday, August 3, 2013

Print Hub Sales.


This week I've been ranking pretty regularly on iPad sales, and a bit on iPhone. Not a high rank, obviously.

Jared is saying he will make a support web site.  Since, I've been pretty bad on support for the app, and we are making an Android version.

At least 3/4th's of the issues keeping the app from the Supported Apps list should be gone now, and I'm hoping to get listed soon.

Today, I'm hoping to get the "basic" versus "advanced" printing capability in.

Anyways, enough of me being crazy or posting.  Gotta get to "work"




The evidence of how rough it is on the ITunes store.  Keep this in mind, even if you have a great app, you are still dependent on search terms in iTunes.  I'm not claiming my app is even great.

How many "sales" does it take to rank on iPad? I don' t know.  I just know that the threshold is a lot lower than ranking in iPhone.  I've shown up on the iPad ranking, a number of times.  iPhone? Meh.   App Annie provided these graphs, and would give me more graphs, if I was interested in paying a large amount of money per year, to get real intelligence on the store environment. (Sorry App Annie, I can't yet, I'm still making coffee money from my IOS App).

Sunday, July 28, 2013

Grid Based Movement in Unity

If you have played old school games like Dungeon Master, Eye of the Beholder, the early Lands of Lore and Wizardry series or even more recent games like Legend of Grimrock, then you know what Grid Based Movement is.    This is my implementation of grid based movement using Grid Framework by HiPhish.  Feel free to use your own grid system.

See script in action

Setup a scene and if you are using Grid Framework create a new grid.
Add an empty gameobject to represent the player.  I also make the camera a child of this object and set the camera position to 0,0,0 so it is always looking forward from the centre of the player.

Add this script to the player object.  If you are not using Grid Framework, you will need to change/remove the GFGrid variable and the first line in the awake method.  All this line currently does is move the player to 0,0,0.  In a later post the grid will be used to determine if a move is valid or not.  You will also need to either create the inputs I have specified in the script or update the script to match your own.  I use w,s,a,d for forwards, backward, stepleft, stepright and q and e for turning.

public GFGrid Grid;//Grid the Player is attached to.
public float StepSpeed = 0.5f; //how fast in seconds each step or turn takes to complete
public Vector3 CurrentGridPosition = new Vector3(0,0,0);  //3d position in Grid
public string CurrentDirection; //Direction Player is facing (n,s,e,w)

float timer = 0; //used to disable turn left and turn right inputs when player is already turning
bool enableRotation = true; //used to disable turn left and turn right inputs when player is already turning
Vector3 intendedPosition;//Before player is moved, the position the player will end up at is stored here
//Is used to check that the move is valid and also used to disable move inputs
//when player is already moving

void Awake()
{
this.transform.position = Grid.GridToWorld(CurrentGridPosition); //move player to default position/grid origin
intendedPosition = CurrentGridPosition; //no movement has occured yet, so intended position is set to current position
CurrentDirection = "n"; //TODO: default direction is calculated from CurrentGridPosition.
}

void Start()
{
//sets timer to match time it takes to make one step or turn
timer = StepSpeed; 
}

public void MoveTo(Vector3 position)
{
//Move Player to position over time
LeanTween.move(gameObject, position, StepSpeed);
}

public void TurnPlayer(Vector3 position)
{
//Turn Player to new rotation over time
LeanTween.rotate(gameObject, position, StepSpeed);

}

#region Movement

public void MoveForward()
{
// calculate intended position. Get current direction and add one step forward
switch(CurrentDirection.ToLower())
{
case "n":
default:
{
intendedPosition = CurrentGridPosition + new Vector3(0,0,1);
break;
}
case "e":
{
intendedPosition = CurrentGridPosition + new Vector3(1,0,0);
break;
}
case "s":
{
intendedPosition = CurrentGridPosition + new Vector3(0,0,-1);
break;
}
case "w":
{
intendedPosition = CurrentGridPosition + new Vector3(-1,0,0);
break;
}
}

//TODO: Check move is valid, if not, break
MoveTo(Grid.GridToWorld(intendedPosition)); //Actually move player
CurrentGridPosition = intendedPosition; //Update CurrentGridPosition
}

public void MoveBackward()
{
// calculate intended position. Get current direction and add one step backward
switch(CurrentDirection.ToLower())
{
case "n":
default:
{
intendedPosition = CurrentGridPosition + new Vector3(0,0,-1);
break;
}
case "e":
{
intendedPosition = CurrentGridPosition + new Vector3(-1,0,0);
break;
}
case "s":
{
intendedPosition = CurrentGridPosition + new Vector3(0,0,1);
break;
}
case "w":
{
intendedPosition = CurrentGridPosition + new Vector3(1,0,0);
break;
}
}
//TODO: Check move is valid
MoveTo(Grid.GridToWorld(intendedPosition)); //Actually move player
CurrentGridPosition = intendedPosition; //Update CurrentGridPosition
}

public void StepLeft()
{
// calculate intended position. Get current direction and add one step left
switch(CurrentDirection.ToLower())
{
case "n":
default:
{
intendedPosition = CurrentGridPosition + new Vector3(-1,0,0);
break;
}
case "e":
{
intendedPosition = CurrentGridPosition + new Vector3(0,0,1);
break;
}
case "s":
{
intendedPosition = CurrentGridPosition + new Vector3(1,0,0);
break;
}
case "w":
{
intendedPosition = CurrentGridPosition + new Vector3(0,0,-1);
break;
}
}
//TODO: Check move is valid
MoveTo(Grid.GridToWorld(intendedPosition));//Actually move player
CurrentGridPosition = intendedPosition; //Update CurrentGridPosition
}

public void StepRight()
{
// calculate intended position. Get current direction and add one step right
switch(CurrentDirection.ToLower())
{
case "n":
default:
{
intendedPosition = CurrentGridPosition + new Vector3(1,0,0);
break;
}
case "e":
{
intendedPosition = CurrentGridPosition + new Vector3(0,0,-1);
break;
}
case "s":
{
intendedPosition = CurrentGridPosition + new Vector3(-1,0,0);
break;
}
case "w":
{
intendedPosition = CurrentGridPosition + new Vector3(0,0,1);
break;
}
}

//TODO: Check move is valid
MoveTo(Grid.GridToWorld(intendedPosition)); //Actually move player
CurrentGridPosition = intendedPosition; //Update CurrentGridPosition
}

public void TurnLeft()
{
//check if player is already turning
if(!enableRotation)
return;

enableRotation = false; //disable turn inputs

Vector3 intendedPosition = transform.localEulerAngles + new Vector3(0,-90,0);//calculate intended position after turning 

TurnPlayer(intendedPosition); //actually turn player

//Because player has turned, player direction has changed.  This updates to correct value
switch (CurrentDirection.ToLower())
{
default:
case "n":
CurrentDirection = "w";
break;
case "e":
CurrentDirection = "n";
break;
case "s":
CurrentDirection = "e";
break;
case "w":
CurrentDirection = "s";
break;
}
}

public void TurnRight()
{
//check if player is already turning
if(!enableRotation)
return;

enableRotation = false; //disable turn inputs

Vector3 intendedPosition = transform.localEulerAngles + new Vector3(0,90,0);//calculate intended position after turning 

TurnPlayer(intendedPosition); //actually turn player

//Because player has turned, player direction has changed.  This updates to correct value
switch (CurrentDirection.ToLower())
{
default:
case "n":
CurrentDirection = "e";
break;
case "e":
CurrentDirection = "s";
break;
case "s":
CurrentDirection = "w";
break;
case "w":
CurrentDirection = "n";
break;
}
}

#endregion

void Update()
{
//checks if player is moving, if not enables movement inputs
if(CurrentGridPosition == intendedPosition)
{
if(Input.GetButtonDown("Forward"))
{
MoveForward();
}
if(Input.GetButtonDown("Backward"))
{
MoveBackward();
}
if(Input.GetButtonDown("StepLeft"))
{
StepLeft();
}
if(Input.GetButtonDown("StepRight"))
{
StepRight();
}
}

//checks if player is turning, if not enables turning inputs
if(enableRotation)
{
if(Input.GetButtonDown("TurnLeft"))
{
TurnLeft();
}
if(Input.GetButtonDown("TurnRight"))
{
TurnRight();
}
}

//if player is turning, checks if turn has finished.
if(!enableRotation)
{
timer -= Time.deltaTime;
if(timer < 0)
{
enableRotation = true;
timer = StepSpeed;

}
}
}





Monday, July 22, 2013

Using Grid Framework to build a platformer

The last months have been insanely busy.  I may have overdone it on my still healing foot, and so today I find myself at home and forced to rest.  It sounds like a perfect opportunity to make a game AND a tutorial!!

I enlisted the help of my 4 year old daughter in deciding what kind of game to make.  She wanted a game where Happy Face has to collect a crown.  Happy Face will encounter a witch, a Mother Spider and her Baby Spiders.  So, I am going to be building a single screen platformer.  By single screen, I mean that what is displayed is the entire game, no scrolling, no extra rooms.  At least not yet :)

I have also just purchased Grid Framework and this is a great time to see what it can do.

First thing is to create the actual grid.  GameObject > Create Grid > Rectangular Grid will do the trick.  Hexagonal Grids and Polar Grids are also available.  Hexagonal grids will be perfect for deep strategy games.  A polar grid is a circular grid, and the only use I can think of for it right now is as some kind of radar or motion sensor display.

Grid with Default Settings

Now to shape the grid to fit our game world.  For this game, I need a grid twice as wide as it is tall.  I dont care about depth, so I set the Z to 0.  X is 12 and Y is 5.  Your dimensions may vary.

2D Grid
I should now be able to use this grid to create a basic level layout.  Open up the Grid Align Panel (Window > Grid Align Panel) and turn on AutoSnapping.  Make sure you have assigned your grid to the panel too.
Create a basic cube (GameObject > Create Other > Cube) and drag it onto the grid.  You will see that it is perfectly aligned, and moving it around will snap it to the grid.  Place a bunch of these and you have a level.
I will create a boundary first, to stop an eager 4 year old from jumping off the world into oblivion.

Once the boundary is created, lets get Happy Face into the game and moving.   All artwork has been provided by my daughter :)

For the sake of simplicity, I am faking a 2D sprite by creating a cube with a transparent diffuse and her painting attached.  Also add a character controller.  This will replace the default box collider.

Fake2D Sprite settings
Lets add some simple scripting to get this happy fella moving.  Attach this script to your 'sprite'

float moveSpeed = 3.0f;
float jumpSpeed = 8.0f;
float gravity = 10.0f;
Vector3 moveDirection = Vector3.zero;
// Update is called once per frame
void Update ()
{
//handle input and move character controller;
CharacterController cc = GetComponent<CharacterController>();
if(cc.isGrounded)
{ moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, 0); // Gets Horizontal movement. Edit > Project Settings > Input to find out more about Axis.
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= moveSpeed;
if(Input.GetButton("Jump") && cc.isGrounded)
{
moveDirection.y = jumpSpeed; }
}
moveDirection.y -= gravity * Time.deltaTime;
cc.Move(moveDirection * Time.deltaTime);


Test it out and you should be able to walk your sprite back and forth without it falling out of the world.  Lets add a few platforms and the crown.  The grid will allow me to easily line up platforms, and with the current gravity settings on the player I know that the sprite can jump just over 3 grid squares high, so I need a maximum distance of 3 squares floor to floor for the character to be able to make the jump.

Basic level


Lets add a quick script to the crown to allow it be 'collected'.
When the player touches the crown, the following needs to happen:
Record that the crown has been collected
Play a 'pick up' sound
'Destroy' the game object.

To make a trigger on the crown object, I select it and set 'Is Trigger' to true on the box collider.  I also have an empty object in my scene called 'Game Manager', with a game manager script attached.  I'll use this to track any information that the entire game needs to know about.  Right now it just consists of a single public bool to track if the crown has been collected or not.  Set it's default value to false (uncollected).

My crown script.  I used the free tool SFXR to generate my sound fx.

using UnityEngine;
using System.Collections;

public class Crown : MonoBehaviour {

void OnTriggerEnter(Collider other) //fired when an object ENTERS the trigger zone
{
//Record that crown has been collected
GameManager gmScript = GameObject.Find("Game Manager").GetComponent<GameManager>();
gmScript.CrownCollected = true;

//Play Pick up sound
audio.Play();

//Destroy Object
Destroy(GameObject.Find("Crown"), 0.3f);
}
}

Test and you should have a playable level with a pick upable crown.  Whats missing?  Friends, of course!!

Next part coming soon....


Sunday, July 21, 2013

The battle with OAuth.

I've been battling OAuth, all day, today.  In Xamarin.Auth.  The fundamental problem is that it didn't support JSON responses.. so I pulled down the GitHub repo.. started dinking with it.

I eventually got it to work.  Took quite a bit of fighting.  I'm looking forward to using it here soon, for the Xamarin.IOS app and for the Xamarin.Android app.

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.

Wednesday, July 10, 2013

Making good progress on the Android Version.


Things are looking pretty decent, actually.  Just gotta keep making progress. I really have gotten a lot better at this whole mobile thing.  Kind of impressed.   It's amazing how much time you save, when your projects have a lot of classes without native references.

I really can't wait for the release this weekend on ITunes.  

I'll have to add a back navigation button.. up in that window.. but I think I can live with how it's taking shape already.

Tuesday, July 9, 2013

Starting up the Android Version of Print Hub.



I've been dying to kick some tush (as I'd say to my boys) on this stuff that's been floating around.
Jared is kicking it with me.  Camera functions and Album functions work, moving on to the rest of the stuff here soon.  Had to take a bit of time and get some native Java code ported over.  I should have started with Android for my first store app, instead of spending so much time on IOS, but I think if I had.. I would have been really frustrated later, moving to IOS.  Java code ports for functionality, are so fast.  I could do it in my sleep. : )

That's one problem that will always exist in Xamarin, because there is no Graphics port for Mono, you always have to work with graphics / pdf's.. almost everything natively.. unless, you can find something that has been ported purely to Mono.

You have to give Apple this:   Their best apps always look good.  Or at least, a heckuva lot better than most Android Apps out there.  The game, is to understand enough.. to be able to style both sides. Android, and IOS.. powerfully.  I think I know have the ability to make.. purdy apps.  Now it's just porting API's.. luckily, I do that once.

What I really love about porting API's.. is that the code to use those API's.. is always so tiny..

Print Hub Progress.

I did a lot of work yesterday on Print Hub.  I'm not even sure how long I worked on it.
It seemed to be a lot more fun than it was before.  In fact, I got a whole pile of the Google Cloud Print API working, that didn't work before previously (Not entirely sure what was up there, but I rewrote a number of classes, and cleaned things up).   Here in the next couple days, I'll be pushing a couple other app ideas, out the door (I'm hoping), but frankly, there doesn't seem to be a lot in the way right now. : )


I added Processing Invites, and deleting Jobs.
Obviously, I did some styling work.
I wanted it to be a bit cleaner.. overall. Faster on that main dialog for printing.

Sunday, June 23, 2013

How to import Sketchup Free models into Unity Free

Sometimes you need to get your 'Programmer Art' into Unity.  I recently tried out Sketchup for 3D modelling and found it an excellent tool to let me create some basic models for prototyping.  This method will allow you to import your own models, or models imported from Google 3D Warehouse.  If you dont use the paid version of Sketchuo,  you will need this free plugin.  If you don't want to register on that site, its in my Dropbox.  Put this file in your sketchup\plugins folder.



Lets get started:

First we need a Sketchup model.  Here is one I made earlier :).  Feel free to use it or make your own.  If you choose to make your own, I recommend using the Simple Metre template, as the scale will match Unity.  If you want pull something from the warehouse, go to Window > Components and use the search bar.

A churchy type thing


When you are ready to export your model:

Select File > OBJ Exporter
Give it a filename and select YES to convert all texture files to PNG.
This process will also optimise the model (remove duplicate vertices etc..)

To import the model into Unity:

Copy the .mtl,.obj and the model textures folder into your projects Asset folder.  Create a new folder or use an existing one, it doesn't matter as long as it is in the Assets folder.
Open your Unity project.  You will see the model and its associated files in the project window.
There will be a prefab ready for you to drag into your scene (or instantiate through code), with it's textures intact, including the UV mappings.

The same churchy thing in a Unity scene.

















Saturday, June 22, 2013

Useful Xamarin.IOS code for Filter Information.

I know with IOS7 coming, making Filter code could be a thing of the past..

But I wanted to throw this code out there anyways.


CIFilter filter = CIFilter.FromName ("CISharpenLuminance");
string[] keys = filter.InputKeys;
NSDictionary attributes = filter.Attributes;
foreach(NSObject key in attributes.Keys)
{
    Console.WriteLine(key.ToString());
    Console.WriteLine (attributes[key].ToString());
}
foreach (string s in keys)System.Console.WriteLine (s);


Pick your filter.. throw it into the CIFilter.FromName() line, and bam, you have all the info you need to apply it.

How to use Xamarin's new UI Designer with Paint Code for custom controls.


After reading this post by the Xamarin team, I really wanted to get to work on making some nifty things.   So, I basically pulled down the latest updates in the Alpha channel from Xamarin, made a new project, and hopped right in.

I wanted to see how much easier it was to make custom styled components and add them to my applications, and boy, was I impressed how much faster it is.


Using the UIButton for this little example of code, is probably the worst thing I could have done, but oh well.  I created this simple class, MyButton and inherited from UIButton. 


    [Register("MyButton")]
    public class MyButton : UIButton
    {
        public MyButton ()
        {

        }
        public MyButton (IntPtr handle)
        {
            this.Handle = handle;
        }
        public override void Draw (System.Drawing.RectangleF rect)
        {
            base.Draw (rect);
        
            var context = UIGraphics.GetCurrentContext();

            //// Color Declarations
            UIColor strokeColor = UIColor.FromRGBA(0.000f, 0.000f, 0.000f, 1.000f);

            //// Shadow Declarations
            var shadow = strokeColor.CGColor;
            var shadowOffset = new SizeF(3.1f, 3.1f);
            var shadowBlurRadius = 5;

            //// Image Declarations
            var image = UIImage.FromFile("Test2.png");

            //// Rectangle Drawing
            var rectanglePath = UIBezierPath.FromRoundedRect(rect, 8);
            context.SaveState();
            context.SetShadowWithColor(shadowOffset, shadowBlurRadius, shadow);
            context.SaveState();
            rectanglePath.AddClip();
            image.Draw(rect);
            context.RestoreState();
            context.RestoreState();

            strokeColor.SetStroke();
            rectanglePath.LineWidth = 1;
            rectanglePath.Stroke();
        }
    }


The Draw code, came from PaintCode.. I had to tweak a couple things, one, I had to tweak image.Draw to match the button's submitted rect for Draw.  Below is a screenshot from PaintCode, I set the Corners to rounded, upped the radius so that it was visible for the rounding of the corners, then I picked a texture image, for the fill.




Below is rendered output inside of their new designer.. which means I didn't need to deploy in order to see a result.  






Friday, June 21, 2013

Print Hub status update.

Graph provided by AppFigures.com
As you can see, I'm still getting purchases.. even without marketing, and without being listed as a supporting app on Google Cloud Print.

I'm hoping this weekend to finish off those requirements, so I can get listed, and then I'll see if my purchase rate goes up.

I had a chat with App.IO's CEO this week, I have a weird suspicion that the App.IO team bought my app and that's why I had that surge of purchases.  Just told him I loved the platform.. and that he needed some "C guys" to deal with the latency in rendering for the product.   To be honest, they really don't need the work done.. who cares if it is laggy.  It's gorgeous.

Here this weekend, I'm going to try and get the start of my next couple apps going.

I don't know what to think.  I don't think being an independent mobile developer will ever be easy, but I do know that I'm going to keep adding my features.  I'm pretty much operating at a loss, in regards to App Store deployments, but honestly, I'm ok with it.  I've gotten some components, that I'll be able to re-use for other projects.  I probably still need a lot more components to be able to do the wide array of applications I intend to do.


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 ();
}