Tumgik
dotnetkow · 8 years
Text
2016 Year In Review
Tumblr media
I had a great 2016!  Like any year, there are always ups and downs, but I really enjoy reflecting back on everything, especially the positive things I've accomplished.  It's incredible how much you can do in a year!  Here are the highlights.
Personal
Tumblr media
A complete focus on health, exercise, and wellness completely transformed me for the better. I feel a million times better mentally, sleep better, and have the best mobility/strength in years. There's much more work to do be done, but that's OK - 2016 was all about laying the foundation.  It's a marathon, not a race, after all!
Began seeing a Personal Trainer in June (have had ~20 sessions). It’s been a fantastic investment: I'm losing weight, increasing my strength (and can tell!), and improving my mobility (so important since I work a desk job!).
Hiked many trails, including Rattlesnake Ledge for the second time in August. The first time, in Fall 2015, was very tough and demotivating - it’s all uphill switchbacks! After a lot of hard work over many months, the 2nd time around was much better: I made it all the way up without stopping once. 
Plenty of new, fun activities: brewed my first beer, attended my first rap concert, first first class flight...
Travel
Tumblr media
My wife and I flew somewhere or had someone visit us almost every month! This was absolutely intentional, as we made it a big priority of ours to explore the West Coast.
9 "groups" of friends visited us in Seattle (15 people total)
Visited 10 unique states (way too much flying!)
Continued exploration of the West Coast and beyond:
Walla Walla, WA (wine!)
San Francisco (Microsoft Build conference)
Las Vegas (college buddies)
Columbus, Ohio (Rock on the Range concert weekend)
Olympic National Park, WA (w/in-laws)
San Antonio and Austin, TX (Lisa conference and visiting friends)
Surprise road trip up and down the Pacific Coast highway 101! (WA, Oregon, CA)
Milwaukee, WI (Buddy's bachelor party... Go! Marquette!)
Chicago, IL and Minneapolis, MN (Buddy's wedding and family reunion)
Denver, CO (GABF and BeerSwift launch)
Leavenworth, WA (Bavarian town weekend getaway)
Chicago, IL and Madison, WI (home for the holidays)
...and already lots planned for 2017!
Slalom 
Tumblr media
I had a wonderful, very challenging first full year at Slalom. Looking forward to year 2!
YTD Utilization: 105.03%
2 major clients
Over 50 hours of internal training/leadership classes
Participated in many fun work events (even tried Rowing once at 6am on a Saturday!)
Tons of Slalom Toastmasters meetings at 7am on Wednesdays, leading to... my Slalom Speaks speech! (above pic)
App Business
Tumblr media
This year, I focused less on Apps and more on health, Slalom, travel, etc.  In 2017, I’ll be refocusing on Fitwatchr and BeerSwift. I tracked hours worked this year for the first time.  I put in over 180 hours of work on nights/weekends, about 4.5 40 hour work weeks’ worth of time. Time went spent!
3 years of selling Apps!  On October 4th, 2013, I got my first iOS app sale.
Over 35,000 users across 5 apps!
Continued to maintain an (almost) 3 year streak: selling 1 or more apps every single day since February 2014!
Reached just short of 2,000 support tickets to date. With 35,000 users, that's 5.7% of my user base that has written in over 3 years.
Finally launched BeerSwift at Great American Beer Festival (above pic)
Close to launching my first Pluralsight developer course (Q1 2017) on PhoneGap Build
Cheers to a happy, healthy 2017!
Tumblr media
0 notes
dotnetkow · 8 years
Text
Revenge of the CSP: iOS 10.2 and UIWebView Issue Resolved
This past weekend, I upgraded my iPhone to iOS 10.2.  All was well, until I happened to open one of my PhoneGap apps and saw some weird freezing issues.  Upon further investigation, they were Content Security Policy issues, seen in Console output as:
Refused to load frame 'gap://ready' because it violates the following Content Security Policy directive: "default-src *". For reference, in PhoneGap Build, I’m using PhoneGap version cli-6.3.0 (iOS 4.2.0 / Android 5.2.1 / Windows 4.4.1).  
It appears as though in one of the recent iOS 10.X updates, Content Security Policies became stricter under the UIWebView (they're already like that if you use the newer WKWebView).
Not fun (and fortunately, rare) to have an OS upgrade completely break an app! Fortunately, the fix was straight forward.
In index.html, I had:  default-src *;
I changed it to: default-src 'self’ gap:;
I had: (no connect-src directive)
I added a "connect-src" directive, needing to allow connections to Fitbit’s API. Just specifying the root URL works here - no need to specify every single endpoint:  connect-src: https://api.fitbit.com;
I had: (no img-src directive)
I added an "img-src" directive, which allows external images to be loaded:     img-src * data:;
Here's the final CSP my app is using.  Note that your app may need different values! For more details, Mozilla has great documentation.
<meta http-equiv="Content-Security-Policy" content="default-src 'self' gap: mailto:; connect-src https://api.fitbit.com; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; img-src * data:; media-src *">
0 notes
dotnetkow · 8 years
Text
Celebrating 1 Year at Slalom Seattle
Tumblr media
"No worries on PTO/working-offline around the holidays…we’ll work something out that fits your schedule."
I had just nervously spent 30 minutes crafting the perfect email, asking my new manager (whom I had yet to meet) about time off and working remotely during the holidays. Above is his quick, one line response.  Could it really be that simple?  It was late October 2015, and I was about to start a new role at Slalom.  Due to coordinating flights home with family, I wanted to get ahead of the question.  As it turned out, it really was that simple!
Last month was my one year anniversary with Slalom.  Along with getting to know the city of Seattle, it's been quite the journey.  Overall, I had a great year and am looking forward to 2017.  Here's a recap:
Challenges
I present a ton of amazing highlights below, but I'm not only going to write about the good stuff.  No matter how rosy a picture I paint, no company is perfect.  
I only had one major challenge this year, in the beginning months of my first project.  As much as I'd love to share details because I'm all about transparency, it would be one-sided and thus not fair. That said, the situation involved working with some very toxic individuals.  For too long, I put up with it without saying anything.  I had my excuses, of course: being brand new and not wanted to "rock the boat" too early on, not knowing yet if toxic people/unsustainable working hours were part of Slalom's culture (they're not!), and more. When I finally came to my senses, Slalom management was swift and... "corrected the issue".  I am very appreciative of their support and bias for action. Overall, it was a good experience to learn from:
- I no longer have any tolerance for toxic/negative people; I'll cut them out of my life right away.
- For unpleasant people whom I must be around: I've rediscovered the idea that my happiness is mine and mine alone to control; someone can affect that only if you let them!
- I awakened a dormant strength: These days I'm extremely confident/outspoken while still remaining humble/respectful. I have no issues speaking up for what's right, though.
Highlights (Where do I begin?!)
Core Values: It says on our Core Values page that we take them seriously.  We really, really do.  I've seen them represented in big actions (quarterly events, happy hours) and in small ones (open conversations with the CEO or Consultants I've just met).  My personal favorites are "Do What is Right, Always" (we've fired clients if they're not a good fit) and "Stay Humble and Curious" (most folks I've met are incredibly down to earth, want to learn from you, share ideas, and get to know you).
Flexibility & Trust: Slalom prides itself on running local market offices; travel is optional.  This is huge because it supports families and respects work/life balance - you don't have to spend weeks living out of a suitcase. They recognize that if you're jet lagged and unhappy all the time, you can't do your best work.  Also, I was nervous for months about my ongoing travel/remote work requests, but each time my People Manager allayed my fears: *Shrug*..."I don't care what you do, I trust you to be honest and get your work done."  I keep waiting for the other shoe to drop, but it hasn't.  You're treated like an adult at Slalom, no micro management necessary!
Transparency: At the beginning of the year, our CFO told us that Slalom continues to save aggressively and plan for the next economic downturn. I almost fell out of my chair. What? Who does that these days? Seriously, my respect for management shot through the roof that day. No IPO/selling out here - they really want to build a private, long-term company that “our grandchildren will work at someday.”
Business details are shared with everyone.  This is huge for many reasons: transparency gives us confidence in the business and allows for open discussion/feedback.  I struggled in the past with understanding the business-side of things because details were hidden from anyone below management.  The issue I took with that was, how am I supposed to grow and move up the managerial ladder if I can't learn from real situations? I can read about it in a book, but it's not the same.  The "why" behind decisions is typically not open to discussion: Financials. Layoffs. Acquisitions.  Politics ("No, he wasn't actually promoted... this was really a demotion and a signal that he needs to improve or leave the company." "Oh.").  I was fortunate in my last role to have a manager that would open up about some of these topics, but he was still reserved.
Supportive: Goals, training, honesty, you name it... Slalom excels here.  There is no annual training budget - as long as what you want to do aligns with your goals, it's likely to get approved.  "Big Hairy Audacious Goals" really push us to think big and accomplish more than we ever think we can.
Everyone's willingness to help is astounding. There are no political roadblocks.  With a short email, I can reach out to fellow employees from any team or market and get results. Can I visit Slalom Chicago while working remotely? Done. Can the social media team post/promote some of my new work? Done. Can I refer someone to Slalom Denver, and oh, I still get a referral bonus, right? Done. Can I start a new X group (Toastmasters, Agile, Improv, Leadership) and get help generating interest? Done, done, done!
Personal Highlights:
- Attending Microsoft Build 2016 conference in San Francisco (was approved to go after only being an employee for 2 months)
- Shifting my work schedule (often last minute) to accommodate friends coming into town. Working remotely in other cities, allowing for more travel and flexibility.
- Main client: Being part of their largest IT project in history. I learned so much about scaling technology for millions of users and the challenges that are involved.  Using newfound skills from Toastmasters and Slalom leadership training classes to drive organizational change at my client. Specifically, getting siloed teams to begin communicating and sharing with each other. Seriously, I'm fairly certain several teams had never spoken to each other in person over the years before I came along!
- Being asked out of the blue to assist with a large cellular company's web based mobile project. I was brought in to leverage my PhoneGap skills, which until now I've only used in side project work. Yay!
- Making exercise and better health my first priority, but still being successful at my client. Exercise has given me the best mental clarity I’ve had in years, making me incredibly productive.
- Continuing to grow my leadership, management, and mentoring skills. After a quick conversation with my manager, I was able to start interviewing candidates for the first time. I've got much more planned for 2017.
- Delivering a speech at Slalom Speaks, our TED-like annual event, to over 100 coworkers and clients. Let me tell you, that was the fastest 10 minutes of my life! Here's me on stage:
Tumblr media
I could keep going, but I need to speak with my people manager.  It's time to discuss my Holiday 2016 PTO plans!
About Slalom: Slalom is a purpose-driven consulting firm that helps companies solve business problems and build for the future, with solutions spanning business advisory, customer experience, technology, and analytics. We partner with companies to push the boundaries of what’s possible—together. Founded in 2001 and headquartered in Seattle, WA, Slalom has organically grown to nearly 4,000 employees. We were named one of Fortune’s 100 Best Companies to Work For in 2016 and are regularly recognized by our employees as a best place to work. You can find us in 25 cities across the U.S., U.K., and Canada. Learn more at slalom.com.
0 notes
dotnetkow · 8 years
Text
"It's Not You, It’s Me": Start Using NPM for PhoneGap Build Plugins Now
In just a few days (November 15th, 2016), PhoneGap Build's plugin directory is going away in favor of Node Package Manager (NPM).  No need to panic! There are several paths you can take to move over to NPM.
Option 1 - "I'm using a popular plugin": Use NPM referral link
In a great move, PG Build has given us the option to see the plugin's equivalent on NPM or submit a suggestion ourselves.
Navigate to the StatusBar plugin page for example.  Here, we see a link to the most likely (submitted by users, so may not be correct!) equivalent plugin on NPM: 
Tumblr media
Clicking the “probably here” link brings us over to NPM.  Most, especially official, PhoneGap plugins begin with “cordova-plugin” so usually it’s safe to assume that they are equivalent.  As we’ll see below though, that’s not always the case - review the NPM one in detail and test it before putting out a new version of your app.
Tumblr media
In our config.xml, replace the PhoneGap Build version with the updated NPM one:
<plugin name="cordova-plugin-statusbar" spec="2.1.3" source="npm" />
NPM link not there? If you happen to know the NPM equivalent, please consider helping others out by submitting it's module name at the bottom of the plugin page. For example, I'm using the PG Build Google Analytics plugin, but found and submitted cordova-plugin-google-analytics as it's replacement.
Tumblr media
Option 2 - No "NPM referral link" on PG plugins page: Find plugin on NPM
In this new world, you need to use NPM: https://www.npmjs.com/.  PhoneGap/Cordova plugins generally begin with "cordova-plugin" in their names, so begin your search with that coupled with whatever you're looking for: cordova-plugin-something-cool.  When you find a plugin, the latest version number to use will be seen on the right hand side of the page: 
Tumblr media
In this example, the config.xml reference should be:
<plugin name="cordova-plugin-google-analytics" spec="1.7.1" source="npm" />
Option 3 - Last Ditch Option: Fork from GitHub
What is there is no referral link and/or you can't find an equivalent on NPM? Fork it from GitHub to your personal account and reference it from there.  This also works in the case that the NPM plugin is not quite the same as the PGB one and you don't have time to update your code just yet.  I actually needed to do this step for the Google Analytics plugin - it turns out the namespaces and methods are slightly different. I'll update the code eventually, but I want to ship out some other changes shortly.
Navigate to the plugin page on PG Build. Under "Other Details", you'll see a Repository link:
Tumblr media
Copy the link.  Over in your config.xml, your old reference probably looks like:
<gap:plugin name="com.adobe.plugins.gaplugin" version="2.4.0" />
Change it to point to the GitHub version using source="git" and name to spec. On a new app build, PGB pulls the code from GitHub now:
<plugin spec="https://github.com/phonegap-build/GAPlugin" source="git" />
As a final step, consider forking the repository for future reference or to maintain a copy in case it's deleted.  Navigate to the repository's GitHub page, then click the Fork button in the upper right hand corner. The repository now appears in your account as a "forked repository".  When I navigate to my forked version of GAPlugin now, it's essentially copied/saved for future reference: https://github.com/dotNetkow/GAPlugin
Happy plugin hunting!
0 notes
dotnetkow · 8 years
Text
“United States of Me”
This is a shopping cart filled with garbage at the end of our street. It's been sitting here for over 2 weeks. In our neighborhood, where condos go for $800,000, no one seems to give a shit that garbage is all over the place. Our neighbors don't return our "hellos" when we greet them.
Tumblr media
If this happens in one of the most affluent Seattle neighborhoods, is it any surprise what happened last night? Apathy is at an all-time high. Selfishness too - "The United States of Me." One FB friend posts concerns about how her disabled clients might lose their ACA care, while another laments that his costs are going up. "Fuck you, got mine!" rings true.
I finally snapped today, passing the cart on my exercise walk. Long overdue, I went back home, grabbed my car and a trash bag, and cleaned up the cart. I was planning on bringing the cart back to the grocery store, but it wouldn't fit in the trunk. I'll contact the City somehow.
Tumblr media
It's cliche, but true: you must be the change you wish to see in the World. Last night reaffirmed my growing feelings: I must continue to lead by example and focus on helping others. I must use my increasing wealth for good, working even harder to limit the damage that the apathetic, backwards-thinking, blinded masses can do.
This is a call to all of you to #DoYourPart to make this country better. It starts at home. Get your struggles worked out, then begin helping your community. I am America. I am the future.
0 notes
dotnetkow · 8 years
Text
Slalom Speaks 2016 Talk - "Time to Find Your Calling"
I’m very excited to share my Slalom Speaks talk, “Time to Find Your Calling”! Taking place on 9/29/2016, "Slalom Speaks” is our annual TED Talk-style event that brings together bright Slalom minds to deliver passionate and idea-focused talks to inspire, foster learning, and promote conversations that matter. 
For almost 1 year now, I’ve been attending Slalom Seattle’s Toastmasters meetings.  It’s a wonderful concept - dedicated speaking practice in a safe, fun, and friendly environment.  We meet Wednesdays from 7 to 8am, before we head off to work at our client sites.  Some scoff at getting up that early, but honestly I find it incredibly energizing and look forward to it every week.
On a recent road trip, my wife and I headed to the only winery in Astoria, Oregon. It’s a one man operation open 365 days a year.  The owner taught me that there is plenty of time to find your calling:
youtube
0 notes
dotnetkow · 8 years
Text
BeerSwift: Launch Week Retrospective
Tumblr media
I launched BeerSwift, a new iOS and Android app for Untappd, a couple of weeks ago.  It was an exciting launch, as it was the first time that I put all of the marketing books/tips I’ve learned to good use!  (Huge shoutout to Justin Jackson for his book Jolt!, a large inspiration for the marketing strategies I tried.)
Overall Thoughts
I’m very happy with how the launch went.  Making something that people love is incredibly rewarding!  I definitely could have used more time to prepare though.  I took on too many personal and professional commitments leading up to the launch - next time I need to focus on just one thing. 
If I’ve learned anything, it’s that marketing and promotion is never ending.  I could only do so much, focusing instead on getting the product experience right.  I’m fairly unknown on the Internet too, and BeerSwift is a very niche concept, so I wasn’t expecting or trying for lots of coverage.  Validating the initial idea via Reddit and a mailing list, then leveraging them to drive the launch, were the two best strategies here.  I’m confident that the app will be very successful - it’s just going to take time to spread the word. 
Soft Launch Weekend (9/30 to 10/2)
I believe in being paid for my work.  That said, BeerSwift’s success will definitely come in the long term through marketing and word of mouth sales.  What’s important now is building up an initial user base so putting up a paywall at this point won’t help.  For the first week, I made the app free. Here are the 3 day results: 
Android Free: 54 downloads 
iOS Free: 136 downloads 
Total: 190 downloads
Entire Launch Totals - 9/30/16 to 10/9/16
iOS:       167 (+31, $13.92 sales (~$9.80 profit), 8 paid, 159 free) 
Android:  76 (+22, $29.24 sales (~$20.47 profit), 28 paid, 48 free) 
Total:     243 users, ~$30 profit 
Users that opened the app at least once: 153 (63% of install base) 
Total hours worked (Very rough estimate due to month long breaks over 2 year period)
Development, Marketing: ~127 hours (3 standard 40 hr work weeks)
Strategies
- Individually sent out Android free promo codes to mailing list and Reddit users (I couldn’t set the app to “free” without it being permanently free - lame, Google Play, lame!): Very successful.  Lots of people responded actively, gave feedback, shared how they were going to use the app.  A bit time consuming but the individual touch was worth it! 
- Product Hunt posting: Didn't do much, which wasn’t surprising.  I was just excited to have something to post there! 
- Reddit post to /r/beer and /r/untappd: Incredibly successful.  Beta users from mailing list chimed in with how much they love the app. I responded to every single comment. 
- Attended Great American Beer Fest (GABF) 2016 in Denver: Saturday session only, 12 to 4pm. Created BeerSwift t-shirts with name/logo on front, "Text ‘beer' to 38470” (try it!) on back.  T-shirts were a great idea - lots of attendees and beer pourers asking “What’s BeerSwift?”.  Handed out business cards to many people.  Wearing a shirt and handing out cards will be a great way to promote in the future at my local Seattle beer festivals.  If I go to GABF again, all 3 days would make the most sense.  Could look into sponsorship too. 
Tumblr media
User Feedback
Great comments all around!  People mentioned going to festivals during the weekend of 9/29, so it was a great choice to launch on a Friday! Exactly what I was counting on.  Some key quotes:
- “We've frequently discussed the different methods we try to use to log new beers at beer fests, but struggle to do well, because it's simply so difficult to keep up."
- “This is perfect for GABF. Went 2 years ago, Internet was horrible. Had to write them down and checkin beers from my hotel."  (Ouch!)
- "I was just at a beer festival in the rain and missed a bunch of checkins this would have been perfect."
- "I can't wait to try. My favorite bar doesn't have decent internet and even the free wifi is way too spotty. They have a wide variety and it's hard to check in everything."
- “I travel for work and don't always have a roaming plan. So the offline is interesting to me."
- (Coolest comment!) "I'll be going to Vienna and Brussels soon, great moments to test the app!"
It's amazing to be able to reach so many people - a potential worldwide audience!  I’m incredibly excited to continue building upon BeerSwift’s launch.
Special Thanks
My Wife: Her patience and support during crunch time was very appreciated. Her love keeps me going!
My Team: Their feedback and excitement helped me stay positive and motivated.
My Beta Users: Thank you for taking a chance on a completely new app experience and giving lots of great feedback.
0 notes
dotnetkow · 8 years
Text
Introducing BeerSwift - Faster, Easier, Offline Untappd check-ins!
Tumblr media
I’m happy to share my latest mobile app, BeerSwift, now available on the App Store and Google Play. Focusing on faster, easier Untappd check-ins, it's optimized for experiences:
At Breweries: Enjoy relaxed tastings with friends
At Beer Festivals: Track large amounts of beer amidst big crowds and slow/no Internet
At Parties: Avoid appearing anti-social by quickly tracking beers
Add beers to your Queue, rating them as you taste. At your convenience, check them into Untappd all at once!
BeerSwift is available now:
Tumblr media
The Beer Queue:
Tumblr media
BeerSwift in action at GABF 2016!
Tumblr media
0 notes
dotnetkow · 8 years
Text
The Complete Guide to Creating a Custom Plugin for an AEMM Project
I was recently tapped to assist with a project that involved creating mobile apps using Adobe Experience Manager Mobile (AEMM).  I know PhoneGap/Cordova well enough, and AEMM uses PhoneGap, so why not?!
I was asked to incorporate a custom plugin (one that AEMM does not already support in their platform) into the AEMM app.  This proved quite challenging, so I found myself taking copious notes as I trial and errored various steps. This guide takes you from start to finish!  Special thanks to the handful of Adobe folks that assisted me and reviewed this guide.
(Currently only for iOS AEM apps - please see the main Adobe page on custom plugins for other platform details (Android, etc.).  Feedback? Error correction? Please leave comment below.
Understanding AEMM
Adobe Experience Manager Mobile allows both technical and non-technical users to create and manage custom mobile apps all from one online portal.  Content (HTML, images) is created and updated within the tool, then published (pushed) to user’s mobile devices.  Each time they open the app, the latest updates are downloaded over the air – thus bypassing the app store review processes.  No coding skills are required, but advanced, interactive features can be added by developers.  The AEMM app is essentially a PhoneGap (Cordova) app, so plugins that add native functionality can be included (geolocation, accessing contacts, camera, etc.).  Custom plugins (any that Adobe doesn’t support out of the box) can be used too, but require more effort.
There are two flavors of app builds: “preflight” and “production”.  Preflight is for testing; it allows you to see staged, unpublished content.  Production builds (Preflight turned off) only show published content.
Prerequisite Downloads
An account on AEM Mobile On-Demand portal: https://aemmobile.adobe.com
For building an iOS App, a Mac computer.
XCode (v7.0 or greater)
AEM Mobile Developer Tool & Cordova (see below installation instructions)
Node JS (current stable version recommended)
AEM Mobile Signing Tool: Download from AEM Mobile website: Navigate to Apps page. Click “Download Signing Tool” in upper right hand corner.
Optional: AEM Mobile Packager: Utility to package HTML, JS, and CSS into an AEM Article file for upload to AEM Mobile website.  Not used currently.
Installing AEM Mobile Developer Tool & Cordova
Launch Terminal. Ensure Node.JS is installed beforehand.
Install AEM Mobile Developer Tool:
sudo npm install -g aemm
Install Cordova:
sudo npm install -g cordova
NOTE: AEMM wraps (sits on top of) Cordova commands.
Install the Simulator Build:
aemm app install ios
Configure iOS environment to allow XCode to build an unsigned framework (necessary for custom plugins):
sudo aemm platform install ios
Creating an App with a Custom Plugin
AEMM Prerequisites
Ensure these steps are complete first otherwise the app and custom plugin code may not work in AEMM.
Create Content (Articles) first.  An "Article" is essentially an HTML page with CSS, images, and JavaScript files.
From the AEMM website portal: Content & Layouts -> Content.
Use AEMM Mobile Packager Tool to bundle a set of HTML, CSS, and JavaScript files into an Article (.article) file.
NOTE: Plugins are restricted to the Article level.  The User must open the Article that references the custom plugin in order to execute it.  To access the plugin “globally”, add the custom code that references the custom plugin (JavaScript file) to an AEM App Template.
Ensure Articles have “Extensibility” turned on.  Without it, plugin code will silently fail/not run without warning.  On an individual Article, select an Article, Content Properties button, Article metadata, and check the “Enable extensibility features” box.
Even better, enable for all Articles by default: Project Settings -> Select Project -> Edit Project -> Content tab -> “Enable extensibility features” checkbox.
Create at least one Collection (Content & Layouts -> Collections).  Add desired Articles to the Collection.  Publish the Collection and the Articles.  Without publishing, Articles will not show in the completed App nor will updates be pushed.  Always re-publish Articles after updates are made.
Have an iOS Developer Account ready.  Identify test iOS devices and obtain device UDIDs (can use http://whatsmyudid.com/).  Create Provisioning Profile using UDIDs.
Create the App
Create the initial app using an AEMM template:
aemm project create [project name]
Write code that interacts with the custom plugin.  Add code files to “www” folder.
Create an “index.html” file.  Include reference to “cordova.js”:
<script type=”text/javascript” src=”cordova.js”></script>
This file is included at AEMM runtime – do not include an actual file!
In JavaScript file, add event listener for “deviceready” event.  Cordova in AEM will fire this event once Cordova has fully loaded, meaning it’s ok to use plugins. Calling plugin code before deviceready will cause errors.  Add script reference to JS file in index.html.
document.addEventListener(“deviceready”, function() {
               // Cordova ready, may call plugins now
} , false);
3. Change directory into the project (“cd project-name”), then install the iOS framework:
    sudo aemm platform install ios
4. Create or pull down the custom plugin and add it to the local project:
    aemm plugin add [plugin name]
To check that it installed correctly, run: aemm plugin list 
5. Compile/Build the iOS app for the iOS simulator.  Correct any errors:
    aemm build ios
Add --device to build the app for iOS devices instead of the simulator
Add --release to build a release version instead of default debug version
6. Test the plugin independently of AEM via the emulator and then incorporate into AEM.  See below.
Build the App for Release
When all Article content is finalized and the custom plugin works, you can create the complete iOS app.
From AEM Website (https://aemmobile.adobe.com):
Verify that all Content, Articles, and Collections are published.  Publish if not up to date.
Verify that all required Articles have “Enable Extensibility Features” flag turned on.
(First time) Create a new iOS App: Go to Apps page.  Click the Plus button.  Choose “iOS” under Platform, then Next button.
General tab:
Set App Name, Supported devices, etc.
Bundle ID: Must match the ID specified in the Apple Developer Member portal (https://developer.apple.com, “Certificates, Identifiers, & Profiles” -> Identifiers -> App IDs.  Format usually follows: com.companyName.appName. Ex: com.adobe.awesomeapp
Preflight: Disable if creating an App Store/distributed app.
Assets tab: Upload app icon and splash screens.
Plugins tab:  Select additional plugins to include.  Optional.
Click Submit button when ready.  You are taken back to the Apps page, and the App will be built. Adobe takes your project settings and configurations and bundles them into an iOS app file (.ipa).  Once the app has built, click the word “URL” under Downloads column to download the generated IPA file.
(Updates to custom plugin) Since the custom plugin code is injected into the IPA file, you must get a fresh IPA file and re-inject the plugin code.  Go to Apps page.  Select the App.  Click the Pencil Edit button. Make any metadata changes then wait a few moments.  Eventually, the “Submit” button will light up.  Click Submit.  Adobe creates a new app package. Download the generated IPA file. NOTE: This is the only way to force a new app build.
(Updates to Article content) Nothing extra to do.  Once you publish the content, Adobe pushes the changes over the air to the users’ devices.  
From Terminal:
Add the custom plugin to the downloaded IPA file: At this point, the app does not have the custom plugin code.  To add it, first change directory into the app project folder:
cd [app folder]
Run one last sanity check to ensure plugin is installed into the local project.  If it is, it will appear in the output.
aemm plugin list
Then, inject it into the IPA file:
aemm package ios --device [path to IPA file]
ex: aemm package ios --device /Users/joe/Downloads/coffee_app.ipa
A success message will output.
Wrap Up:
Sign the app using an iOS Developer certificate and provisioning profile.
If building a test version of the app, Adobe’s AEMM Signing Tool is handy.
If using AEM Mobile Signing Tool, a new IPA file will appear alongside the current one.  When deploying to devices or the App Store, pick the IPA file that ends with “-signed.ipa”.
Upload the App to the App Store.
(Optional) To copy to a test iOS device using iTunes: Open iTunes.  Using Finder, navigate to location where “-signed.ipa” app is.  In iTunes, click “Library”, then “Apps”.  From Finder, select IPA file and drag/drop it into the iTunes “Apps” window. If it works, a new entry for the app appears in the Apps list.
Plug in iOS test device to computer.  After a few moments, the device icon appears. Click it then choose “Apps”.  The newly added App will appear in the list.  Click the “Install” button, then “Sync” button to install onto the device.
If the app does not install or open properly, double check the device’s UDID in the provisioning profile, as well as the Developer Certificate.
Testing App Plugin Code Locally, before Incorporating into AEM Mobile
AEMM’s project template is slightly different than Cordova’s, unfortunately, so you have to do one extra step.  AEMM moves the “www” content one level lower in their projects (www/SampleArticle/[code] as opposed to www/[code]), so you must copy your code (HTML, CSS, JavaScript files) into the www folder temporarily for testing.
In Terminal, begin in the project directory. Compile/Build the iOS app for the iOS simulator and correct any errors:
aemm build ios
Open the iOS Simulator.  AEMM does not have an “emulate” option, so use Cordova:
cordova emulate ios
Once the Emulator launches, you can debug the web code of the app (JavaScript info/errors to the console, etc.) using Safari.  Open Safari, then go to Develop -> [Your Name]’s Macbook -> select available index.html file.  The Developer Tools load in a new window.  Click on Console tab to view info/errors.
Modifying the Custom Plugin and Testing It
Should additional functionality or changes be required of the customized plugin later on, follow these instructions:
Make your changes to the plugin files.  Beginning at [custom plugin] folder:
/src/ios folder: Contains the native Objective C code.
/www folder: Contains the web (JavaScript) interfaces that Cordova uses to create a “bridge” between native and web code.
Apply the changes to the app project that uses by custom plugin by first removing the old plugin code and re-copying in all changes.  (Note: there is a “link” flag option, but it doesn’t seem to work!)
Change directory into the project: cd app-project
Remove the old code: aemm plugin rm [plugin name]
Add the updated code (typically one level higher in folder structure): aemm plugin add ../[plugin name]
Build the app: aemm build ios
The new plugin code will be compiled.  Correct any errors.
Test/deploy using other instructions in this guide.
References
Using Cordova plug-ins in AEM Mobile: Tools to install (AEM Mobile Developer Tool) and commands to use in order to package the custom plugin into the App.
iOS Publishing Guide: Adobe’s complete overview of submitting to Apple App Store (certificate files, signing apps, publishing…).
Signing iOS and Android apps for AEM Mobile: How to use the AEM Mobile Signing Tool to sign an app, which permits it to be installed on a mobile device and/or uploaded to the Stores.
Creating links using “navto”: Redirect the user to the specified Article page in the App using AEM Mobile “navto” functionally.
0 notes
dotnetkow · 8 years
Text
Cut Your PhoneGap Build App Size In Half With This One Weird Trick!
I’m in the midst of wrapping up my first Pluralsight course on PhoneGap Build Fundamentals and stumbled upon this today: if you include a special file into each icon and splash screen image directory, PhoneGap Build will only include the platform specific icon/splash files in each app binary created.
For years now (and I suspect I’m far from the only one), I’ve assumed that PG Build already does since, since we specify the image file paths in the config.xml file.  Nope!  All images are always included.  Include a PGB Omit file with no file extension (.pgbomit) into each icon/splash directory.  I tested it with the app I’m building for the course:
Before: 6.4MB
After: 3.3MB
Basically half of the original size! Awesome.
Details can be found at the newly revamped PhoneGap docs page:
A typical use case is for a directory containing the icons and splash screens for an app. Place .pgbomit in that directory and none of those files/directories will be included in the binary app package, except those copied and used for icons and splash screens for a specific platform.
0 notes
dotnetkow · 8 years
Text
Excellence In All Things
(Dedicated to all the fathers out there who lead the way, especially my own, who inspired this post.  Happy Father’s Day!) 
It’s putting back the lone grocery cart that wasn’t yours in the parking lot before the wind blows it into someone’s car. 
It’s stopping to pick up the soda can in the woods instead of stepping over it.
It’s obeying the speed limit, even with miles of open farmland in front of you. 
It’s Leaving No Trace (Go Boy Scouts!). 
Excellence is striving to do the right thing, always, especially when others are lazy/impatient/apathetic.   It is a challenging, life-long journey.  The mental pull to “just leave it for the next person to fix” is constant and pervades our society.  However, when everyone thinks that way, small problems become big problems.  Consider a building with one broken window: one broken window becomes multiple broken ones, becomes spray painted walls….and so on and so forth.  Decay doesn’t happen all at once. 
It’s being creative in how you lead others.  At my last client, we had a late night code release.  A group of us were standing around, waiting for another team to finish a task so that we could move on to ours.  Leftover food that had been ordered in for our teams was just sitting there nearby.  I cleaned up the food and wiped down the table without saying a word.  A couple coworkers cracked some light-hearted jokes about it.  During the next release, I cleaned again. This time, others joined me.
It’s not taking shortcuts.  A couple months ago, I needed to update my mobile app Fitwatchr to a new behind-the-scenes technology.  It was tempting to do the bare minimum, which would have saved me tons of time/effort but at the expense of my users, who would have been confused and inconvenienced over why the app suddenly stopped working.  The change went live with no-one noticing. 
It’s honesty in the face of discomfort.  If you start with a small lie (perhaps trying to save face over something relativity unimportant), how do you think you’ll act after a bad habit has been formed and when it really counts?  It’s a slippery slope. 
It’s rationality in the midst of fear mongering.  “Faith in humanity restored!” and “Make America Great Again” are just plain silly.  Humans have always committed amazing but also terrible acts.  Nothing in recent history has changed the world - it’s just that in this Internet age, both extremes are readily present.  
As cliche as “Be the change you want to be in the world” is, it’s true.  The choice is yours to avoid negativity, embrace a positive outlook, and strive for Excellence. 
0 notes
dotnetkow · 8 years
Text
“.NET Core Overview” Brown Bag
We’ve recently began a weekly development brown bag series at Slalom Seattle.  It’s a great way to share what we are learning with the larger group, especially since as consultants, we are all across Seattle, staffed at different client sites.
This was my first presentation, a follow-up to Microsoft’s 2016 Build conference, on .NET Core.  Core is a ground-up rewrite of the .NET framework.  Notably, it’s open source, cross-platform, and modular.
While not quite enterprise-ready yet (RC2 currently available and no v1.0 release date set as of June 2016), it’s an exciting move by Microsoft.  Here is the talk; note that the audio is a bit rough due to recording over GoToMeeting & I speak very informally, but I think you’ll enjoy it.
youtube
1 note · View note
dotnetkow · 8 years
Text
Building Upon Success Through the Domino Effect
I've been reading "The One Thing", a book that preaches focusing on one thing at a time in order to achieve extraordinary results. By doing so, your success will build gradually, in a kind of domino effect.  I believe this has been the case for me and it inspired this post.
I've been reflecting recently on my life and career.  I'm all together not entirely satisfied, so naturally I'm working on fixing that.  I've realized that of all the people that I look up to, do I know how they got to be so influential/successful/interesting?  Whether it's a mega celebrity or your company's CEO, often we just know them from their biggest, most public achievements.
I really wish folks would share more about the key moments in life that shaped who they are, especially in regards to their careers.  Not only is it fun to hear about, lots of great lessons can come from it.  In the spirit of things, here's mine:
Childhood: My parents sit my brother and I down to read books every night.  The first thing that set me up for success - instilling an appetite for knowledge and continual learning.  Mom stays at home with us then later goes back to school to become a fifth grade teacher.  Dad goes back to school while moving up the ranks at Sears Corporate.  Watching them, I learn the second thing: hard work, discipline, and sacrifice.  Through the ups and downs of Life, they always put their children first.  Thanks, Mom and Dad! 
Middle school: I struggle socially with shyness.  My parents push me to "spread my wings".  I do but they later come to regret this when I reach early adulthood and become fiercely independent.  A small, tight knit group of friends is formed.
High school: I still struggle socially and am not athletic, a formula for disaster in high school. I'm not naturally smart (meaning concepts don't connect without effort) so I focus entirely on schoolwork.  The hard work pays off when I'm accepted to Marquette University.  I solidify three best friends who stand up at my wedding over a decade later.  They mean the world to me.
College: I view it as an opportunity to redefine myself socially.  I talk to everyone I can opening weekend, meeting many friends that are with me to this day.  I struggle for two years academically but refuse to give up.  I dedicate myself fully to computer science in later years, living in the computer lab while others party.  I be sure to schedule time with friends on Friday/Saturday nights, becoming the guy that plans all the gatherings.  I eventually excel overall, opposed to students who were naturals in high school and had ACT scores in the 30's struggle for the first time.  I become President of the Spanish Honor Society, study abroad in Mexico for 6 weeks, build a EMR system for a non-profit Milwaukee clinic, intern with Motorola, and meet my future wife.
Post College: I land a job with The SAVO Group in Chicago as a junior developer after almost 100 failed job applications.  Humbled, I gradually work my way up.  I move out of my parents house almost right away, having missed the freedom of living on my own.
First two years:  I code small projects while my manager handles client interactions.  I realize that I'm a terrible programmer and put effort in and outside of work to get better, going to conferences on Saturdays and studying to become Microsoft certified.  I am forever indebted to my manager, who teaches me the best lesson yet of my career: knowing how to program while understanding the why of business turns you into an unstoppable force.
Next two years: I become confident in my programming abilities and begin experimenting on my own with side projects.  I create a Kinect iTunes app and some small Chrome extensions.  I begin to see the vast opportunities in front of me as I feel the exhilaration of publishing work in my own name publicly.  I begin interacting with clients on small projects and get promoted to Developer.  A coworker pays me several hundred dollars to create an application; I reinvest the funds into a powerful desktop computer that helps me to this day on new projects.  I marry my best friend, throwing the best celebration party ever!
Final two years: I stand out among my peers by: becoming the rare client-facing "super developer", breaking down internal silos where possible, building relationships with management, becoming a SME and "go-to" guy, and creating a top selling application after grasping the business space.  I try my hand at mobile development after getting my first smartphone, creating a really neat Netflix app.  I love my first taste of entrepreneurship and begin aggressively studying business & marketing. Continuing the theme of creating things based on product gaps that I personally want and therefore am invested in, I create a fitness app, Fitwatchr, in 2013.  Growth picks up in 2014 after 6 months in the App Store, and I team up with another SAVO coworker.  I blog about my mobile apps and lessons learned and get noticed by other companies that need help on their mobile strategies.  I face my fear of public speaking by giving a speech at a tech conference.  My wife and I move to Seattle to try a new city while we're still young and without kids.  I'm miserable working remotely and realize I need a change.  I make the hardest decision of my career and quit via a Google Hangouts session.  I still miss my colleagues dearly but do my best to keep in touch.
Present: I am introduced to a company, Slalom Consulting, that values hard work while still maintaining work/life balance.  After 6 months of new challenges and struggles being away from home, I help launch an international coffee company's largest technology initiative yet.  I hit the ground running, beginning to establish myself as a leader within the company, doing such things as: taking nightly leadership training classes, joining Toastmasters, and being a spokesman for better quality & process improvement at the client.  I leverage my mobile experience to land an opportunity to create developer training videos for Pluralsight.  Recognizing my blessings, I begin a renewed focus on family, friends, and giving back (volunteering, coaching friends on their careers, and randomly sending books that have shaped who I am to those I love).
May 2016:  I write this blog post and can't wait to add more to it!  I'm at a crossroads in my career, not fully knowing what the next 5 to 10 years will bring.  I'll certainly focus on improving my leadership and development skills, knowing that eventually the path forward will become clear!
0 notes
dotnetkow · 8 years
Text
Celebrating 10 Years of Programming Experience
Ten years ago in Fall 2005, I began pursuing a computer science degree at Marquette University.  My first programming class taught Java.  Prior experience had included using DOS commands to run "Command & Conquer" and "Doom" on my parent's Windows 95 PC and a BASIC class that I took in high school, taught by a gym teacher who knew as much as we did.  So frankly, not much!
This post is inspired by several groups of people: those who ask me about software development and learning how to program, are curious about my apps/accomplishments, and Ramit Sethi, famed entrepreneur of IWillTeachYouToBeRich.com.  In a recent email, he wrote about how people love to believe that success is effortless and just happens:
For example, one of my friends, a mother of 3, told me how other women would ask her how she looked so amazing with her busy job and family of 5. She used to excitedly tell them about her detailed workouts and diet. Their response? "They got really mad," she told me. They would say things like, "I could never do that" and "Must be nice to have time"You know what she tells them now? "I just watch what I eat and play with my kids a lot." They smile and carry on.People hate seeing how the sausage is made.
Personally, I appreciate the honesty. Instead of having people tell me vague lies about what it takes to look great, build muscle, earn more, start a business. etc — I’d rather hear the unvarnished truth.
This struck a cord with me because, like others, I'm guilty of this: always touting our successes, but never our failures.  It's a shame, because there are valuable lessons to be learned by sharing both!  Here's my truth: I struggled a lot during the first few years.  School never came naturally to me - I've always had to work hard.  This was especially the case with programming.  My freshman and sophomore years were the hardest.
Beginning freshman year with Java programming was an experience! It was a large class of about 50 students.  We flailed around not having a clue as to what we were doing, typing up code printed off of lesson workbooks.  In the lab portion, dedicated time to go through the lessons, we had just one grad student TA available to help us.  For many weeks, nothing really made sense.  Additionally, I had to take Calculus 1 as part of the CS degree.  Math was never my strength, so it became the hardest class I would ever take.  My first semester turned into a stressful battle between spending long hours programming in the lab and trying to understand Calculus.  I barely made it through, narrowly passing Calc with a "CD" grade (C- equivalent).
In Sophomore year, we switched gears to embedded systems programming in C.  In these classes, I was humbled while learning about the lowest levels of programming and technology.  In our first lab, the goal was to send pixels to a CRT monitor.  If the screen was completely black after running our program, then it hadn't worked.  Hours upon hours later, we saw color appear on the screen and jumped for joy.  Later lessons, building upon each other, were more difficult.  Some days I would go to class from 8am to 4pm then go to the computer lab to work until midnight or later.  I remember one late night reviewing memory management with a favorite professor of mine, fighting back tears when I couldn't seem to understand pointers and address spacing.  Those were brutal days but I pushed through with the help of awesome (patient) professors and CS friends.  I was hooked at this point though - there was nowhere to go but forward.  
With each passing year, it got a bit easier, yet harder at the same time.  With programming, there is always something new to learn.  Computer science fundamentals can feel abstract and require learning how to think logically.  That seems funny, right? "Think logically? Of course, everyone does that!".  They do, that's true.  With programming though, you're really forced to truly learn how to solve problems.  This includes the biggest insight that I gained from a professor: how to break problems down into individual, manageable pieces.  Without that skill, each goal is overwhelming; a large source of my initial struggles.  
By Spring 2009, I had almost made it through.  I learned .NET during my year long Senior Design project, in which we built an Electronic Medical Records system for a local medical clinic.  However, I quickly became discouraged.  You see, most of the people in my CS program had lined up jobs before graduating, but not me.  I moved back home and slowly started applying to jobs, spending a few hours a day looking.  When I wasn't applying, I worked on my senior design project, fixing bugs for the clinic. It was really difficult at the time for me - with my fancy degree I thought I was hot stuff and should have gotten a job right away. I remember whining after my Mom suggested that I apply to a temp agency.  I recoiled at the thought - I was ready for my "big boy" job after all!  In a lecture that I'll never forget, Mom reminded me that I should never feel like I am above any type of work.  Humbled, I applied to the agency and then went back to applying to programming jobs.
Over the summer, I applied to over 100 positions.  The majority were outright rejections or silent.  Application #72, to The SAVO Group, eventually came through.
An entirely new, wildly different educational chapter began.  In addition to being the lowest developer on the totem pole, I was faced with business challenges: deadlines, working with others, meetings, satisfying clients - on and on.  Utilizing my hard work ethic and humility I had honed over the years, I achieved a lot during my time at SAVO.  Multiple promotions earned, awards won, and products launched.  Long lasting relationships with great coworkers.
Today I'm expanding beyond programming: taking an interest in business, marketing, customer service, and entrepreneurship as I build my own products.  I'm excited for what's next!
Key lessons learned over 10 years:
- Nothing is impossible.  Every problem can be broken down into digestible chunks.  Taking a break and starting fresh the next day is never a bad choice. 
- Relationships (working with people) are harder than writing software.  I still have much to learn here (it'll be a lifelong journey!).
- Stay humble, hungry, and focused.  Take advantage of every opportunity available.
- Programming is one tool of many used to solve problems.  Going beyond programming is important for personal and career growth.
- Hard work and passion will beat raw intelligence every time.  The naturally talented have less intrinsic incentive to push themselves forward, often over time becoming lazy.
Programming.  It's an amazing undertaking to create something from nothing - one that keeps me inspired still today.  Here's to the next ten years!
1 note · View note
dotnetkow · 8 years
Text
Appearance on Talking Devs Podcast
Tumblr media
Excited to share my first podcast appearance today on The Talking Devs podcast.  I met Chris Bohatka at That Conference years ago and have since kept up with him mostly via Twitter.  When he approached me about being the first guest on a new podcast project he was starting, I of course said yes! 
We had a lot of fun recording this.  Despite clocking in at 1 hour+, we could have kept going!  We cover a lot at a fast pace: moving from Chicago to Seattle, starting a PhoneGap mobile app business in the context of Fitwatchr, and my upcoming Pluralsight course on PhoneGap Build.  Check it out!  
iTunes: https://itunes.apple.com/us/podcast/the-talking-devs/id1109451513
Google Play: https://play.google.com/music/m/I3quv7qdbwmqprwitcsy64umpby?t=The_Talking_Devs
Main site: http://thetalkingdevs.com/
Please take a moment to leave a review on iTunes and Google Play - much appreciated! 
1 note · View note
dotnetkow · 9 years
Text
Microsoft Build 2016 Recap
I had the pleasure of attending Microsoft’s Build conference this week in San Francisco.  It was a fantastic experience - certainly one of the better years to go.
  Overall Conference
For the most part, the conference itself is run very well.  Great wifi coverage, decent mix of sessions, and large spaces for recharging, collaborating, and socializing.  At $2,200 just for the conference ticket plus the insane cost of San Francisco city itself though, unless your company is paying it’s pretty much a non-starter for an independent developer.  Unfortunate perhaps, but the targeted audience here is definitely enterprise developers.   
I found the sessions to be very informative and engaging.  The best info came directly from Microsoft employees sharing internal knowledge and insights that could only come from them!  All of the content is available on GitHub (such as these great Code Labs) which is excellent because there was not enough time to go through it all in three short days.
Some improvements I hope they consider: 
 - Provide more sessions for the most popular topics.  With “code labs” requiring tickets that were handed out way in advance, it was difficult if not impossible to go to key sessions on ASP.NET Core & mobile for example.  While sessions on Unity game development, IoT, etc. are fun, they detract from others that provide the majority of the value. 
- Some (rather than no) giveaways and more, better quality food, please.  Budget cutbacks were obvious.  I’m fine with them not giving away a big ticket item to everyone (a la Xbox One) but at the very least serve breakfast!  These are long days and proper nourishment given how much we pay seems basic to me.
ASP.NET Core
Modular.  Managed.  Cross-platform.  Open Source.  This was a huge announcement and the most exciting one to me.  It’s great to see Microsoft finally embrace the way the development world is going.  With the relevance of Windows and Office declining, they are pretty much being forced to, but even so - these are great changes that are being executed well.  It’s clear that they are pushing everyone towards their cloud Azure platform but in order for everyone to embrace it, .NET needed to be open, modular, and run on everything.  With these changes, they’ve lowered the barrier to entry for both new developers and Mac/Linux folks, all while increasing existing .NET developers' value. 
The modular aspect is particularly cool - pick and choose a variety of services, APIs, dependency management tools, and databases for your applications.  Dependency Injection looks great - as seen here, very clean and straightforward.  As shown in a demo, a new vanilla .NET Core  project is extremely barebones: if you want MVC for example, you say services.AddMvc( ) in the app’s startup code.  AddThis and AddThat makes it easy to see at a glance exactly what the app consists of. 
Xamarin/PhoneGap/Universal Windows Platform
Building on .NET Core’s momentum, Microsoft officially bought Xamarin a few weeks ago.  Xamarin allows developers to create mobile apps using C#.  Very cool, yes, but originally very expensive (thousands per year I believe).  When I started building mobile apps 3 years ago, I chose PhoneGap over Xamarin due to cost.  Now, choosing between the two will be a lot harder.  I had a hunch that Microsoft would provide Xamarin for free, and they will now; however, the announcement that it’s free on Visual Studio Community Edition as well was a nice surprise.  Adoption is guaranteed to soar now.  The bottom line: cross-platform development is absolutely a viable option in 2016.  It’s great to see my bet on it a few years ago work out, admittedly!  Looking forward, if you’re a .NET developer, start with Xamarin.  If you’re a web/open source developer, PhoneGap is still a worthy option: the best stack at the moment is Ionic framework/Angular.js 2/Cordova. 
Office 365
Not a lot of excitement on this front from the keynote crowds, but honestly the Office team’s work with plugins/Add-Ins continues to mature and offer excellent application opportunities.  I’ve built a few plugins over the years, mostly with painful results.  It now has a better marketplace for discoverability, better tooling, and better language support, so I can see this being a hit in the enterprise space. 
HoloLens: virtual reality
Try as I might, I was unable to score a ticket to “Destination: Mars”, a virtual walk on Mars experience.  However, after speaking with others who were able to try it, it’s clear that it has a long way to go.  The FOV is very small and the headset is clunky and heavy.  Personally, I think that all the VR headsets coming out now will be a bit rough.  That’s ok though; this is a new wave of VR so of course over time it will improve.  I believe in 5 to 10 years it could provide some really compelling experiences.  The keynote demo involving medical students viewing the human anatomy was particularly inspiring. 
Bots/Cognitive Services
Microsoft unveiled “bots” at Build - “conversation as a platform”.  Coming totally out of left field (for me at least), I’m curious to see where this goes.  These will primarily launch within Skype only, but I’m sure they'll be available throughout all Microsoft products soon after.  Technically, the bots have been a thing for a long time, but so it goes: one or more large companies suddenly start pushing them and then they become popular/ubiquitous.  Really, what Microsoft is providing is a framework & platform that will allow users to create bots easily and often with little to no code.  Lots of possibilities here for businesses and consumers.
The Cognitive Services APIs are, quite simply, awesome!  Vision, Speech, Language, Search - so many options.  One particularly amazing demo showed a company that builds tech to assist the deaf.  The application listened to a spoken language (Portuguese in this case), processed it, and showed an on-screen avatar relaying the same message, but in sign language (!!!) with English subtitles (so us in the audience could understand).  Breaking down language barriers - wow.
Build 2016 was a great experience.  I recommend attending if you can (thanks to Slalom for giving me the opportunity!).  It’s a great time to be a .NET developer!
6 notes · View notes
dotnetkow · 9 years
Text
Android - 404 Not Found (from cache)
I encountered a frustrating issue the other day after upgrading to PhoneGap version cli-5.2.0 on Android.  My requests to Fitbit's API began to fail, resulting in 404 errors. I was incredibly stumped - the exact same code worked fine on iOS.  I ran the code on my iPhone and my Android tablet and pulled up both requests side by side.  All details in the requests were the same: URL, HTTP method, etc.  Everything except the status code - 200 OK for iOS and 404 Not Found (from cache) for Android.
Why a 404, specifically? Was something wrong on Fitbit's end?  Couldn't be - it went through on Android.  Finally it hit me - "(from cache)"?  That's odd!  After some Google searches, I had the answer.
As the Cordova docs explain, the more recent PhoneGap "cli" type versions coupled with Android's security model require the Cordova whitelist plugin.  I was testing on an Android 4.4 device, so that makes sense.  What the first link doesn't explain, but this blog post does, is that "Network requests are blocked by default without the plugin."  Ok then!
After installing the whitelist plugin and rerunning my code, I got an error pop-up with the following message:
"SecurityError: Refused to load the script 'https://api.fitbit.com/' because it violates the document's Content Security Policy."
The whitelist plugin docs explain that there are 4 types of security policies to be aware of:
Navigation: Controls which URLs the WebView itself can navigate to
Intent: Controls which URLs the app is allowed to ask the system to open.  This doesn’t apply to plugins - only hyperlinks and calls to window.open( )
Network Request: Controls which network requests (images, XHR/HTTP) are allowed to be made via Cordova native hooks.
Content Security Policy: Controls which network requests (images, XHR/HTTP) are allowed to be made via the webview directly.
I load images and make REST API calls via the webview directly, so I needed a CSP.  After much fiddling, consulting links like this one, I got it to work.  Add this to your index.html page to the <head> element:
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; media-src *">
Yes, the "unsafe" portions are troubling, but apparently they are required for PhoneGap to work properly. 
Additionally, I needed the Network Request portion, which is set in config.xml:
<access origin="*://*.fitbit.com/*" />
<access origin="*://*.cloudfront.net/*" />    (Fitbit profile images hosted here)
You’ll be tempted to just use origin=“*” (asterisk to allow all requests) but keep your app secure by explicitly allowing access only from the resources you will connect to!
To explain why I saw the 404 issue: by not specifying the CSP in my HTML file, the whitelist plugin most likely uses a default, very restrictive one that would not allow for external HTTP requests.  When my code tried to make one, it was blocked and instead looked for the requested resource (api.fitbit.com) locally within the app.  Of course, that route/path doesn't exist, hence the 404 not found error.  This explanation is mostly just pieced together from the documentation I've shared here, so if anyone out there knows more, I'd love to know!
3 notes · View notes