Presentation is loading. Please wait.

Presentation is loading. Please wait.

FUNCTIONAL ASPECTS OF GREAT NATIVE MOBILE APPS

Similar presentations


Presentation on theme: "FUNCTIONAL ASPECTS OF GREAT NATIVE MOBILE APPS"— Presentation transcript:

1 FUNCTIONAL ASPECTS OF GREAT NATIVE MOBILE APPS http://www.flickr.com/photos/ourcage/8343799386/

2 Functionality to go from good to great Why create a native mobile app if you aren't going to use the hardware that is hard or impossible to access in a mobile web app? Other functional considerations related to creating great apps We'll continue the conversation about "great apps" in Unit 5.

3 Accessing phone hardware E.g., Compass, Geolocation, Accelerometer, Shake, Sound, Camera Some of these are robustly supported only in certain mobile browsers (e.g., compass in Safari) but available and reliable in native apps Others are available in most mobile browsers (e.g., geolocation), but more features are available in native apps

4 Compass var win = Ti.UI.createWindow({ backgroundColor : "#FFFFFF", title : "test" }); var lbl = Ti.UI.createLabel(); win.add(lbl); win.open(); function display(e) { lbl.text = e.heading ? 'compass:' + e.heading.magneticHeading + ',when:' + (new Date()).getTime() : 'null heading'; // see also the trueHeading property, used along with location tracking } // you can get heading just once with getCurrentHeading() or you can monitor it… Ti.Geolocation.addEventListener("heading", display); // use removeEventListener when done!!

5 Geolocation function display(e) { lbl.text = e.coords ? 'lat:' + e.coords.latitude + ',lon:' + e.coords.longitude + ',when:' + (new Date()).getTime() : 'null coords'; } Ti.Geolocation.preferredProvider = Titanium.Geolocation.PROVIDER_GPS; Ti.Geolocation.purpose = "CS496"; Ti.Geolocation.accuracy = Titanium.Geolocation.ACCURACY_BEST; // can use lower accuracy Ti.Geolocation.distanceFilter = 10; // can use broader filter if (Titanium.Geolocation.locationServicesEnabled === false) { alert('You need to turn GPS on.'); } else { // to get location just once Ti.Geolocation.getCurrentPosition(display); // to continually get location Ti.Geolocation.addEventListener('location', display); // unregister with Ti.Geolocation.removeEventListener(display) when done with it! }

6 Accelerometer When the device isn’t accelerating, it’s more of a “gravity-meter” than an accelerometer var listener = function(e) { lbl.text = 'accel: ' + e.x + ';' + e.y + ';' + e.z; }; Ti.Accelerometer.addEventListener('update', listener); Ti.Accelerometer.removeEventListener('update', listener);

7 Shake Ti.Gesture.addEventListener('shake', fn); Ti.Gesture.removeEventListener(fn); // No API for just retrieving once (obviously?) // Seems to only detect really strong shakes (?)

8 Key cautions Accessing this specialized hardware is very battery-intensive Option #1: Just retrieve value once – Use setTimeOut every few minutes if needed Option #2: Register for the event listener – Look into the specialized APIs for filtering events E.g., "only fire a geolocation event on change >100 meters" – Unregister your event listener as soon as possible

9 Camera var win = Ti.UI.createWindow({ backgroundColor : "#FFFFFF", title : "test" }); var btnCamera = Ti.UI.createButton({ title : 'Take picture', top : 20 }); btnCamera.addEventListener('click', function() { Titanium.Media.showCamera({ success : function(event) { var photoTaken = event.media; if (event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO) { var imgView = Titanium.UI.createImageView({ left : 10, width : 300, height : 300, image : photoTaken }); win.add(imgView); } }, cancel : function(event) { alert('cancel'); }, error : function(event) { alert('error'); } }); win.add(btnCamera); win.open();

10 Other functional considerations Great apps also have functionality for: – Validating inputs, managing state throughout an application's lifecycle – Taking advantage of relevant specialized user interface controls and views – Selectively applying platform-specific APIs

11 Input validation: Assuring that your app's state is initialized from user data correctly Sadly, form validation is very underdeveloped in Titanium Best approach is to: 1.Add labels to your form, for showing error msgs 2.In your button click handler, check every input (e.g., with regular expressions) 3.If an input is invalid, set an error message; else, clear error message(s) and continue.

12 Handling lifecycle events Apps can be paused and then resumed – For example, if user goes to home screen and then comes back to your app – iOS and Android have slightly different events, but Titanium hides some of this from you On pause, – Save any state that cannot be lost, release resources On resume, – Reinitialize from saved state, reinitialize resources

13 Example of handling lifecycle events Ti.App.addEventListener('pause',function(e) { // call removeEventListener for hardware // save user data to local storage }); Ti.App.addEventListener('resume',function(e) { // reload user data from local storage // call addEventListener for hardware });

14 You can also detect Android-specific lifecycle events Detecting your execution environment function isAndroid() { // iOS vs Android return Ti.Platform.name == 'android'; } Accessing Android-specific events (another video will cover the Android lifecycle in detail) Ti.Android.currentActivity.addEventListener('create', function(e) { // called when the app's current activity (window) is created }); Ti.Android.currentActivity.addEventListener('start', function(e) { … }); Ti.Android.currentActivity.addEventListener('resume', function(e) { … }); Ti.Android.currentActivity.addEventListener('pause', function(e) { … }); Ti.Android.currentActivity.addEventListener('stop', function(e) { … });

15 Speaking of which… Great apps take selective advantage of functionality that is platform-specific – Yes, this decreases portability – But it has the potential to improve the user experience and benefits given to users And use specialized user interface controls – That might be rendered in platform-specific ways

16 Judicious use of specialization Specialization driven by guidelines & hardware – E.g., guidelines: iOS apps use toolbars to navigate – E.g., hardware: Android phones have 2+ buttons FYI, you can also specialize images – Depending on platform and screen density (essentially dots per inch) – Customize using Resources subdirectories

17 ScrollView Rendered nearly the same on iOS & Android var win = Ti.UI.createWindow({ backgroundColor : "#FFFFFF", layout : 'vertical' }); var scrollView = Ti.UI.createScrollView({ contentWidth : 'auto', contentHeight : 'auto', showVerticalScrollIndicator : true, height : Ti.UI.FILL, width : Ti.UI.FILL, layout : 'vertical' }); for (var i = 0; i < 100; i++) scrollView.add(Ti.UI.createLabel({ text : "item " + i, color: '#000000' })); win.add(scrollView); win.open();

18 Picker Same code, rendered differently on iOS & Android var win = Ti.UI.createWindow({ backgroundColor: "#FFFFFF", layout: 'vertical' }); var picker = Ti.UI.createPicker({ selectionIndicator: true }); var items = []; items[0]=Ti.UI.createPickerRow({title:'OSU'}); items[1]=Ti.UI.createPickerRow({title:'UO'}); items[2]=Ti.UI.createPickerRow({title:'UW'}); picker.add(items); win.add(picker); win.open();

19 TabGroup Same code, rendered differently on iOS & Android // From the wizard-generated code… //create module instance var self = Ti.UI.createTabGroup(); //create app tabs var win1 = new Window(L('home')), win2 = new Window(L('settings')); var tab1 = Ti.UI.createTab({ title: L('home'), icon: '/images/KS_nav_ui.png', window: win1 }); win1.containingTab = tab1; var tab2 = Ti.UI.createTab({ title: L('settings'), icon: '/images/KS_nav_views.png', window: win2 }); win2.containingTab = tab2; self.addTab(tab1); self.addTab(tab2); You can just use Ti.UI.createWindow(…), FYI

20 CoverFlowView Only available on iOS var win = Ti.UI.createWindow({ backgroundColor : "#FFFFFF" }); var imgs = []; for (var i = 1; i <= 3; i++) imgs.push({ image : 'img' + i + '.jpg', height : '33%', width : '33%' }); var view = Titanium.UI.iOS.createCoverFlowView({ backgroundColor : '#00000', images : imgs, width : Ti.UI.FILL, height : Ti.UI.FILL }); win.add(view); win.open(); http://www.flickr.com/photos/musicbook/3525997685 http://www.flickr.com/photos/kbcool/2226493331 http://www.flickr.com/photos/ranh/2390167998

21 Toolbar Only available on iOS var win = Ti.UI.createWindow({ backgroundColor : "#FFFFFF" }); var btnReview = Titanium.UI.createButton({ title : 'Review', style : Titanium.UI.iPhone.SystemButtonStyle.DONE, }); // systemButton specifies a standard appearance (has nothing to do with behavior) var btnTrash = Titanium.UI.createButton({ systemButton : Titanium.UI.iPhone.SystemButton.TRASH, }); var btnCancel = Titanium.UI.createButton({ systemButton : Titanium.UI.iPhone.SystemButton.CANCEL }); var spacer = Titanium.UI.createButton({ systemButton : Titanium.UI.iPhone.SystemButton.FLEXIBLE_SPACE }); var toolbar = Titanium.UI.iOS.createToolbar({ items : [btnCancel, spacer, btnTrash, spacer, btnReview], top : 0, borderTop : false, borderBottom : true }); win.add(toolbar); win.open();

22 Menu Only available on Android var win = Ti.UI.createWindow({ fullscreen : true }); var activity = win.activity; activity.onCreateOptionsMenu = function(e) { var menu = e.menu; for (var i = 0; i < 4; i++) { var menuItem = menu.add({ title : "Choice " + i }); menuItem.addEventListener("click", function(e) { alert("Your choice has been noted.") }); } }; win.open();


Download ppt "FUNCTIONAL ASPECTS OF GREAT NATIVE MOBILE APPS"

Similar presentations


Ads by Google