Month: August 2012

One APK to rule them all

I wrote this a while back on a forum post and never posted it here. I figured it was good information and could help other Android nerds as well.

Having one apk to rule them all is a tricky thing to manage. I just recently launched with normal, large, and xlarge layouts along with landscape for large and xlarge. It is not easy, it takes a ton of regression testing, but is totally worth it.

There are some people that are developing separate apps for tablet. I wouldn’t recommend it, personally. Maybe if you pull out all business logic and throw it in a library it may be easier but there would still be a ton of redundant work. Abstract out the work of building out the views, and that will allow you to manage each resolution re-using the same techniques.

One tip is to have a very easily accessible flag that allows you to differentiate which device size you’re running on.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//check to see if we have a tablet, large or phone, and then set the global flag
int screenLayout = getResources().getConfiguration().screenLayout;
model.isTablet = 
   ((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE);
 
//if isTablet is false, check to see if we have a Large device, else
we have a phone
if(model.isTablet == false){
   model.isLarge = 
       ((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE);
   if(model.isLarge){
      model.deviceSize = "Large";
   }else{
      model.deviceSize = "Phone";
   }
}else{
   model.deviceSize = "Tablet";
   model.isLarge = false;
}
 
//throw in a isLandscape if that matters as well. 
public boolean isLandscape(Context context) {
   int orientation = context.getResources().getConfiguration().orientation;
   return (orientation == Configuration.ORIENTATION_LANDSCAPE);
}

by using these flags on simple singleton model, you can easily build out the appropriate view for any scenario….except for small. just add a new flag for that 😉

Deep copy of Objects in C# Metro for Windows RT/WoA

Hey Guys! I don’t write blogs as much as I should. I swear I have tons of fun little snippets of code that I use all the time. I just don’t post them. :X

Here’s a great one that I’ve just finally figured out. Deep Copy in C# for Metro is very tricky. All the examples you will find are based on older version of .NET that aren’t included or are deprecated completely in Windows RTM.

Here is a super simple helper function that you can easily throw in an extension class.
 

using System.IO;
using System.Runtime.Serialization;
using Windows.Foundation;

namespace Extensions
{
#pragma warning disable 1591
    public static class ObjectExtension
    {
        public static Object DeepCopy(this Object objectToCopy)
        {
            Object copy;
            DataContractSerializer serializer = new DataContractSerializer(typeof(Object));
            using (MemoryStream ms = new MemoryStream())
            {
                serializer.WriteObject(ms, objectToCopy);
                ms.Position = 0;
                copy = (Object)serializer.ReadObject(ms);
            }
            return copy;
        }
    }

#pragma warning restore 1591
}

In the example class above, you can easily swap out Object for any Class type you want. I wanted to make this generic but couldn’t get it working. If you can, more power to ya! 🙂

I personally have a Data object in place of Object. One gotcha that you may run into is classes with an ImageSource property or another property that can’t be serialized. You need to add these metadata tags to your class to define which properties are supposed to be copied and which are ignored.

[DataContract]
class DataClass

[DataMember]
String title { get; set;}

[IgnoreDataMember]
ImageSource imageSource { get; set;}

More info can be found in the msdn: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx