You are browsing the archive for Presentation.

Accessibility on Android

9:10 pm in Android, Presentation by Luke Wallace

The July 2011 DalMob Conclave focused on Accessibility in Mobile apps, with a presentation from Doug Russell and Luke Wallace from Bottle Rocket.

Luke’s presentation on Android Accessibility is available as a PDF link below.

Accessibility on Android (PDF)

This presentation was created before Android 4.0, which has made some small changes to how Accessibility is handled, with an option for a “explore-by-touch” mode. More details can be found at the following links:
http://developer.android.com/guide/practices/design/accessibility.html
http://developer.android.com/sdk/android-4.0-highlights.html#DeveloperApis
http://developer.android.com/reference/android/view/accessibility/AccessibilityRecord.html

November Conclave:

7:30 pm in Conclave, Presentation by Jay Henderson

NOVEMBER MEETUP- Mobile Web & PhoneGap

First of all, I just wanted to say that I am really getting into the groove of posting again. I definitely will be posting quite regularly now, and soon will be posting video content once I get a Canon or Sony camera! Now to business, I want to talk a little bit about Mobile Development and my first experience with Dallas Mobile [ DalMob ]. I honestly did not know that a resource like this group existed. The reason that I found out about the group was from a tweet posted by BottleRocket [ @_BottleRocket ]. This gave me some interest and the topic was on Mobile Web and PhoneGap, two topics I love!! So I headed downtown to TechWildcatters [ @techwildcatters ] to learn more about what this group was about and what I could learn.

THE ATMOSPHERE

I arrived at 6:48 and needless to say, I was late but the event was in full networking and discussion as the set-up was being polished. I will say that the Asian cuisine and beer was quite awesome while I waited to view the information. I gazed the room and found a few familiar faces from the AT&T Hack-a-thon event from the previous weekend. As I sat down to enjoy the refreshments we chatted about the experiences from the hack-a-thon and exchanged information learning more about careers, self interests, and the reason we were there for DalMob. I really found out a great deal from just talking with a few developers that were in attendance, and gained a new perspective on their ideas for mobile development.

THE PRESENTATION

The organizer of the event, Justin Leger, started the event by greeting everyone and letting us know what was going to be discussed for the night. He also stated that he was looking for volunteers to help with the group. He then proceeded to introduce Ean Schuessler, a co-founder of Dallas-based digital media consultancy, Brainfood. Ean started off the presentation talking about Mobile Web and presented us with the URL – http://dalmobdemo.clients.brainfood.com

Privacy for location Based Services with Smartphones

6:30 pm in Conclave, Presentation by james spargo

I would like to thank everyone for allowing me to present my research to DalMob.
Both the slides for my talk and my research can be found at www.spargonaut.com/dalmob/

Abstract:
These days, mobile devices and smartphones enabled with GPS and Internet access have become extremely common. People are using these devices as they would a personal computer for easy access to information. Location Based Services (LBS) provide customized information based on a user’s geographic location that has been retrieved from a dedicated spatial database such as Google Places, Yahoo’s Local Search Web Services and Yelp.com. This information can include nearby hotels, restaurants, gas stations, banks or other Points of Interest (POIs). Since most search engines and databases are known to store previous queries in order to improve future search results and other reasons, many researchers have expressed concerns and proposed solutions to protect a user’s location privacy. Research has shown that a significant amount of information, such as medical conditions, political or religious affiliations and more can be inferred based on a person’s previous location tracks. Many methods proposed by researchers rely on the use of trusted third parties such as anonymizing servers, other nearby mobile devices, or the LBS itself. CAP (Context-Aware Privacy) is a system that was designed to protect a user’s location without having to rely on a trusted third party or interfere with the operation of the LBS. A desktop prototype was made, yet it was never implemented on a mobile device or smartphone until now.

Preliminary tests of CAP with lower privacy settings proved to be effective, although when the privacy settings were increased, the results seemed to deteriorate. Closer examinations of the algorithm indicate that it is effective when compressing contextual map data for use by a mobile device, as well as effective perturbation of the user’s location. The POI results returned from the LBS tell a different story. While the POI results at low privacy levels seemed to be accurate (i.e. the POIs returned from the LBS are in fact the POIs that are closest to the user), when the privacy settings were increased, the results would degrade (i.e. the POIs returned were, as expected, further away from the user’s actual location). This is effective in the sense that the user’s actual location is not able to be divulged to an adversary, but is not very effective in terms of usability and convenience for the user. In this paper, we review CAP and several other proposed methods of location privacy intended for use with mobile devices. We have implemented CAP on a smartphone in its proposed method and evaluated its results, followed by modifications in order to gain more accurate POI results from publicly available LBS.

Research Paper: spargo.pdf
Presentation Deck: Spargo_dalmob_slides.pptx.pdf

It’s Not Easy Being Green

6:30 am in Conclave, Presentation by Michael Griffith

Even if you have been building things digital for your entire career, mobile is different. The iPhone debuted in 2007, the iPad in 2010. That means it’s still new for even the most experienced mobile developers. No one is an expert. This presentation contains some design considerations to hopefully ease the pain.

Presentation available at: http://prezi.com/aaqlovukco3e/its-not-easy-being-green/

Below are the design considerations we covered, if you would like more detail or elaboration on any of them, leave a comment.

Understand the phone vs. the tablet

A user will interact with their phone for 20 seconds, 100 times a day. For many it is the first and last object they interact with every day. The tablet is more a of sit back experience. Consider the devise use cases.

Work simply and iteratively

No matter how fast you can wireframe in OmniGraffle, I can sketch it on a whiteboard, photograph it, mail it and have client approval in half the time. Look for low fidelity product that can move the project faster.

Embrace the Human Interface Guidelines

If you fully understand Apple’s HIG it can save time and reduce mistakes. They have already solved many of the problems you are facing.

Love Thy Developer/Designer/Strategist as Thyself

In the digital space, all the disciplines overlap to some extent. Being humble and working closely and iteratively with people outside of you discipline will result in a better end product. Sit together in the same room if possible.

Don’t turn a website into an app

Although you client may think they want this, they are wrong. Most likely, 80% of the website users are only using 20% of the content. Figure out what that 20% is and build an app with focus. Also realize the mobile user needs and expectations may be very different than the users of the site.

Do One Thing and Do It Well

Similar to above. Apps are called apps for a reason. They are not called applications. My favorite apps do very singular and simple things but do them exceedingly well.

Make An App With Personal Relevance

Your phone is probably the most personal item you own. It contains all your contacts, photos, secrets, etc. The app should be honored to live in your pocket. Every app should have a personal reason to exist to the user.

Understand UI and UEX and Don’t Build Apps, Build Brand Experiences

The User Interface is only a part of the larger user experience. The user experience is a brand experience. The users experience with that app will make them form an opinion about your client and their brand.

There Is No Such Thing As a Port

So you just built a great app and the client now wants you to port the app to Android devices. Not so fast. Not so simple. User’s choose the iPhone or the Android phone because it fits them and the way they want to interact with the device. If you don’t design with that in mind, users will notice. This means you need to think of the project from scratch and leverage the small things you can.

The last part of the presentation was a case study of building the SPIN Play app developed by Bottle Rocket.

Apps Mentioned

TED – check out the Inspire Me button, very clever for people wanting to be entertained for a specific time period.
Instagram – An app with laser focus. Very simple. Very cool.
Steinway Metronome – Great example of a one trick pony but beautifully done.
Flipboard – Off the charts for personal relevance
NikeID – A great brand experience. Upload a photo, get shoes to match!
Pizza Hut – A brand experience to be had before you ever even taste the pizza.

DISCLAIMER: The above apps were used as examples of good work, they were NOT developed by Bottle Rocket.

Alternative Autocomplete UITextField

6:30 pm in Conclave, Presentation by Andrew Wimpy

For a project I am working on, I needed to implement a search bar that would automatically complete the word the user is typing into the search bar and display relevant results. However, I didn’t want this to work like the default search bar functionality in objective c where the search bar is tied to a table view that takes up most of the on screen real estate. Instead I needed this auto complete search bar to visually be more like the search bar on Google. I have attached an example Xcode Project that demonstrates this functionality on an iPhone.

As can be seen in the image above the only two objects needed to make this work are a UITextField and a UITableView. The UITextField will act as our search bar, and the UITableView will be populated with our auto complete elements. Other than that you just need to have the correct logic.

Step 1: Create Objects

First, we will be creating the UITextField and the UITableView. The table and text fields can be configured according to what is needed in your app, but I would always create the UITable with a width of about 2 to 4 pixels less than the text field. This will allow the auto complete functionality to be visually more like the Google search bar. The one thing to note is that the table is initially hidden. This is done because we only want the table to display when the user is typing into the text field.

//Search Bar
txtField = [[UITextField alloc] initWithFrame:CGRectMake(5, 20, 261, 41)];
txtField.borderStyle = 3; // rounded, recessed rectangle
txtField.autocorrectionType = UITextAutocorrectionTypeNo;
txtField.textAlignment = UITextAlignmentLeft;
txtField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
txtField.returnKeyType = UIReturnKeyDone;
txtField.font = [UIFont fontWithName:@"Trebuchet MS" size:22];
txtField.textColor = [UIColor blackColor];
[txtField setDelegate:self];
[self.view addSubview:txtField];
[txtField release];

//Autocomplete Table
autoCompleteTableView = [[UITableView alloc] initWithFrame:CGRectMake(6, 56, 259, tableHeight) style:UITableViewStylePlain];
autoCompleteTableView.delegate = self;
autoCompleteTableView.dataSource = self;
autoCompleteTableView.scrollEnabled = YES;
autoCompleteTableView.hidden = YES;
autoCompleteTableView.rowHeight = tableHeight;
[self.view addSubview:autoCompleteTableView];
[autoCompleteTableView release];

We now need to create an array that will be what we are searching through to populate the autoCompleteTableView. I have included a text file with sample elements to populate this array. We first need to pull the contents of the file into memory and then convert the bytes from the file into a string. This string will then be split around newline characters to create our array. Finally, we will be creating our auto complete array that will hold the elements that correspond with what is being typed in the search bar.

//Pull the content from the file into memory
NSString *filePath = [NSString stringWithFormat:@"/Users/drewnextpression/AutoCompleteTextField/elements.txt"];
NSData* data = [NSData dataWithContentsOfFile:filePath];

//Convert the bytes from the file into a string
NSString* string = [[[NSString alloc] initWithBytes:[data bytes]
length:[data length]
encoding:NSUTF8StringEncoding] autorelease];

//Split the string around newline characters to create an array
NSString* delimiter = @"\n";
NSArray *item = [string componentsSeparatedByString:delimiter];
elementArray = [[NSMutableArray alloc] initWithArray:item];
autoCompleteArray = [[NSMutableArray alloc] init];

Step 2: Text Field Logic

As the user types into the text field, the text will be converted into a substring by using UITextfield’s delegate method shouldChangeCharactersInRange. Once this substring has been created, it will be passed to the method searchAutocompleteEntriesWithSubstring.

The method searchAutocompleteEntriesWithSubstring will compare the substring of the text field against the elements in the element array to see if any of the element’s beginning characters are the same as the substring. This is done by grabbing each element one at a time from the array of elements. An NSRange value is then created that will have the range and location of the substring in the element. Since I wanted the search to be case insensitive I have two different ranges. One NSRange will check for lowercase and another will check for uppercase.

Once these ranges are found, their length can be used to determine if the substring occurred at the beginning of the element. Since NSRange will return a length of 0 if the substring isn’t in the beginning of the current element, we can use this logic to only add elements to the autoCompleteArray that have an NSRange of length != 0.

Finally, the table needs to be unhidden since the user is typing into the text field, and it needs to be reloaded since it is being drawn based on the elements in the autoCompleteArray.

// String in Search textfield
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *substring = [NSString stringWithString:textField.text];
substring = [substring stringByReplacingCharactersInRange:range withString:string];
[self searchAutocompleteEntriesWithSubstring:substring];
return YES;
}

// Take string from Search Textfield and compare it with autocomplete array
- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring {

// Put anything that starts with this substring into the autoCompleteArray
// The items in this array is what will show up in the table view

[autoCompleteArray removeAllObjects];

for(NSString *curString in elementArray) {
NSRange substringRangeLowerCase = [curString rangeOfString:[substring lowercaseString]];
NSRange substringRangeUpperCase = [curString rangeOfString:[substring uppercaseString]];

if (substringRangeLowerCase.length != 0 || substringRangeUpperCase.length != 0) {
[autoCompleteArray addObject:curString];
}
}

autoCompleteTableView.hidden = NO;
[autoCompleteTableView reloadData];
}

Step 3: TableView Logic

As noted in step 2, the table is being drawn based on the elements in the autoCompleteArray. If the array is empty, the table will be drawn with one empty cell. If the array has one element, the table will be drawn with one cell displaying this element. If the array has two elements, the table will be drawn with two cells displaying the elements. If the array has three elements or more, the table will be drawn with three cells and will be scrollable if there are more than three objects. The code for populating the table is found in the table delegate method cellForRowAtIndexPath, and the table drawing functionality is found in the tableview delegate method numberOfRowsInSection.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section {

//Resize auto complete table based on how many elements will be displayed in the table
if (autoCompleteArray.count >=3) {
autoCompleteTableView.frame = CGRectMake(6, 56, 259, tableHeight*3);
return autoCompleteArray.count;
}

else if (autoCompleteArray.count == 2) {
autoCompleteTableView.frame = CGRectMake(6, 56, 259, tableHeight*2);
return autoCompleteArray.count;
}

else {
autoCompleteTableView.frame = CGRectMake(6, 56, 259, tableHeight);
return autoCompleteArray.count;
}
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
static NSString *AutoCompleteRowIdentifier = @"AutoCompleteRowIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier:AutoCompleteRowIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AutoCompleteRowIdentifier] autorelease];
}

cell.textLabel.text = [autoCompleteArray objectAtIndex:indexPath.row];
return cell;
}

When the user clicks on an element in the table, the textfield will be populated with that element and the method finishedSearching will be called. This method will close the keyboard and hide the table.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
txtField.text = selectedCell.textLabel.text;
[self finishedSearching];
}

- (void) finishedSearching {
[txtField resignFirstResponder];
autoCompleteTableView.hidden = YES;
}

Step 4: Closing the Keyboard

I wanted the user to be able to close the keyboard by either pressing the Done button on the keyboard or tapping anywhere on the background. I used the text field’s delegate method textFieldShouldReturn to close the keyboard on a Done button press. Finally, I used the method touchesBegan: withEvent: to close the keyboard when the user touches the background.

// Close keyboard when Enter or Done is pressed
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
BOOL isDone = YES;

if (isDone) {
[self finishedSearching];
return YES;
} else {
return NO;
}
}

// Close keyboard if the Background is touched
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
[super touchesBegan:touches withEvent:event];
[self finishedSearching];
}

Step 5: Clean up and Release

At this point we need to release the autoCompleteArray and elementArray. The table and text field don’t need to be released since we already released them after we initialized them.

- (void)dealloc {
[autoCompleteArray dealloc];
[elementArray dealloc];
[super dealloc];
}

That’s it! Download the AutoCompleteTextField project and give it a go. If you find any bugs or have any suggestions let me know.

Source Code: AutoCompleteTextField.zip

IP Service Contracts

6:30 pm in Conclave, Presentation by Chris Koeberle

Any time money changes hands in software development, a contract is being formed. Writing that contract out gets everyone on the same page and gives them a chance to consider possible outcomes that might not otherwise have occurred to them. With luck, the people involve might even resolve disputes before anyone has made a significant investment of blood, toil, tears, and sweat.

This sample contract is not intended to be a substitute for competent legal representation or a detailed investigation of issues relevant to a particular development engagement. It is meant, instead, to serve as an introduction to issues common to contracts for mobile development, and as a starting place for drafting a (relatively) friendly agreement for a small development project. The associated presentation explains the contract in some depth and explores some issues particular to mobile development.

Obviously, there’s no substitute for a contract which was drafted by an attorney specifically for an engagement, and reviewed exhaustively by the other side’s attorney. But if neither side can justify paying for such legal services, contract templates such as these are likely to be better than nothing. This contract is drafted to be generally fair to both sides, allowing the developer to retain rights to a reusable software library developed for the purposes of the engagement, as well as any patentable technology which may be invented.

Feel free to contact me with any questions or comments!

Presentation: IPServices-Contracts.pdf
Contract Template: softwareAgreement-Template.doc

iOS Sprite Animations with Notifications

6:30 pm in Conclave, Presentation by Justin Leger

On one of my first projects, I needed to do simple sprite animations using UIImageView. When I got into it, I quickly realized that I didn’t have the level of control that I needed.  So I created LIImageView and LIAnimationManagerView. I added the ability to load tile based sprite sheets, numbered sequenced images, UIImage decompression on loading and most importantly Observer Notifications on animation events (Start, Stop, Pause and Loop).

I have attached an example Xcode Project that shows most of all of the functionality of these classes, but play around with it and you’ll soon see the benefit over using the standard animations of UIImageView.

As you can see below, steps 1-6 are pieces of code from the viewDidLoad selector from the projects main ViewController.

Step 1: Importing Headers into View Controller

First things first, let’s import the header files for the new image view and animation manager.

#import "LIImageView.h"
#import "LIAnimationManagerView.h"

Step 2: Load Sprite Sheet

Next, we are going to load the animation sprite sheet. This sprite sheet has all the image animation frames for all the different states of the animation sequence. They are tiled into columns and rows and spaced with a specific Rect size. First we created a string with path to the file resource. Then we load the file into a UIImage using the decompression category class extension I added. This category extension decompresses the image into memory, during the initialization of the UIImage object, so that you don’t see a lag when the animation plays for the first time. Lastly, we define a Rect variable to use with this sprite sheet.

// Load Image
NSString *fileLocation = [[NSBundle mainBundle] pathForResource:@"BrianSheet.png" ofType:nil];
UIImage *image = [[UIImage alloc] initWithContentsOfFileDecompressed:fileLocation];
CGRect spriteRect = CGRectMake(0, 0, 61, 85);

Step 3: Build Animations From Sprite Sheet

Now we are going to build the LIImageView objects. We initialize the object with a tile sprite sheet and pass a start index, end index and a rect size of the sprite. If the sprite sheet dimensions are not dividable by the Rect dimensions then a nil is returned. Indexes are zero based and start in the upper left of the sprite sheet and wrap when it reaches the end of a row. If we have a 5×5 sprite sheet, the first row would contain indexes 0-4, second row would contain 5-9 and so on.

Next we set the repeat count of the animation loops. This is the same as UIImageView, the default value is 0, which specifies to repeat the animation indefinitely.

Now we can set the frame duration of the animation. I preferred this way setting animation timing rather than setting an animation duration.  I have included several predefined values for 5, 10, 15 and 30 FPS, but all you have to do is provide a double value.

// Build Drink Animations
LIImageView *drinkIn = [[LIImageView alloc] initWithTileImage:image fromIndex:12 toIndex:15 fromRect:spriteRect];
drinkIn.animationRepeatCount = 1;
drinkIn.animationFrameDuration = ImageAnimator10FPS;

LIImageView *drinkIdle = [[LIImageView alloc] initWithTileImage:image fromIndex:15 toIndex:15 fromRect:spriteRect];
drinkIdle.animationRepeatCount = 10;
drinkIdle.animationFrameDuration = ImageAnimator5FPS;

LIImageView *drinkOut = [[LIImageView alloc] initWithTileImage:image fromIndex:16 toIndex:22 fromRect:spriteRect];
drinkOut.animationRepeatCount = 1;
drinkOut.animationFrameDuration = ImageAnimator10FPS;

Step 4: Create Animation Manager and Add Animations

Here, we are going to set up an animation manager. This manager is a UIView and is responsible for storing animations by a state name and the loading and unloading playback controls of these animations by state. The managers Rect is usually the same size as the sprite animation size and can be placed anywhere in it parents view.

Animations are added to the manager with a string defining its state. I guess I should have called it a Key, but oh well.

// Create Animation Manager
animationManager = [[LIAnimationManagerView alloc] init];
animationManager.frame = CGRectMake(129, 85, 61, 85);
[self.view addSubview:animationManager];

// Add Drink Animations to Manager
[animationManager addAnimation:drinkIn withState:@"drinkIn"];
[animationManager addAnimation:drinkIdle withState:@"drinkIdle"];
[animationManager addAnimation:drinkOut withState:@"drinkOut"];

Step 5: Add Observers to LIImageView Objects

Here is the part that I really like. Each LIImageView will dispatch a notification when the state of the animation changes (Start, Stop, Pause and Loop). This way I can define a controlled sequence of animations. “drinkIn” loops once and the triggers “drinkIdle” when done. “drinkIdle” plays 10 times then triggers “drinkOut” when it finishes. There are countless possibilities and allows a lot of customization.

So, lets define what we want to happen when a state changes. The code below defines that when the drinkIn animation stops, start playing the drinkIdle animation. The callback selector playDrinkIdleAnimation tells the animation manager to play animation by state “drinkIdle”.

// Drink Event Listeners
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(playDrinkIdleAnimation)
                                             name:ImageAnimatorDidStopNotification
                                           object:drinkIn];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(playDrinkOutAnimation)
                                             name:ImageAnimatorDidStopNotification
                                           object:drinkIdle];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(playWalkAnimation)
                                             name:ImageAnimatorDidStopNotification
                                           object:drinkOut];

Step 6: Clean Up and Release

Now that we have built all the animations from the sprite sheet and added all animations to the manager, we can release our reference to them. It’s now the managers responsibility to release.

// Clean Up
[image release];

[drinkIn release];
[drinkIdle release];
[drinkOut release];

Step 7: Create Notification Callback Selectors

Lastly, we add a few notification callback selectors to tell the animation manager to play an animation by state.

// Drink
- (void) playDrinkInAnimation {
	[animationManager playAnimationByState:@"drinkIn"];
}
- (void) playDrinkIdleAnimation {
	[animationManager playAnimationByState:@"drinkIdle"];
}
- (void) playDrinkOutAnimation {
	[animationManager playAnimationByState:@"drinkOut"];
}

// Walk
- (void) playWalkAnimation {
	[animationManager playAnimationByState:@"walk"];
}

That’s about it. Please download the LIImageViewSample Xcode project and play around with it. Please feel free to let me know if you find any bugs, defects or have any suggestions.

Source Xcode Project: LIImageViewSample.zip