1 / 22

Functional aspects of great native mobile apps

Functional aspects of great native mobile apps. http://www.flickr.com/photos/ourcage/8343799386/. 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?

rachel
Download Presentation

Functional aspects of great native mobile apps

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Functional aspects ofgreat 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 varwin = Ti.UI.createWindow({ backgroundColor : "#FFFFFF", title : "test" }); varlbl = 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" }); varbtnCamera = Ti.UI.createButton({ title : 'Take picture', top : 20 }); btnCamera.addEventListener('click', function() { Titanium.Media.showCamera({ success : function(event) { varphotoTaken = event.media; if (event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO) { varimgView = 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 specializeduser 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: • Add labels to your form, for showing error msgs • In your button click handler, check every input (e.g., with regular expressions) • 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() { // iOSvs 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. ScrollViewRendered nearly the same on iOS & Android var win = Ti.UI.createWindow({ backgroundColor : "#FFFFFF", layout : 'vertical' }); varscrollView = 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. PickerSame 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. TabGroupSame 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. CoverFlowViewOnly available on iOS var win = Ti.UI.createWindow({ backgroundColor : "#FFFFFF" }); varimgs = []; 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. ToolbarOnly available on iOS var win = Ti.UI.createWindow({ backgroundColor: "#FFFFFF" }); varbtnReview = Titanium.UI.createButton({ title : 'Review', style : Titanium.UI.iPhone.SystemButtonStyle.DONE, }); // systemButton specifies a standard appearance (has nothing to do with behavior) varbtnTrash = Titanium.UI.createButton({ systemButton : Titanium.UI.iPhone.SystemButton.TRASH, }); varbtnCancel = Titanium.UI.createButton({ systemButton : Titanium.UI.iPhone.SystemButton.CANCEL }); varspacer = Titanium.UI.createButton({ systemButton : Titanium.UI.iPhone.SystemButton.FLEXIBLE_SPACE }); vartoolbar = Titanium.UI.iOS.createToolbar({ items : [btnCancel, spacer, btnTrash, spacer, btnReview], top : 0, borderTop : false, borderBottom : true }); win.add(toolbar); win.open();

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

More Related