Titanium iOS KeyChain support with Securely

I’m happy to announce the the availability of the Securely Titanium module.  The goal of Securely is to provide a security toolkit for Titanium developers to write more secure apps.

KeyChain Properties API

The first release of Securely (iOS only) provides a Properties API which provides access to the iOS KeyChain.  Designed for ease of use the Properties module should be familiar to anyone using Titanium as it mimics the popular Ti.App.Properties API.

var securely = require('bencoding.securely');
Ti.API.info("module is => " + securely);

//You can provide optional identifier and accessGroup 
//If none are provided we will use your bundle id as the identifier
var properties = securely.createProperties({
     identifier:"Foo",
     accessGroup:"Bar"
});

Since the Securely Properties module mimics Ti.App.Properties you simply call setString when you would like to save a value.  Instead of being written to Properties it is instead persisted to the device’s KeyChain.

properties.setString('String','I am a String Value ');

Similarly you use the getString method just like you would for properties, but instead you are retrieving values from the KeyChain.  We even support default values for API compatibility.

Titanium.API.info('String: ' + properties.getString('whatever',"Fred"));

All of your other Ti.App.Properties you rely upon also have a compatible equivalent in Securely.  To see the full list please read our documentation here.

Get the module

The module is available at benahrenburg/Securely on github.

Need an example?

The module’s example folder contains a sample app.js demonstrating all of the available methods.  You can view the sample in on github here.

Learn more

To learn more please visit the Securely github repo and read the documentation.

What’s next?

I am currently working on adding Encryption and File Handling features to Securely.  An Android version is also in the planning stages.

Changing a Titanium iOS Module’s GUID

Occasionally you will need to a module’s GUID.  This is commonly done to avoid licensing conflicts with open source modules.

Updating a module’s GUID is a straight forward and simple process.  The below steps demonstrate how to change the GUID in your Titanium iOS custom module.

Before getting started it is important to note that Appcelerator doesn’t support updating your module’s GUIDs so please make a back-up of your original files just in case.

Generate a new GUID

The first step is to generate a new GUID.  I like to use GuidGenerator.com. Using this site we generate a GUID of 2016a336-bc2-494a-b112-98d6edd999de that we will us to update our Xcode module project.

guidgenerator

Updating the Manifest File

When you create a Titanium Module project, a manifest file is automatically created for you.  This file contains your project name, version information, module id, and your module’s GUID.

The manifest file is located in the root of your Xcode project, as shown below.

manifest_file

Open this file in your favorite text editor and change the existing GUID to the new one generated by GuidGenerator.com.  In our case the manifest should now look like the below.

 

manifest_guid_update

Updating your Xcode Project

The next step is to update your module’s moduleId method.  This is located in the <Your Module Name>Module.m file of your project. In this example our module is called BencodingNetwork, so we will want to look in the BencodingNetworkModule.m project file.

finding_class

You will want to open this class file in Xcode and update the moduleGUID property.  You simply update the return value with the same GUID used in updating our manifest file.

xcode_update

Almost done, one last step

Now that you’ve updated your module’s GUID you will need to re-build your module.  To do this open terminal in the root of your module’s folder and run the ./build.py script as shown below.  This will generate a new compile module zip for you to use in your Titanium projects.

termina

Opening Custom Url Schemas with Titanium

Apple’s iOS implements a custom URL scheme is a mechanism through which third-party apps can communicate with each other.  This allows your app to launch other apps.

Using this powerful iOS feature is simple, just provide the app’s url to the Titanium.Platform.openURL method.

List of Custom Url Schemes Resources

The most challenging part of using Custom Url Schemes is finding available url’s to call.  Several new services have been released to meet this need.  Below is a few of the most comprehensive resources I have found.  Unfortunately many of the examples only show the top level Url without detailed functionality mapping.

Custom Url Examples:

Using the Custom Url Scheme resources discussed above you can quickly integrate with a wide variety of services using the same implementation pattern as shown below.  The below  are a few examples showing how you can use custom urls within your Titanium app.

FaceTime:

//Make a facetime call

var url = "facetime://1234567890";
if (Titanium.Platform.canOpenURL(url)) {
    Titanium.Platform.openURL(url);
}
else {
    alert('Cannot open app');
}

iBooks:

//Open an iBook from the App Store

var url = "itms-books://itunes.apple.com/us/book/the-zombie-survival-guide/id419952002";
if (Titanium.Platform.canOpenURL(url)) {
    Titanium.Platform.openURL(url);
}
else {
    alert('Cannot open app');
}

Facebook:

//Open the facebook app to the friends section

var url = "fb://friends";
if (Titanium.Platform.canOpenURL(url)) {
    Titanium.Platform.openURL(url);
}
else {
    alert('Cannot open app');
}

More Resources

Titanium MapView ImageOverlays, TileOverlays, GeoJSON and More

I’m happy to announce the latest release of the benCoding.MapView module.

This is a big release that provides support for the following:

In addition to the above features the module’s memory footprint has greatly been reduced.

The module is fully documented with samples demonstrating how to use each feature.  To learn more please visit our module documentation here.

What to see more of the module in action?  The module’s samples has been updated with videos highlighting many of the advanced features of the MapView module.  Please visit the our showcase  to view the demos in action.

A special thanks to Jeff Bonnes (@jeffbonnes) for contributing TileOverlay support.

New Features In Action

Here are a few of the new features in action.

 

Supporting Different orientationModes in your Universal iOS App

Recently I had a requirement to create a universal app that supported different orientation modes for iPhone and iPad. 

There are two key points to implementing a universal app that support different orientations by device.

  1. Explicitly define your launch orientations in your tiapp.xml for both iPhone and iPad
  2. On Window create explicitly set the orientation mode property.

Setting iPhone and iPad Launch Orientations

By configuring your orientation modes in your tiapp.xml tells the app what orientations are supported when the app is loading and your splash screen is active.  Since Titanium 2.0 you have the ability to set the orientation modes using info.plist format as shown below.

  1. Add the UISupportedInterfaceOrientations node as shown below. This specifies the orientation mode used by the iPhone.
  2. Add the UISupportedInterfaceOrientations~ipad node as shown below. This specifies the orientation mode the iPad will use.

If you do not add the iPad orientation node(UISupportedInterfaceOrientations~ipad) your app will use the UISupportedInterfaceOrientations settings to determine default orientation behavior.

The example below shows setting the launch orientations for the iPhone to Portrait and the iPad to both Portrait and Landscape.

<?xml version="1.0" encoding="UTF-8"?>
<ti:app xmlns:ti="http://ti.appcelerator.org">
    <deployment-targets>
        <target device="mobileweb">false</target>
        <target device="iphone">true</target>
        <target device="ipad">true</target>
        <target device="android">false</target>
        <target device="blackberry">false</target>
    </deployment-targets>
    <ios>
        <plist>
            <dict>
                <key>UISupportedInterfaceOrientations</key>
                <array>
                    <string>UIInterfaceOrientationPortrait</string>
                    <string>UIInterfaceOrientationPortraitUpsideDown</string>
                </array>
                <key>UISupportedInterfaceOrientations~ipad</key>
                <array>
                    <string>UIInterfaceOrientationPortrait</string>
                    <string>UIInterfaceOrientationPortraitUpsideDown</string>
                    <string>UIInterfaceOrientationLandscapeLeft</string>
                    <string>UIInterfaceOrientationLandscapeRight</string>
                </array>
            </dict>
        </plist>
    </ios>
</ti:app>

For more information please reference the iOS Specific Section documentation here.

Creating Windows with Explicit Orientations

It is a best practice to always set the orientations you wish to support on Window creation.

Below is a helper function and sample I use when creating all of my windows.  This can also be helpful for setting a common backgroundColor, or other setting.

1. CommonJS Helper ( file called helper.js)

var _isPhone = (Ti.Platform.osname == "iphone");
exports.makeWindow=function(a){
    a = a || {};
    var win = Ti.UI.createWindow(a);
    if(_isPhone){
            win.orientationModes = [
                Ti.UI.PORTRAIT,
                Ti.UI.UPSIDE_PORTRAIT
            ];  
    }else{
            win.orientationModes = [
                Ti.UI.PORTRAIT,
                Ti.UI.UPSIDE_PORTRAIT,
                Ti.UI.LANDSCAPE_LEFT,
                Ti.UI.LANDSCAPE_RIGHT
            ];  
    }

    return win; 
};

2. Sample Window Creation (app.js)

var helpers = require('helpers');
var winConfig = {
        title:"Foo", backgroundColor:'#fff', tabBarHidden:true, barColor:'#000
};
var win = helpers.makeWindow(winConfig);
var testLabel = Ti.UI.createLabel({
        text:"this is a test, turn the device to see if it worked", 
        color:"#000", top:40, left:25, right:25, height:60,
        textAlign:"center", font:{fontSize:12}
});
win.add(testLabel);
win.open();

For more information about window orientation please see the documentation here.

Setting the Minimum iOS Version for your Titanium Project

With Appcelerator’s release of Titanium SDK 2.1.2 you can now specify the minimum iOS version in your tiapp.xml file.  This is a big step forward in managing all of your cross platform configurations in one file.  For me this has removed the latest need for a custom plist,

Just add the min-ios-ver node to the ios configuration section in your project’s tiapp.xml.  The below example sets a minimum iOS SDK level to 5.0.

<ios>
    <min-ios-ver>5.0</min-ios-ver>
    <plist>
        <dict>
            <key>UIPrerenderedIcon</key>
            <true/>
            <key>UIStatusBarStyle</key>
            <string>UIStatusBarStyleBlackTranslucent</string>
            <key>UISupportedInterfaceOrientations</key>
            <array>
                <string>UIInterfaceOrientationPortrait</string>
                <string>UIInterfaceOrientationPortraitUpsideDown</string>
            </array>
        </dict>
    </plist>
</ios>

This has streamlined the deployment process for me both via Titanium Studio and Transport.py.

Using Circle Layouts in your Titanium MapView

In my last post, I outlined how you can add Polygon support to your Titanium MapView.  Continuing with this topic, I have added Circle Overlay support (MKCircle) to the Titanium MapView module.

To avoid any namespace collisions I forked the native Titanium MapView implementation and create the benCoding.Map module.

To show how this works, I’ve create a demonstration showing all of the worlds nuclear power plants with a circle showing a 10 and 50 mile radius.

Link: http://www.youtube.com/watch?v=jwnByWz1eJo

Please visit github for the compiled module, documentation, and sample apps. The project can be found at https://github.com/benbahrenburg/benCoding.Map

The Polygon and Circle example apps are included in the modules example folder or on github here.

Hopefully these examples will be useful for anyone working with GIS functions in Titanium.

Using Polygons in your Ti.Map.View

For a recent project, I needed to add Polygon support to Titanium’s MapView.  To avoid any namespace collisions I forked the native Titanium MapView implementation and create the benCoding.Map module.

To show how this works, I’ve put together a sample showing Polygon’s for all of the US States, and a country level Polygon for the United Kingdom.

Link: http://www.youtube.com/watch?v=1rudu6S9-rc

For the compiled module and associated code please visible https://github.com/benbahrenburg/benCoding.Map

The demo project shown in the video is included in the module’s example folder.

Hopefully these examples will be useful for anyone working with GIS functions in Titanium.

Using Local Notifications in Titanium

A recent Titanium project called for the use of Local Notifications.  I wanted to share my experience implementing this feature in hopes it will help others.

Tips / Questions

1. Tips on using Ti.App.iOS.scheduleLocalNotification

The current (version 2.0.2 ) implementation of the Ti.App.scheduleLocalNotification API requires that you call this method as part of a background service.  Keep in mind, this might change in future versions so please test your scenario on the current version of the framework.

Most problems with scheduling local notifications can be solved by moving your scheduling actions to a background service.  The below shows how the KitchenSink sample app performs this task.

First we need to register the background service in app.js. This will create the service once the app is based into the background.

    // register a background service. this JS will run when the app is backgrounded
    var service = Ti.App.iOS.registerBackgroundService({url:'bg.js'});

Second we create the notification in the bg.js


  var notification = 	Ti.App.iOS.scheduleLocalNotification({
	alertBody:"Kitchen Sink was put in background",
	alertAction:"Re-Launch!",
	userInfo:{"hello":"world"},
	sound:"pop.caf",
	date:new Date(new Date().getTime() + 3000) // 3 seconds after backgrounding
  });

Please visit this great QA Forum thread to learn more about different strategies to implement Ti.App.scheduleLocalNotification.

2. How do I cancel an individual notification?

It is my understanding there is currently two ways to do this:

  • You can call cancel on the notification after you create a notification.  See below for an example show how to implement this approach as demonstrated in the KitchenSink sample app.

Notification example from bg.js


  var notification = 	Ti.App.iOS.scheduleLocalNotification({
	alertBody:"Kitchen Sink was put in background",
	alertAction:"Re-Launch!",
	userInfo:{"hello":"world"},
	sound:"pop.caf",
	date:new Date(new Date().getTime() + 3000) // 3 seconds after backgrounding
  });

  // we cancel our notification if we don't want it to continue
  notification.cancel();

  • I believe you can use Ti.App.iOS.cancelLocalNotification to cancel a notification using a convention.  If when you created your notification you set the userInfo.id property to a unique integer value you can then pass this integer into the Ti.App.iOS.cancelLocalNotification method to cancel your notification.  This approach seems to work under some use cases but not others.  I would recommend testing on device to make sure it fits your app’s workflow.

Modify the bg.js example to add id to the userInfo object.


  //Create the notification
  var notification = 	Ti.App.iOS.scheduleLocalNotification({
	alertBody:"Kitchen Sink was put in background",
	alertAction:"Re-Launch!",
	userInfo:{"id":4, "hello":"world"},
	sound:"pop.caf",
	date:new Date(new Date().getTime() + 3000) // 3 seconds after backgrounding
  });

  //Cancel the notification using the id passed in as part of the userInfo object
  Ti.App.iOS.cancelLocalNotification(4);

3. How do I cancel all of my my Scheduled Notifications?

To cancel all of your notification you simply need to call the Ti.App.iOS.cancelAllLocalNotifications() method.  This will cancel all scheduled notifications linked to your app.


    // Cancel all notifications linked to your app
    Ti.App.iOS.cancelAllLocalNotifications();

4. How do I list my Scheduled Notifications?

Currently Titanium does not support querying scheduled notifications.  I discuss this more in how I implemented by solution below.

My implementation

Titanium is open source and extendable, making it easy to understand the platform’s current implementation and quickly add functionality.  For this project I needed to implement a custom workflow around local notifications that allowed users to schedule and managed their own notifications through a “dashboard”.

To assist with that I created a custom module that allows you to extend or replace the extending Titanium creation and cancellation methods.

  1. ScheduleLocalNotification – Same as the native Titanium but without the return object and you are able to call without a background service.
  2. activeScheduledNotifications  – Provides a callback with a list of your scheduled local notifications.
  3. returnScheduledNotifications – Provides the same collection of scheduled local notifications as the activeScheduledNotifications but directly without the callback.
  4. cancelLocalNotification – Takes an id and loops through canceling any scheduled local notification with a userInfo.id property that matches. A value is returned with the number of notifications that were scheduled.
  5. cancelAllLocalNotifications – Works the exact same way as the native method.

If you are interested in learning more about the benCoding.localNotify module please visit the project on Github here.

Using Titanium’s Transport.py

The Titanium Mobile SDK comes with the powerful transport.py script that allows you to generate stand alone XCode projects for your existing Titanium Mobile Projects.

The transport.py script allows you to share your XCode project with clients, third parties, or others that do not have the Titanium SDK installed.  You can also use this process to simply the App Store, Ad Hoc, and other processes by directly using Apple’s tools.

I use the transport.py process for all of my release compiles.  Below is the process that I follow when using this script.

Before We Get Started

For this example I’m going to use the Titanium SDK version 1.8.2 to create an XCode project for bARk.  You can download bARk from github if you want to follow along.

Verifying Your Titanium Project

Before running the transport.py script I recommend verifying a few things in your Titanium Project.

  1. Open Titanium Studio and go to your project
  2. When in your project open your tiapp.xml file and confirm the SDK Version is set to the correct version.  In this case we are using 1.8.2. as shown below.
    Verify Titanium SDK Version
  3. After confirming the SDK version we next need to make sure the project has been cleaned. This will ensure that the transport.py script performs a full build of your project.
  4. To clean your project click on the Project option in your toolbar then select Clean…
  5. This will open the below dialog box.  Select to either clean all projects or select the one you want to run transport.py against.  In the below example I’ve selected to only Clean the bARk project.
    Clean Project
  6. After your project has been cleaned, open Finder and go to your <Project>/build/iphone directory and confirm that it is empty.  This is important as the transport.py will create it’s files here.
    Confirm Directory Is Empty
  7. You can now close Titanium Studio and move onto running the transport.py script as outlined in the next section.

Running The Transport.py Script

The transport.py is a Python script located in your ~/Library/Application Support/Titanium/mobilesdk/osx/<SDK Version>/iphone directory.  This file is available with each release of Titanium so to use a later version update navigate to the correct directory.

For this example we’re using the path ~/Library/Application Support/Titanium/mobilesdk/osx/1.8.2/iphone

To run this script please follow the below steps.

  1. Open terminal and navigate to your ~/Library/Application Support/Titanium/mobilesdk/osx/1.8.2/iphone directory
  2. Issue the following command  ./transport.py <path to your project directory>  in my case that is ./transport.py /Users/benjamin/Dev/Projects/Ti/Demos/bARk/
    Transport.py Path Example
  3. You will now is the project building, the output should look like the below.
    transport.py console output
  4. Once the build has completed you will see a message saying “Finished! Share and Enjoy.”
    transport.py finished message
  5. Transport.py has now generated a stand alone XCode project for you in your Titanium Project’s build/iphone directory.
  6. Open Finder and navigate back to your <Project>/build/iphone directory that we cleaned in the “Verify Your Titanium Project” section.

Moving The Build Directory

Since Titanium often re-generates your project’s build directory I recommend moving the <Project>/build/iphone folder to another location before opening it in XCode.  This ensures the project wont be deleted by mistake.

XCode Project Updates

You now can work with your application using XCode directly.  Simply click on the .xcodeproj file in your output directory.

The below are a few configuration updates I typically make in XCode before creating a build. 

Remove Unwanted Targets

The transport.py script generates iPhone, iPad, and Universal targets when running.  It is recommended that you remove any targets you do not need.

Project Targets

To remove a target, simply select the target and press delete. You will be presented with a confirmation box such as the one below.

Press delete to remove the target from your project

Deleting a project target

Since bARk is only an iPhone app, I’ve removed all other targets just leaving the below.

iPhone Target

Verify Icon’s and Splash Screen Configuration

You will want to confirm that your app icons and splash screens are correctly associated with your project.

If you select your target ( in my case bARk) then press the Summary tab at the top you will see all of your icons. You can see in the below sample that we need to set both of our app icons and associate our retina splash image.

Target Icons

To add an icon you need to right mouse click ( control + shift + click ) on the different image boxes. 

Select Image

This will allow you to select an image using the Finder. To select your icons and splash images you want to navigate to the Resources/iphone directory in your build output folder.  The below shows an example of the path.

Image Finder

You will want to perform the above steps for any missing images.  When completed the Summary tab for your target should look like the below.

All images added 

Add or Remove Icon Gloss Effect

For some apps you will want to remove the prerendered-icon ( or gloss effect) on the icon.

By default this effect is enabled.  To remove this effect select your target, then go to the Info tab. Under the “Custom iOS Target Properties” section you will see a configuration entry called “Icon already includes gloss effects”. Toggle this effect to NO to remove the gloss effect.

See the below screenshot for an example.

Default Gloss Effect

In iOS 5 Apple introduced an additional property to control the icon gloss effect.  You can update this configuration by selecting your target, then go to the Info tab. Under the “Custom iOS Target Properties” section you want to expand the “Icon files (iOS 5) property and under the “Primary Icon” option you will see an option called “Icon already includes gloss effects”. Toggle this effect to NO to remove the gloss effect.

See the below screenshot for an example.

Icon Gloss Effect iOS5

Adding Icon to your URL Types

You have the ability to set custom URL Types.  By default you have a main URL Type for your application. 

To add an icon, select your target then press the Info tab at the top of your screen.  Then scroll to the end of screen to a section labeled URL Types. To add an icon, click on the icon dropdown box as shown below.

Adding a URL Icon

The dropdown will list all of the icons associated with your project.  Select the icon you want to use and it will populate the URL icon preview box as shown below.

URL Icon Added

What’s Next?

You now have a full stand alone XCode project. 

This can be helpful when performing the following:

  • Sending to a client or third party for signing and App Store Submission
  • Creating Ad Hoc distributions
  • Submitting to the App Store with non Titanium defaults
  • Pushing to device using the native Apple tools.

Watch The Video

Below is a video walk through of the above.