Monday, July 31, 2017

iOS UIWebView, NSURLSession cache

NSURLSession can handle cache based on the NSURLSessionConfiguration.requestCachePolicy property. 

The default value of the requestCachePolicy property is NSURLRequestUseProtocolCachePolicy (0), when the default value is used, the cache validation and loading is transparent to application implementation. For example, when a request is sent to server by NSURLSession, if the cached response is available using etag as validator. Then NSUrlSession will automatically add the "If-None-Match" header in the request before sending the request to server. If server side sees the response data is not changed based on the etag value, the server will return 304 (not modified) to client without response data. When NSURLSession gets the 304 response status from server, it will load the cached response, and call the NSURLSessionDataTask's completion block with the status code and response data loaded from the cached response, so the application will only the status code is 200 instead of 304.

If you want to prevent this automatic cache management, then you can set requestCachePolicy property to NSURLRequestReloadIgnoringLocalCacheData. For example, if etag is used for validate the cache, then nsurlsession will not add the required IF-NONE-MATCH header to the client request, and the server will always return a full response.

Note, if you want to test and verify the cache works properly in your app, you have to log the device http traffic, as the delegate of NSURLSession will never see the 304 status code returned from server, it will be automatically replaced by the status code in the cached response. Besides, do not explicitly add the cache validation header, such as If-None-Match or If-Modified-Since in your request, as NSURLSession will automatically add those header is needed.

For UIWebview, in addition to the default ios cache management NSURLCache, it also has an additional in memory cache management. This in memory cache manager will add the conditional cache header if necessary. So When using NSURLProtocol to intercept the xmlhttprequest, you may see the additional headers are automatially added to the requests. In case server returns 304 to those requests, the UIWebView will automatically load the cached response from memory and return to xmlhttprequest callback method using the status code and data saved in the cached response. When loading cached response from the in memory cache, the default NSURLCached is not involved.

Tuesday, July 25, 2017

Get iphone/ipad Device Identifier from ITune

Get device id from xcode is quite easy, just open from Window->Device menu and select the device will get it.

Get device id from iTune on mac is little bit trick.
1. First open the iTune and select the device by clicking the device icon

2. Select Summary item on left side list, it will show the Serial number as shown below

3. the trick is clicking on the "Serial Number" label field, and it will show the device id as UDID


Sunday, July 23, 2017

Android Studio editor shortcut keys on mac

Auto Format:
Command+Option+L

Comment/Uncomment toggle:
Command+/  (/ is forward slash)

go back to last visited line
Command +[

Go forward last visited line
Command + ]

Indent 
<TAB>

Reverse Indent
Shift + <Tab>

Show and add the override methods from the base class
Control + O

If a class name does not import the package automatically, edit the class name to trigger the auto import.

Friday, July 21, 2017

Fix gradle error when building old version of kapsel (SP14) andorid cordova project

When building android cordova project (kapsel sp14) with new version of android sdk, after imported the project into android studio, a few gradle related build errors may be reported. The following steps can be used to fix the error:

1. Open module build.gradle, and remove productFlavors section as empty, this will avoid the NDK error
if (Boolean.valueOf(cdvBuildMultipleApks)) {
    productFlavors {
    }
}

2. in the same build.gradle file, update gradle version and gradle plugin version as the latest one
dependencies {
    classpath 'com.android.tools.build:gradle:2.3.3'
}


task wrapper(type: Wrapper) {
    gradleVersion = '2.14.1'
}


Another simple way to updating gradle and gradle plugin version is, after importing the project into android studio, select File->Project structure menu and then update the gradle and gradle plugin version the default one used by android studio.

Tuesday, July 18, 2017

Using cordova channel to handle javascript event

Cordova uses channel&subscribe to fire and handle event. This logic can also be used in application logic. The APIs are quite easy to understand, so using the APIs does not need to know the details of the implementation. Actually, the cordova channel&subscribe model can be used in a regular js file not be part of a cordova plugin.

The below is a sample to using cordova channel to create an event, subscribe to the event and fire the event.

In index.html
<button onclick="createevent()">create event</button>
<button onclick="subscribeevent()">subscribe event</button>
<button onclick="fireevent()">fire event</button>
<button onclick="unsubscribeevent()">unsubscribe event</button>



In js file
function createevent(sticky){
   var channel = cordova.require('cordova/channel');
   channel.createSticky('myevent');
}

function subscribeevent(event){
    var channel = cordova.require('cordova/channel');
    channel.myevent.subscribe(handler);
}

function handler(e){
    alert("event fired: " + e);
}

function fireevent(event){
    var channel = cordova.require('cordova/channel');
      channel.myevent.fire("my event obj");
}