TestFlightApp.com MonoDevelop Integration

Well it’s been quite a while since I’ve done a post. Today’s post is just a repost of an old post I had on my old blog before I had some data loss issues. Someone in the IRC channel asked about it today, so here it is. The following is a except from a csproj file, showing what you need to add/change into your configuration to get MD to auto-build your app and upload to TFA.

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
26
27
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AdHoc|iPhone' ">
    <DebugType>none</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\iPhone\AdHoc</OutputPath>
    <WarningLevel>4</WarningLevel>
    <MtouchDebug>False</MtouchDebug>
    <AssemblyName><Your Assembly Name></AssemblyName>
    <CodesignKey><Your Key Here></CodesignKey>
    <MtouchI18n />
    <CustomCommands>
      <CustomCommands>
        <Command type="BeforeBuild" command="rm -rf ${SolutionDir}/Output/Payload/${ProjectName}.app/" />
        <Command type="BeforeBuild" command="rm -rf ${SolutionDir}/${ProjectName}.ipa" />
        <Command type="AfterBuild" command="cp -r ${ProjectDir}/bin/${ProjectConfigPlat}/${ProjectConfigName}/${ProjectName}.app ${SolutionDir}/Output/Payload/${ProjectName}.app" workingdir="" />
        <Command type="AfterBuild" command="zip -r ../${ProjectName}.ipa ." workingdir="${SolutionDir}/Output/" />
        <Command type="AfterBuild" command="curl http://testflightapp.com/api/builds.json -F file=@../${ProjectName}.ipa -F api_token='<Your API Token Here>' -F team_token='<Your Team Token>' -F notes='Uploaded Automatically From MonoDevelop' -F notify=false -F distribution_lists='<Your Distribution Lists>'" />
      </CustomCommands>
    </CustomCommands>
    <CodesignProvision><Your Codesign UID></CodesignProvision>
    <MtouchUseLlvm>false</MtouchUseLlvm>
    <MtouchUseArmv7>false</MtouchUseArmv7>
    <MtouchUseThumb>false</MtouchUseThumb>
    <MtouchUseSGen>false</MtouchUseSGen>
    <MtouchArch>ARMv6</MtouchArch>
    <MtouchSdkVersion>4.3</MtouchSdkVersion>
    <MtouchMinimumOS>4.3</MtouchMinimumOS>
  </PropertyGroup>

Once you’ve made this change to your CSPROJ file, the next steps are as follows.

  1. Create an Output Directory in your solution folder
  2. Create a Payload folder inside the new Output folder
  3. Configure the upload note, and API Key and

While there is still lots of room for improvement, it should give everyone a quick idea of how to use MD’s custom build actions to automatically upload your build to TFA.

Cheers
Warren

Rewrite Memory size for JNLP Web Clients

Well today I ran into a weird issue where a JNLP file wouldn’t launch the JVM. Through some troubleshooting, I discovered it was because more virtual memory than could be assigned was being assigned. I wrote this little script that goes and gets the latest ws file, searches for 1024m and replaces with 768m then runs the file.

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
26
27
28
29
30
31
32
33
34
35
36
Const ForReading = 1
Const ForWriting = 2
 
Dim fso, folder, files, NewsFile,sFolder, dDateModified, jnlpFile
dDateModified = CDate("1/1/2000")
Set fso = CreateObject("Scripting.FileSystemObject")
Set sFolder = fso.GetSpecialFolder(2)
 
If sFolder = "" Then
    	Wscript.Echo "No Temp Folder Found"    
	Wscript.Quit
End If
 
Set folder = fso.GetFolder(sFolder)
Set files = folder.Files 
 
For each fil In files
    if (InStr(fil.Name,"javaws") > 0 and fil.DateLastModified > dDateModified) then
        dDateModified = fil.DateLastModified        
	jnlpFile = fil.Name
    end if
 
Next
 
if jnlpFile <> "" then
	Set objFile = fso.OpenTextFile(sFolder.Path & "\" & jnlpFile, ForReading)
    	strText = objFile.ReadAll    
	objFile.Close
    	strNewText = Replace(strText, "1024m", "768m")
    	Set objFile = fso.OpenTextFile(sFolder.Path & "\" & jnlpFile, ForWriting)
    	objFile.WriteLine strNewText    
	objFile.Close
    	Set WshShell = WScript.CreateObject("WScript.Shell")
    	WshShell.Run("javaws " & """" & sFolder.Path & "\" & jnlpFile & """")    
	Set oShell = Nothing
end if

ABAddressBook Helper

Hey everyone, while working on my latest project, i discovered the need to search the address book for a phone number. Through my travels, I DID discover that it seems this functionality isn’t exposed by default with the native iOS libraries, or if it is, its with NSArrays, and NSObjects which can be slower than native MT components. So with a bit of help from Clancy, i came up with this helper class for the MonoTouch ABAddressBook. Enjoy.

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class ContactHelper
{
    public ContactHelper() { }
 
    public static ABPerson PickContact(UIViewController view)
    {
        ABPeoplePickerNavigationController picker = new ABPeoplePickerNavigationController();
 
        ABPerson ret = null;
 
        picker.SelectPerson += delegate(object sender, ABPeoplePickerSelectPersonEventArgs e)
        {
            picker.DismissModalViewControllerAnimated(true); ret = e.Person;
        };
 
        picker.Cancelled += delegate
        {
            picker.DismissModalViewControllerAnimated(true);
        };
 
        view.PresentModalViewController(picker, true); return ret;
 
    }
 
    public static ABPerson SearchByPhoneNumber(string phoneNumber)
    {
        List singlePeople = new List();
        phoneNumber = Regex.Replace(phoneNumber, "[^0-9]", "");
        ABAddressBook ab = new ABAddressBook();
 
        var people = ab.Where(x => x is ABPerson).Cast().Where(
            x => x.GetPhones().Where(p => Regex.Replace(p.Value, "[^0-9]", "").Contains(phoneNumber) ||
                phoneNumber.Contains(Regex.Replace(p.Value, "[^0-9]", ""))).Count() > 0).ToArray();
 
        foreach (var person in people)
        {
            if (singlePeople.Intersect(person.GetRelatedNames().Cast()).Count() <= 0)
                singlePeople.Add(person);
 
        }
 
        return singlePeople.ToArray().First();
 
    }
 
}

Updates to SuperYeti/MonoTouch.Dialog

I fixed up the BooleanImageElement to draw the On/Off slider in the correct location on the view now, it detects what device it is, and based on that it changes the X value accordingly. http://github.com/SuperYeti/MonoTouch.Dialog

Im Back hehe new updates to MonoTouch.Dialog.Extensions

Well after a bit of a hiatus on iOS Dev, i’m back. I added a new “SpiffyDialogViewController” to the MT.D.Ext library today. Its based off of Miguel’s code sample in MT.d to do a backgroun image on a UITable, but wasn’t working correctly on the iPad aka not at all. So i did some research figured out where it was failing and fixed it. silly SDK version inconsistencies. Well its all good to go now, and uploaded to. http://github.com/SuperYeti/MonoTouch.Dialog.Extensions feel free to add to it or any comments or suggestions are always welcomed. Cheers.

MonoTouch.Dialog.Extensions Release

Hey everyone. I’ve released the 1st version of MonoTouch.Dialog.Extensions at http://github.com/SuperYeti/MonoTouch.Dialog.Extensions. The first addition is a UrlImageStringElement extension that will load an image and caption from a URL, save the image on the file system, and create a thumbnail for it. This also utilizes an LRU cache, and download throttling mechanism thanks to Miguel for that. Check it out, and let me know what other extensions you’d like to see on it in the future. Cheers.

UPDATE: I just added in a search bar, and image cache management for clearing the cache. I made the sample app a little google images search tool.

http://github.com/SuperYeti/MonoTouch.Dialog.Extensions.

MonoTouch.DirectoryRecurser

Well today i built a quick little File system browser for the iPhone using MonoTouch.Dialog as a little POC. It goes and recurses your documents directory, and allows you to navigate through the folder structure, and click on files to see an alert with the name.

SuperYeti/MonoTouch.Dialog updates

Well Miguel went to merge some/all of my changes on my fork into trunk today, and there were a ton of whitespace and formatting changes. i went through and cleaned these up, and pulled from trunk to make it more consistent. While i was in there i included all of Miguel’s recent changes, and made his new changes, and my old ones play nice together. Essentially the merge is done, miguel just has to decide which of the changes he wants to keep. in any case, please find the url below, and check it out for yourself if wanted. Cheers.

http://github.com/SuperYeti/MonoTouch.Dialog/

caulker extensions

hey guys, today FAK finally released his AWESOME 3d mapping library, and i began to cut my teeth on it. it annoyed me that double tap wasn’t there so i added it in, and removed the tilt during zoom functionality as well. I was thinking either 3 touch tilt (ahill’s idea) or maybe a touch and hold button and use the accelerometer to tilt your display of the map, that’d be kinda cool. Also i think the compass, and gps should be tied into the core library, for map orientation, and location capabilitites. I’ll be adding this release to FAK’s source if he wants when he gets back, but i wanted to start a good forum on ideas/suggestions for the library while it was fresh until FAK gets up a forum, or suggestion list. Cheers Warren. I’m lazy and didnt feel like posting the file elsewhere. Just right-click and save-as the link below and remove the .jpg extension from the file to reveal the tar.gz. l8rs

Download Source Here, rename to *.tar.gz

UPDATE: MonoTouch Compatible Encryption Functions

Hey guys, i was informed that i used a weak cipher combination on my last post and example. I’ve done some more reading, learned a ton more about encryption today :) , and have come up with this based on the MSDN examples, and some more reading. Cheers.

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
public static class PageSecurity
{
    private const string bKey = "Fvjh834funw0uw34nf9we80yfw07FYB3Q4FNH74329";
 
    private static byte[] bSalt
    {
        get { return new byte[] { 0x23, 0x5e, 0x2d, 0x65, 0x94, 0x7a, 0x62, 0x64, 0x5d, 0x3c, 0xe3, 0xee, 0xfa }; }
    }
 
    public static string EncryptString(string plainText)
    {
        Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(bKey + UIDevice.CurrentDevice.UniqueIdentifier, bSalt);
 
        byte[] Key = rdb.GetBytes(32);
 
        byte[] IV = rdb.GetBytes(16);
 
        // Check arguments.
        if (plainText == null || plainText.Length <= 0)
            throw new ArgumentNullException("plainText");
        if (Key == null || Key.Length <= 0)
            throw new ArgumentNullException("Key");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("IV");
 
        // Declare the stream used to encrypt to an in memory
        // array of bytes.
        MemoryStream msEncrypt = null;
 
        // Declare the RijndaelManaged object
        // used to encrypt the data.
        RijndaelManaged aesAlg = null;
 
        try
        {
            // Create a RijndaelManaged object
            // with the specified key and IV.
            aesAlg = new RijndaelManaged();
            aesAlg.Key = Key;
            aesAlg.IV = IV;
 
            // Create a decrytor to perform the stream transform.
            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
 
            // Create the streams used for encryption.
            msEncrypt = new MemoryStream();
            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            {
                using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                {
 
                    //Write all data to the stream.
                    swEncrypt.Write(plainText);
                }
            }
        }
        finally
        {
            // Clear the RijndaelManaged object.
            if (aesAlg != null)
                aesAlg.Clear();
        }
 
        // Return the encrypted bytes from the memory stream.
        byte[] retArray = msEncrypt.ToArray();
 
        return Convert.ToBase64String(retArray, 0, retArray.Length);
 
    }
 
    public static string DecryptString(string cipher)
    {
        Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(bKey + UIDevice.CurrentDevice.UniqueIdentifier, bSalt);
 
        byte[] Key = rdb.GetBytes(32);
 
        byte[] IV = rdb.GetBytes(16);
 
        byte[] cipherText = Convert.FromBase64String(cipher);
 
        // Check arguments.
        if (cipherText == null || cipherText.Length <= 0)
            throw new ArgumentNullException("cipherText");
        if (Key == null || Key.Length <= 0)
            throw new ArgumentNullException("Key");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("IV");
 
        // Declare the RijndaelManaged object
        // used to decrypt the data.
        RijndaelManaged aesAlg = null;
 
        // Declare the string used to hold
        // the decrypted text.
        string plaintext = null;
 
        try
        {
            // Create a RijndaelManaged object
            // with the specified key and IV.
            aesAlg = new RijndaelManaged();
            aesAlg.Key = Key;
            aesAlg.IV = IV;
 
            // Create a decrytor to perform the stream transform.
            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
            // Create the streams used for decryption.
            using (MemoryStream msDecrypt = new MemoryStream(cipherText))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
 
                        // Read the decrypted bytes from the decrypting stream
                        // and place them in a string.
                        plaintext = srDecrypt.ReadToEnd();
                }
            }
        }
        finally
        {
            // Clear the RijndaelManaged object.
            if (aesAlg != null)
                aesAlg.Clear();
        }
 
        return plaintext;
    }
 
    public static string EncryptString(int value)
    {
        return EncryptString(value.ToString());
 
    }
 
}

« Older Entries