FROM IDEA TO APPor how we roll at Small Town Heroes
@bramus | Opleiding Elektronica-ICT, Odisee | 02/12/15
All work, no and play
#ikdoeict Small Town Heroes
I’m a former lecturer Web & Mobile, now into breaking builds at Small Town Heroes
So you have this great idea for an app
• Evaluate your idea• Is it a good idea?• Will it help people?• How’s the competition doing?• Is there a market?
• Plan your app• Features• Define the MVP• Design• App Flow (Wireframes)
http://yvonnelao.com/2011/04/28/mobile-app-user-flow-chart/
Resulting Wireframes
FROM IDEA TO APPor how we roll at Small Town Heroes
@bramus | Opleiding Elektronica-ICT, Odisee | 02/12/15
FROM IDEA TO APPor how we roll at Small Town Heroes
@bramus | Opleiding Elektronica-ICT, Odisee | 02/12/15
FROM WIREFRAMES TO APPor how we roll at Small Town Heroes
@bramus | Opleiding Elektronica-ICT, Odisee | 02/12/15
FROM MVP TO APPor how we roll at Small Town Heroes
@bramus | Opleiding Elektronica-ICT, Odisee | 02/12/15
https://adactio.com/journal/4437
If you’re looking for the more honest, truthful answer to pretty much any question on web
design and usability, here it is:
It depends.
It Depends (TM)
https://adactio.com/journal/4437
It Depends (TM)
If you’re looking for the more honest, truthful answer to pretty much any question on web
design and usability, here it is:
It depends.
https://developer.apple.com/programs/enroll/
Apple Developer License
https://developer.apple.com/programs/enroll/
Apple Developer License
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html
Objective-C
http://developer.android.com/distribute/googleplay/start.html
Google Play Developer License
http://developer.android.com/distribute/googleplay/start.html
Google Play Developer License
http://developer.android.com/tools/studio/index.html
Android Studio
https://play.google.com/apps/publish/
Google Play Developer Console
https://play.google.com/apps/publish/
Google Play Developer Console
http://androidreviewtimes.xormedia.com/
Average Play Store Review Times
→ If you know HTML/CSS/JavaScript, you know how to build a mobile app
HTML
You, after “Webtechnieken”
Ionic = CSS Framework
http://ionicframework.com/docs/components/
Ionic = JavaScript Components
Ionic Component = Angular directive + behavior (+ Angular delegate)
Bootstrapitis
http://www.novolume.co.uk/blog/all-websites-look-the-same/
b. Native App: Use WebViews
Host some of your views online so that you can change it anytime you want.
Native-Webview Communication with JockeyJS
https://github.com/tcoulter/jockeyjs
// Send an event to JavaScript, passing a payload.// payload can be an NSDictionary or NSArray, or anything that is serializable to JSON.// It can be nil.[Jockey send:@"event-name" withPayload:payload toWebView:webView];
// If you want to send an event and also execute code within the iOS app when all// JavaScript listeners have finished processing.[Jockey send:@"event-name" withPayload:payload toWebView:webView perform:^{ // Respond to callback.}];
// Listen for an event from iOS and log the payload.Jockey.on("event-name", function(payload) { console.log(payload);});
Example
div(ng-switch="'featureInvitefriends' | setting : false")
div(ng-switch-when="false")
.item.item-divider.item-info(ng-bind-html="'CREATE_CHANNEL.SHARE.EXPLANATION' | translate")
a.item.item-icon-left(ng-click="doShareGroup(id, title, share_url)")i.icon.icon-add| {{ 'CREATE_CHANNEL.SHARE.LABEL' | translate }}
div(ng-switch-when="true")
.item.item-divider.item-info(ng-bind-html="'CREATE_CHANNEL.INVITE.EXPLANATION' | translate")
.item.item-dividerion-item.friend(ng-repeat="friend in friends.list", ng-click="doInvite(friend)")
img(ng-src="{{ friend.thumbnailURL }}").name {{ friend.firstName }} {{ friend.lastName }}
Let your views show or not show a feature depending on a setting
Native: Method Swizzling#import #import "UIViewController+Logging.h"@implementation UIViewController (Logging) + (void)load { static dispatch_once_t once_token; dispatch_once(&once_token, ^{ SEL viewWillAppearSelector = @selector(viewDidAppear:); SEL viewWillAppearLoggerSelector = @selector(logged_viewDidAppear:); Method originalMethod = class_getInstanceMethod(self, viewWillAppearSelector); Method extendedMethod = class_getInstanceMethod(self, viewWillAppearLoggerSelector); method_exchangeImplementations(originalMethod, extendedMethod); }); } - (void) logged_viewDidAppear:(BOOL)animated { [self logged_viewDidAppear:animated]; NSLog(@"logged view did appear for %@", [self class]); }@end
http://spin.atomicobject.com/2014/12/30/method-swizzling-objective-c/
Hybrid: Load extra JS/CSSvar loadScripts = function(array, callback) {
var loader = function(src, handler) {var script = document.createElement('script');script.src = src;script.onload = script.onreadystatechange = function() {
script.onreadystatechange = script.onload = null;handler();
}var head = document.getElementsByTagName('head')[0];(head || document.body).appendChild(script);
};
(function() {if (array.length!=0) {
loader(array.shift(), arguments.callee);} else {
callback && callback();}
})();
};
http://stackoverflow.com/a/1867135/2076595
Angular/Ionic: Decorate itangular.module('ionHeaderBarTapOverride', [])
// Add our custom tapToScroll implementation on ionHeaderBar (with a higher priority).directive('ionHeaderBar', ['$ionicScrollDelegate', function($ionicScrollDelegate) {
return {restrict: 'E',priority: 100,link: function($scope, $element, $attr) {
// YOUR CODE HERE}
};}])
// Remove Ionic's tapToScroll implementation from ionHeaderBar.config(function($provide) {
$provide.decorator('ionHeaderBarDirective', ['$delegate', function($delegate) {$delegate.shift(); // It's the first one. Delete itreturn $delegate;
}]);
});
http://stackoverflow.com/a/18425418/2076595 http://stackoverflow.com/a/23209542/2076595
Git Branching Strategy
• Develop on master• Result = “beta”or “staging” builds• → Send these to your beta testers
• Promote master to release• Result = “production” or “appstore” builds• → Send these to the App Store / Play Store / …
Continuous Integration: how?
→ It’s one big hack (Combination of circle.yml, Makefile, bash scripts, build hooks, etc) but it works
# Inject settings for BUILD_ENV into config files- BUILD_ENV=$(ENVIRONMENT) grunt string-replace:settings
# Compile src into www, with staging environment- BUILD_ENV=staging grunt build
## Build Android- BUILD=$CIRCLE_BUILD_NUM BUNDLE_ID="be.smalltownheroes.vrt.allesweter.$ENVIRONMENT" BUILD_ENV=$(ENVIRONMENT) make android- ./scripts-ci/archive_apk.sh staging- ./scripts-ci/distribute_apk.sh
# Build IOS- BUILD=$CIRCLE_BUILD_NUM BUNDLE_ID="be.smalltownheroes.vrt.allesweter.$ENVIRONMENT" BUILD_ENV=$(ENVIRONMENT) make ios- ./scripts-ci/archive_ipa.sh staging- ./scripts-ci/distribute_ipa.sh staging
Continuous Integration: how?
→ It’s one big hack (Combination of circle.yml, Makefile, bash scripts, build hooks, etc) but it works
# Inject build number and bundle id into config.xmlAPP_BUILD=$(BUILD) APP_ID=$(BUNDLE_ID) node scripts-ci/update_config_xml.js
# Install Ionic Platforms and Pluginsrm -rf platformsrm -rf pluginsionic platform add android
# Inject Crashlytics./scripts-ci/crashlytics-android.sh
# Build itANDROID_NAME="$(DISPLAY_NAME)" ionic build android --device --release
FROM IDEA TO APPor how we roll at Small Town Heroes
@bramus | Opleiding Elektronica-ICT, Odisee | 02/12/15
Top Related