Upload
gian-lowe
View
214
Download
1
Tags:
Embed Size (px)
Citation preview
MOBILE DEVELOPMENT
CHRIS FRANZSYSTEMS CONSULTANT / ADVANTAGE EVANGELIST
MAY 2011
2 – European Advantage Conference – May 2011
AGENDA
• Introduction• iOS• Android• Windows 7 Phone
3 – European Advantage Conference – May 2011
INTRODUCTION
• Picking a platform & development environment–Market share– Devices (features, cost)– Development community
User groups Packages or libraries available
– Cost of development Developer license
4 – European Advantage Conference – May 2011
PLATFORMS
5 – European Advantage Conference – May 2011
IPOD TOUCHIPHONEIPAD
6 – European Advantage Conference – May 2011
OVERVIEW
• Supported Devices– iPod Touch– iPhone– iPad
• Development Tools– xCode v3.2 and Interface Builder or xCode v4–Objective-c– Emulators for iPhone and iPad
• Recommended Reading: Head First iPhone Development by Dan & Tracey Pilone
7 – European Advantage Conference – May 2011
APPLICATION ARCHITECTURE
• Follows MVC Model• Application Components– Views– Frameworks– Resources
8 – European Advantage Conference – May 2011
ODATA OBJECTIVE-C CLIENT
• Available from Codeplexhttp://odataobjc.codeplex.com• Consists of Two Components–MSODataLib– oDataGen
• Using With Your Project– Add location of MSODataLib source to project Header Path– Add location of libMSODataLib.a to project Library Path– Add libMSODataLib.a to project Frameworks
9 – European Advantage Conference – May 2011
GENERATING DATA CLASSES
• oDataGen creates data classes based on the metadata provided by the Advantage Web API• Syntaxodatagen /uri=<data service Uri> [/out=<output file path>] [auth=windows|acs /u=username /p=password [/sn=servicenamespace [/at=appliesto] ] [/ups=yes|no] ]
• Exampleodatagen /uri=https://localhost:6282/adsweb/example_db/1/ /out=/Users/chrisfranz/projects/tasksapp /u=adssys
10 – European Advantage Conference – May 2011
EXAMPLE CLASS/** * @interface:Tasks * @Type:EntityType * @key:id* */@interface tasks_Model_Entities_Tasks : ODataObject{
/*** @Type:EntityProperty* NotNullable* @EdmType:Edm.Int32*/NSNumber *m_id;
/*** @Type:EntityProperty* NotNullable* @EdmType:Edm.Decimal*/NSDecimalNumber *m_rowversion;
/*** @Type:EntityProperty* @EdmType:Edm.String* @MaxLength:50* @FixedLength:true*/NSString *m_name;
/*** @Type:EntityProperty* @EdmType:Edm.DateTime*/NSDate *m_started;
/*** @Type:EntityProperty* @EdmType:Edm.DateTime*/NSDate *m_finished;
}
11 – European Advantage Conference – May 2011
EXAMPLE CLASS
@property ( nonatomic , retain , getter=getid , setter=setid )NSNumber *m_id;@property ( nonatomic , retain , getter=getrowversion , setter=setrowversion )NSDecimalNumber *m_rowversion;@property ( nonatomic , retain , getter=getname , setter=setname ) NSString *m_name;@property ( nonatomic , retain , getter=getstarted , setter=setstarted )NSDate *m_started;@property ( nonatomic , retain , getter=getfinished , setter=setfinished )NSDate *m_finished;
+ (id) CreateTasksWithid:(NSNumber *)aid rowversion:(NSDecimalNumber *)arowversion;- (id) init;- (id) initWithUri:(NSString*)anUri;@end
+ (id) CreateTasksWithid:(NSNumber *)aid rowversion:(NSDecimalNumber *)arowversion;- (id) init;- (id) initWithUri:(NSString*)anUri;@end
12 – European Advantage Conference – May 2011
INITWITHURI METHOD- (id) initWithUri:(NSString*)anUri { if(self=[super initWithUri:anUri]) { [self setBaseURI:anUri]; m_OData_hasStream.booleanvalue=NO; mProperties *obj;
obj=[[mProperties alloc]initWithEdmType:@"Edm.Int32" MaxLength:@"" MinLength:@"" FixedLength:NO Nullable:NO Unicode:NO ConcurrencyMode:@"" FC_TargetPath:@"" FC_KeepInContent:YES FC_SourcePath:@"" FC_ContentKind:@"" FC_NsPrefix:@"" FC_NsUri:@""]; [m_OData_propertiesMap setObject:obj forKey:@"m_id"]; [obj release];
obj=[[mProperties alloc]initWithEdmType:@"Edm.Decimal" MaxLength:@"" MinLength:@"" FixedLength:NO Nullable:NO Unicode:NO ConcurrencyMode:@"" FC_TargetPath:@"" FC_KeepInContent:YES FC_SourcePath:@"" FC_ContentKind:@"" FC_NsPrefix:@"" FC_NsUri:@""]; [m_OData_propertiesMap setObject:obj forKey:@"m_rowversion"]; [obj release];
obj=[[mProperties alloc]initWithEdmType:@"Edm.String" MaxLength:@"50" MinLength:@"" FixedLength:YES Nullable:NO Unicode:YES ConcurrencyMode:@"" FC_TargetPath:@"" FC_KeepInContent:YES FC_SourcePath:@"" FC_ContentKind:@"" FC_NsPrefix:@"" FC_NsUri:@""]; [m_OData_propertiesMap setObject:obj forKey:@"m_name"]; [obj release];
obj=[[mProperties alloc]initWithEdmType:@"Edm.DateTime" MaxLength:@"" MinLength:@"" FixedLength:NO Nullable:NO Unicode:NO ConcurrencyMode:@"" FC_TargetPath:@"" FC_KeepInContent:YES FC_SourcePath:@"" FC_ContentKind:@"" FC_NsPrefix:@"" FC_NsUri:@""]; [m_OData_propertiesMap setObject:obj forKey:@"m_started"]; [obj release];
obj=[[mProperties alloc]initWithEdmType:@"Edm.DateTime" MaxLength:@"" MinLength:@"" FixedLength:NO Nullable:NO Unicode:NO ConcurrencyMode:@"" FC_TargetPath:@"" FC_KeepInContent:YES FC_SourcePath:@"" FC_ContentKind:@"" FC_NsPrefix:@"" FC_NsUri:@""]; [m_OData_propertiesMap setObject:obj forKey:@"m_finished"]; [obj release];
NSMutableArray *anEntityKey=[[NSMutableArray alloc]init]; [anEntityKey addObject:@"id"]; [m_OData_entityKey setObject:anEntityKey forKey:@"Tasks"]; [anEntityKey release]; } return self;}
13 – European Advantage Conference – May 2011
ACCESSING ADS DATA
// Get all tasks from our servicetasksData *proxy = [[tasksData alloc]
initWithUri:@"http://server:6272/adsweb/example_db/v1/" credential:nil];QueryOperationResponse *response = [proxy execute:@"Tasks"];_tasksArray = [response getResult];[_tasksArray retain];NSLog( @"got %d tasks back", [_tasksArray count] );
// Log contents of first row as an exampleTasks *task = [_tasksArray objectAtIndex:1];NSLog( @"Row1: TaskName: %@ StartDate: %@", [task getname], [task getstarted] ? [[task getstarted] description] : @"Not Yet" );
14 – European Advantage Conference – May 2011
ANDROID
ANDROID
15 – European Advantage Conference – May 2011
OVERVIEW
• Android OS - http://www.android.com/– Android is an open source mobile platform– Developed by the Open Handset Alliance– Strongly driven by Google– Supports multiple devices and carriers
• Development – http://developer.android.com/– Built on Linux micro kernel– Applications written in Java– SDK and emulator are free– Eclipse IDE with plug-in is used for development
16 – European Advantage Conference – May 2011
APPLICATION OVERVIEW
• Architecture– Applications do not exit– UI can be paused, resumed, or terminated by system at
anytime– A single thread handles all UI for entire device
No blocking or long calls in UI thead
• Building Blocks– Activities– Service and Content Providers– Intents and Broadcast Receivers
17 – European Advantage Conference – May 2011
DESIGN PATTERNS FOR DATA ACCESS
• Three suggested design patterns– Content Provider API– Content Provider API with SyncAdapter– Service API
• Video from Google IO 10 covers all three patterns– http://www.google.com/events/io/2010/sessions/developin
g-RESTful-android-apps.html
18 – European Advantage Conference – May 2011
CONTENT PROVIDER API PATTERN
Activity and CursorAdapter
Content Provider
Asynchronous Service
oData Client
Processor
1. query, insert, update, delete
7. notification
2. startService(intent) 5. returned data
3. oData request
4. GET/POST/
PUT/DELETE
6. update\insert
8. requery
19 – European Advantage Conference – May 2011
CONTENT PROVIDER API PATTERN
• Activity and Cursor Adapter– Displays data– Use ContentObservers to receive notifications of data
changes– Should re-query data when notified– Android CursorAdaptors and ListViews handle notifications
automatically• Content Provider– Caches data in local SQLite database– Requests oData call from Asynchronous Service– Returns local cached data– Sends notifications when data changes
20 – European Advantage Conference – May 2011
CONTENT PROVIDER API PATTERN
• Asyncronous Service– Sets up oData request– Checks for existing oData request– Registers the Processor callback with the thread– Starts new thread to perform oData request– Handles callback even if requesting Activity is terminated
• Processor– Callback used to process results from oData query– Uses the Content Provider to update local SQLite database
Causes Content Provider to notify observers
21 – European Advantage Conference – May 2011
ODATA CLIENT
• Two existing oData clients for Android– Restlet http://www.restlet.org/– oData4j http://code.google.com/p/odata4j/
• Both clients work with Advantage and are actively being developed• Provide slightly different licenses
22 – European Advantage Conference – May 2011
EXAMPLEimport org.restlet.ext.odata.Query;import com.advantage.example.android.quick.task.tasks.model.entities.Tasks;
public class Main extends Activity { private static final String TAG = Main.class.getSimpleName(); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TasksModelService model = new TasksModelService();; Query<Tasks> query = model.createTasksQuery("/Tasks"); try { query.execute(); } catch (Exception e) { e.printStackTrace(); } for ( Tasks task : query) { Log.i(TAG, task.getName()); } }}
23 – European Advantage Conference – May 2011
WINDOWS PHONE 7
24 – European Advantage Conference – May 2011
WINDOWS 7 PHONE
• Tools– Visual Studio 2010 (express is free, even for commercial use)–Windows Phone 7 Developer Tools (work in progress)– Phone emulator works very well
25 – European Advantage Conference – May 2011
CONNECTING TO ADS
oData Proxy Class or Object - Add Service Reference dialog
26 – European Advantage Conference – May 2011
ACCESSING ADS DATA
• Use the proxy class (object) to access tables
Uri serviceUri = new Uri( “http://localhost:6272/adsweb/example/v1" );
Context = new testddData( serviceUri );
IEnumerable<Customers> query;
query = from c in context.Customers select c;
IList<Customers> cList = query.ToList();
foreach ( Customers c in cList )
Console.WriteLine( "{0,4} {1,10} {2,10}", c.ID, c.Name, c.Location );
27 – European Advantage Conference – May 2011
SILVERLIGHT
private void Window_Loaded( object sender, RoutedEventArgs e ){ var context = new testdd.testddData( new Uri( “http://localhost:6272/adsweb/example/v1" ));
var query = from c in context.Customers select c;
DataContext = query.ToList();}
<TextBox Text="{Binding Location}" Name="txtLocation" />
28 – European Advantage Conference – May 2011
MORE
• Example videos on MSDN– http://msdn.microsoft.com/en-us/data/cc300162