Nov 15, 2015

Manually refresh (and clear cache on) current page on IonicView as needed

Ionic v1.2.4

If you've looked around for a solution to manually clear cache and refresh current page, you'll more likely found solution like below.

$ionicHistory.clearCache().then(function () {
  $state.go($state.current, {} , {reload: true});
});


After I've tried the solution above, it doesn't really work as expected, and I don't see how it clear the view cache for current page.
My First try with

$ionicHistory.clearCache().then(function () {
  $state.go($state.current, {} , {reload: true});
});

the page/view would just be redirected with $state.go(), and does not has it cache cleared (it still shows the old content).

As I roughly went through the ionic.bundle.js, I found $ionicHistory.clearCache() actually does accept array value, stateIds, as parameter to clear the view cache specifically.

So, the final solution to the expected result (manually clear cache and refresh current page):

$ionicHistory.clearCache([$state.current.name]).then(function () {
  $state.go($state.current, {}, {reload: true});
});

As you can see, I added the [$state.current.name] to specifically assign each required view cache to be cleared. And so, that's what required for $ionicHistory.clearCache() to work properly.

Nov 13, 2015

Cordova Plugin not found

Today I ran into Cordova plugin mapping issue.

Spent around 2 hours time to find out the root cause of the missing plugin,
it happens every time we rebuild iOS before any plugin is cloned.

To replicate the problem:

  1. In the cordova app project directory, remove "plugins" & "platforms" folders
  2. run `cordova platform add ios` to add platform directly (this step will fetch required plugins stated in config.xml and generate the iOS platform)
  3. Once iOS platform is ready, run `cordova run ios`.
The three steps above will lead you to problems like screenshot below.
plugins not found
Plugins not found
ERROR: Plugin 'File' not found, or is not a CDVPlugin. Check your plugin mapping in config.xml.
["File334867545","File","requestAllPaths",[]]
ERROR: Plugin 'NetworkStatus' not found, or is not a CDVPlugin. Check your plugin mapping in config.xml.
inJSON = ["NetworkStatus334867546","NetworkStatus","getConnectionInfo",[]]
ERROR: Plugin 'Device' not found, or is not a CDVPlugin. Check your plugin mapping in config.xml.
788:2282747] -[CDVCommandQueue executePending] [Line 159] FAILED pluginJSON = ["Device334867547","Device","getDeviceInfo",[]]
In case I proceed by ignoring those "plugin not found" issues,
and run the buggy app on my device.
I'll end up getting errors like below in my debugging tool's console:
deviceready has not fired after 5 seconds
Channel not fired: onPluginReady
Channel not fired: onCordovaReady


To workaround this issue,
you'll need to rebuild the cordova iOS platform again with all the plugins fetched at first.

Now, since I have all the required plugins ready (from previous added iOS platform),
I'll keep the fetched plugins (inside plugins folder) and follow the steps below.

Remove and add back the iOS platform:
  1. cordova platform rm ios
  2. cordova platform add ios

Cordova: phonegap-facebook-plugin alternative with Facebook SDK 4

There are choices of cordova Facebook login plugins available, but I found two useful at the time I'm developing my Cordova mobile app.

Those are:
- phonegap-facebook-plugin
- cordova-plugin-facebook4

phonegap-facebook-plugin is mostly recommended by the internet community at the time I am writing this, as example ngCordova - Facebook,
but it caused some UX and development issues to me as a developer.

phonegap-facebook-plugin
It uses FacebookSDK version 3.21.1, with this SDK, for iOS 9, it leads to problems like:
  • must not have bitcode enabled (activated by default in xcode 7)
  • requires manually add whitelist Facebook access every time you have your iOS platform created
  • Every login will leave a blank safari browser opened for Facebook browser login (unless user has native Facebook app installed)
  • Symlink of FacebookSDK is broken with direct cordova plugin add phonegap-facebook-plugin
cordova-plugin-facebook4
The purpose this plugin is to make use of FacebookSDK 4.
  • It helps saving the drudgery on adding LSApplicationQueriesSchemes and NSSApplicationTransportSecurity items.
  • support bitcode encoded, so you don't need to deactivate it every rebuild of the cordova platform.
  • Time saving on git cloning to workaround broken FacebookSDK symlink.

Added 2015-11-13 10:55 PM
the only bad thing about cordova-plugin-facebook4
there is different between plugin cloned by cordova added through new platform build (cordova platform add ios/android) with the one manually added with cordova cli (cordova plugin add).

Differences:

# Cloned with platform add Plugin added with cordova cli
1 Need manual add of
LSApplicationQueriesSchemes
Auto added
2 Bitcode_enabled to be disabled support bitcode_enabled
3 Facebook login with
safari browser
Do not need external browser
for Facebook login 

Even though both cordova cloned with platform and cli are the same cordova-plugin-facebook4,
but at the time I developing,
it does has differences as your installation method is different.

Furthermore,
if you already have cordova-plugin-facebook4 saved into config.xml,
running cordova plugin add cordova-plugin-facebook4 (with variables) again will update itself into a different version plugin.

my case:
    <plugin name="cordova-plugin-facebook4" spec="~1.3.0-0">
        <variable name="APP_ID" value="FB_APP_ID" />
        <variable name="APP_NAME" value="FB_APP_NAME" />
    </plugin>

run cordova plugin add cordova-plugin-facebook4 --save (with variables) again, will become:
    <plugin name="cordova-plugin-facebook4" spec="~1.1.0">
        <variable name="APP_ID" value="FB_APP_ID" />
        <variable name="APP_NAME" value="FB_APP_NAME" />
    </plugin>

Nov 10, 2015

Use ngCordova inAppBrowser executeScript interacting with remote WebView content

Even the idea/solution very straight forward, but still, I learned ngCordova's inAppBrowser the hard way.

I am using cordovaInAppBrowser to handle my remote content in mobile's WebView.
Tutorials accessible out there mostly give you the idea of how it works in direct content display, like:


// insert Javascript via code / file
$cordovaInAppBrowser.executeScript({
  code: 'alert("some text in the webview");'
});


Yes, it does tell the code is working in the webview,
but my problem is how can the value be manipulated and pass back to our cordova app?
So what we need is more than pop up alert box in webview.

As I learned,

  1. executeScript code WOULD JUST work when we have target as "_blank"

    // executeScript must has "_blank" as target
    $cordovaInAppBrowser.open(YOUR_URL, '_blank');
    

  2. the executeScript code would just run once as inAppBrowser page load/refresh depend on the events triggered:
    • $cordovaInAppBrowser:exit
    • $cordovaInAppBrowser:loaderror
    • $cordovaInAppBrowser:loadstop
    • $cordovaInAppBrowser:loadstart

So what you can do with this executeScript feature is to 'grab' your expected variable.

$rootScope.$on('$cordovaInAppBrowser:loadstop', function(e, event){
  $cordovaInAppBrowser.executeScript({
    code: "var executable = function(data) { return data; }; executable(yourJsVariable || null);"
  }).then(function(data) {
    // Do something here with your obtained value
    if (angular.isObject(data)) {
      console.log(data);
    }
  });
});

In my case above, my detection of yourJsVariable starts as the page load of the inAppBrowser stops.

Reference: Issue injecting external script with executeScript method in Cordova
(The reference above is the best working example code I found so far.)

Nov 7, 2015

Short Note: HTML5 localStorage - think "resume"

Just realise something that I have been using it so long,
while still not knowing one of the best part of its "resumable" feature.

It keeps what you last stored in the localStorage, and won't lost the stored data until you do it manually.

In this case,
we can check any progress updated before any kind of interruption,
and resume the progress from there.

One of my concern was that I didn't know I can really trust the stored data while having an interruption happens in the middle of the process.

Thanks to Dive Into HTML5: HTML5 Storage in Action,
I should start utilise it with progress status data and think localStorage from know on.
(Even though it isn't a very new thing anymore)