Debugging Cordova Apps, My Way

Cordova is hard to debug. There are millions things that can go wrong and it hard to separate the easy to debug stuff from the rest once you start working with native. That’s why its important to make the parts that don’t depend on native functionality work in the browser first. Get it working, then when it’s finished, bring it into the native app and work from there. Here’s a quick video showing you what I mean:

If you’re interested in my grunt file here it is:

[pastacode lang=”javascript” message=”” highlight=”” provider=”manual”]

module.exports = function(grunt){

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        exec:{
        	prepare:{
        		command:"cordova build",
        		stdout:true,
        		stderror:true
        	}
        },
        copy: {
                main: {
                        expand: true,
                        cwd: 'www/',
                        src: ['*', '**/*'],
                        dest: 'browser/'
                },
                cordovasrc: {
                        expand: true,
                        cwd: 'cordova-browser-src/',
                        src: ['*', '**/*'],
                        dest: 'browser/'
                }
        },
        watch:{
        	files:['www/**/*.*', 'cordova-browser-src/**/*.*'],
        	tasks:['exec:prepare', 'copy']
        }
    });
        
        // watch the www folder and build cordorva
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-exec');
        // copy www to browser and load in cordova.js to test in browser
        grunt.loadNpmTasks('grunt-contrib-copy');

    grunt.registerTask('default', ['watch']);

};

[/pastacode]

And here’s the cordova.js file:

[pastacode lang=”javascript” message=”” highlight=”” provider=”manual”]

var cordova = { 
    init: function() {
        app.initialize();
        var event = new Event('deviceready');
        document.dispatchEvent(event);
    },
    plugins: {
        notification: {
            local: {
                on: function(listener, callback, context) {
                    document.addEventListener(listener, callback, context);
                },
                getAll: function(callback) {
                    var notifications = [];
                    callback(notifications);
                },
                hasPermission: function(callback) {
                    callback(true);
                },
                schedule: function() {
                    
                },
                cancel: function(id, callback) {
                    var notification = {
                        stuff: 'things',
                        id: id
                    };
                    callback(notification);
                },
                registerPermission: function(callback) {
                    callback(true);
                }
            }
        }
    },
    InAppBrowser: {
        open: function(url) {
            window.location = url;
        }
    }
};

var StatusBar = {
    hide: function() {
        return true;
    }
};

setTimeout(function() {
    cordova.init();
}, 1000);

[/pastacode]

It will fire a “deviceready” event to kick the whole thing off!

 

Uploading multiple APKs to the Play Store from Cordova and Crosswalk

Let’s say you have a low version release and a current release for your app. Let’s also say you’re using crosswalk or another plugin that builds for different device architectures. We can still do it!

It all depends the android version code. If you take a look in your android manifest you’ll see something like:

android:versionCode="102052"

Basically it’s a version code that (among other things) tells google play that this is a new APK. You need to increment this every time you upload a new APK, even if its meant to support the same version!

Here’s the code:

[pastacode lang=”bash” message=”” highlight=”” provider=”manual”]

# in your config xml file
# add the following attribute to "widget"
# should look something like: 

[/pastacode]

Here's a video to show you how to do it:

Publishing Your Cordova App to the Play Store

You’re done! Now you want to publish? There’s a great resource here: http://ionicframework.com/docs/guide/publishing.html

But I’ll repost the instructions here, in case the page goes away.

First you need to build for release:

[pastacode lang=”bash” message=”” highlight=”” provider=”manual”]

cordova build --release android

[/pastacode]

If you have a keystore file already you can skip the next part. Basically, google requires you to sign the app, they will use this public key to verify you on your updates, so make sure you keep the .keystore file around:

[pastacode lang=”bash” message=”” highlight=”” provider=”manual”]

keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000

[/pastacode]

Next you need to sign it with the keystore file:

[pastacode lang=”bash” message=”” highlight=”” provider=”manual”]

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore HelloWorld-release-unsigned.apk alias_name

[/pastacode]

Now to the only trick part of this…

You need to “zipalign” your file:

[pastacode lang=”bash” message=”” highlight=”” provider=”manual”]

zipalign -v 4 HelloWorld-release-unsigned.apk HelloWorld.apk

[/pastacode]

Just make sure you have access to the zipalign executable from your terminal, if you don’t you could do something like this:

[pastacode lang=”bash” message=”” highlight=”” provider=”manual”]

~/Library/Android/sdk/build-tools/23.0.0/zipalign -v 4 HelloWorld-release-unsigned.apk HelloWorld.apk

[/pastacode]

If you’re on a Mac that should work. Now go to the play store console: https://play.google.com/apps/publish/

You need to pay $25 to get into their developer program, once you’ve done it, you should be able to create a new app and upload your apk that you generated above.

Git Tracking Remote Branches

For some reason, I’ve always failed to remember what the command to track a remote branch is in git. I look it up on this page everytime I want to do it: https://git-scm.com/book/en/v2/Git-Branching-Remote-Branches

Well no more. I figured if I write a post about it, I will remember it so here we go:

[pastacode lang=”bash” message=”” highlight=”” provider=”manual”]

git fetch origin
git checkout -b somename origin/somename

[/pastacode]

That’s it… the branch will be set up to track the remote and you are switched over automatically.

Using the Facebook iOS SDK in Swift

Just a quick video to show you how to use the facebook native ios sdk in swift.

follow the directions to get your plist file updated here: https://developers.facebook.com/quickstarts/?platform=ios

Once that’s done follow the instructions to add your build identity to facebooks records. Then…

  1. drag the frameworks into your project
  2. update your appdelegate file
  3. update your view controller
  4. make your view controller a delegate for the login button
  5. test
AppDelegate.swift:

replace your applicationdidlaunchwithoptions:

[pastacode lang=”javascript” message=”” highlight=”” provider=”manual”]

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
        return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
    }

[/pastacode]

Then add the following:

[pastacode lang=”javascript” message=”” highlight=”” provider=”manual”]

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
        return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
    }

[/pastacode]

Then in your “applicationDidBecomeActive“:

[pastacode lang=”javascript” message=”” highlight=”” provider=”manual”]

FBSDKAppEvents.activateApp()

[/pastacode]

NOTE: make sure to import:

[pastacode lang=”javascript” message=”” highlight=”” provider=”manual”]

import FBSDKCoreKit

[/pastacode]

ViewController.swift:

[pastacode lang=”javascript” message=”” highlight=”” provider=”manual”]

//
//  ViewController.swift
//  FacebookTutorial
//
//  Created by Mike Newell on 8/13/15.
//  Copyright (c) 2015 Mike Newell. All rights reserved.
//

import UIKit
import FBSDKCoreKit
import FBSDKLoginKit

class ViewController: UIViewController, FBSDKLoginButtonDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        if FBSDKAccessToken.currentAccessToken() != nil {
            // user already has access token
            self.logUserData()
        } else {
            let loginButton = FBSDKLoginButton()
            loginButton.center = self.view.center
            loginButton.readPermissions = ["email"]
            self.view.addSubview(loginButton)
            loginButton.delegate = self
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    override func viewWillAppear(animated: Bool) {
        self.logUserData()
    }
    
    func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
        println("logged in")
    }
    
    func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
        println("logged out")
    }
    
    func logUserData() {
        let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil)
        graphRequest.startWithCompletionHandler { (connection, result, error) -> Void in
            if error != nil {
                println(error)
            } else {
                println(result)
            }
        }
    }


}

[/pastacode]

That’s it! here’s a video explaining more:

There’s also a great tutorial for anyone looking to do the older “bridging” method of importing the sdk: http://www.brianjcoleman.com/tutorial-how-to-use-login-in-facebook-sdk-4-0-for-swift/