WKWebView. Return a value from native code to JavaScript

WKWebView exposes a comfortable way to call native code from JavaScript. So called Message handlers are defined in native code and can be later used in JavaScript like this:

webkit.messageHandlers.<handler>.pushMessage(message)

But what about return values? For as you know, WKWebView runs in its own process and that’s why pushMessage() function cannot return any value. It is not possible to get the return value from native function synchronously. It is also not possible to give a JS callback function to native function. So what to do, if we need a return value from native function?

There are several approaches how to realize and organize asynchronous communication of native code <-> JavaScript with WKWebView. The first thought is to implement another JS function that would be called from native code after operation on native side is finished, i.e.

JavaScript code:



function readStringFromFile(relativeFilePath) {
   webkit.messageHandlers.readFileHandlder.pushMessage({filePath: relativeFilePath});
}

// this function will be later called by native code
function readStringFromFileReturn(returnedValue) {
   // do you stuff with returned value here
}

And the corresponding handler implementation in Objective-C would look like this:

- (void)userContentController:(WKUserContentController*)userContentController
      didReceiveScriptMessage:(WKScriptMessage*)message {
    
    if([message.name isEqualToString:@"readFileHandler"]) {
        NSDictionary *paramDict = message.body;        
        NSString *filePath = [paramDict objectForKey:@"filePath"];
        NSString *resultString = [self readStringFromFileSynchronously: filePath];
        NSString *javaScript = [NSString stringWithFormat:@"readStringFromFileReturn('%@');", resultString];
        [self.webView evaluateJavaScript:javaScript completionHandler:nil];     
    }     
}

The described approach is not very elegant. If you have several functions in your interface between JavaScript and native code, the chained calls get very quickly confusing.

Much better approach is utilizing relative new concept of promises in JavaScript. I think, it’s also the way, Apple bore in mind when WKWebView has been introduced. More about promises can be read here or here. First, we need to extend our JavaScript:


// object for storing references to our promise-objects
var promises = {}

// generates a unique id, not obligator a UUID
function generateUUID() {
    var d = new Date().getTime();
    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                                                              var r = (d + Math.random()*16)%16 | 0;
                                                              d = Math.floor(d/16);
                                                              return (c=='x' ? r : (r&0x3|0x8)).toString(16);
                                                              });
    return uuid;
};

// this funciton is called by native methods
// @param promiseId - id of the promise stored in global variable promises
function resolvePromise(promiseId, data, error) {
    if (error){
         promises[promiseId].reject(data);
        
    } else{
       promises[promiseId].resolve(data);
    }
    // remove referenfe to stored promise
    delete promises[promiseId];
}


Our readStringFromFile function looks now like this:


function readStringFromFile(relativeFilePath) {
   var promise = new Promise(function(resolve, reject) {                                  
                                  // we generate a unique id to reference the promise later
                                  // from native function
                                  var promiseId = generateUUID();
                                  // save reference to promise in the global variable
                                  this.promises[promiseId] = { resolve, reject};
                                  
                                  try {
                                    // call native function
                                    window.webkit.messageHandlers.readFileHandler.postMessage({promiseId: promiseId, fileName: fileName}); 
                                  }
                                  catch(exception) {
                                    alert(exception);
                                  }
                                  
                                  });
        
        return promise;

}


The JavaScript code is self explaining. One important thing to mention is that the reference to the created promise-object is stored globally.

And now the Objective-C code:

- (void)userContentController:(WKUserContentController*)userContentController
      didReceiveScriptMessage:(WKScriptMessage*)message {
    
    if([message.name isEqualToString:@"readFileHandler"]) {
        NSDictionary *paramDict = message.body;
        NSString *promiseId = [paramDict objectForKey:@"promiseId"];
        NSString *filePath = [paramDict objectForKey:@"filePath"];
        NSString * resultString = [self readStringFromFileSynchronously: filePath];
        NSString *javaScript = [NSString stringWithFormat:@"resolvePromise('%@',%@, null);",promiseId, resultString];        
        [self.webView evaluateJavaScript:javaScript completionHandler:nil];     
    }     
}

As you can see the native function calls resolvePromise with return value. The code at JavaScript continues running, after the promise is resolved. What we are still missing, is the usage example for function readStringFromFile, which returns a promise object:


readStringFromFile("someRelativePath").then(function(returnedString) {
    var returnValue = returnedString;
    logToConsole(returnValue);
    // do your stuff here

  }, function(returnedString) {
      logToConsole('error');
  });

Utilization of promises as described above makes code more readable.It allows a clean definition of the interface between JavaScript and native code.

There are also other projects, aiming to enable easy communication between JavaScript in WKWebView and native code, e.g. XWebView. However, when integrating such components in your project be aware of:

  • you become dependent on third party development. Each newer version of SWIFT would make you to wait for compatible updates
  • they use the same messaging mechanism under the hood

About communication between JavaScript and native code in WKWebView

WKWebView is a replacement of UIWebView that is available since iOS 2.0. Apple encourages using WKWebView instead of UIWebView in its documentation:

Note

In apps that run in iOS 8 and later, use the WKWebView class instead of using UIWebView.

One of the key advantages of the new component is the more comfortable way to call native functions directly from JavaScript and to execute JavaScript functions at the native side. However, there are some limitations, which one should know:

  • WKWebView runs in its own process. On one hand it is a great performance improvement. On the on the hand it implies some unpleasant limitations in exchanging data between native app and the WKWebView
  • Native <=> JavaScript communication can only be asynchronous.
  • Native functions called from JavaScript cannot return values immediately.
  • The only way to return a value is to call another JavaScript function from native function with return value as parameter.
  • JavaScript functions can be called within native native methods only in global context.

To my opinion, limitations mentioned above are a step back comparing with UIWebView. With UIWebView it is possible to obtain JavaScript context and inject native(!) objects into that context by means of JSExport interface. There is then no difference wether you call a function on an injected object or some other JS function. Native functions can return values synchronously! The only disadvantage of this approach is that Apple has not exposed JavaScript context of the UIWebView officially. It is only possible to obtain the context  via private properties. That’s why this approach should not be used in product apps.

Start using Swift code in your Objective-C project

If you decided to start using Swift in your existing Xcode project, it can become a pain if your project is large and contains multiple targets. Follow steps below to be able to use Swift classes in your Objective-C code:

  1. Create a new *.swift file in your Objective-C project, or drag a .swift file with Finder
  2. Xcode prompts you to create an Objective-C bridging header file. Confirm it or add the bridging header manually
  3. Use @objc attribute for your Swift class:
    import Foundation
    
    @objc class YourController: UIViewController {    
    }
    
    
  4. In Build Settings of your project check parameters below:
    Defines Module : YES
    Install Objective-C Compatibility Header : YES => Once you’ve added *.swift file to the project this property will appear in Build Settings
    Objective-C Generated Interface Header : $(PROJECT_NAME)-Swift.h
  5. Import Swift interface header in your *.m file like this:
    #import "YourProject-Swift.h" // $(PROJECT_NAME)-Swift.h
    

iOS: Today Extensions / Widgets

A Today extension, also known as a widget, is a way for the app to provide quick access to its main functions and the up-to-date information in the Notification Center. The content for the widgets might be directly fetched from the web, but quite often there is a requirement to share data between the App and its widget.

How to add Today extension / Widget to an existing project?

Just add a new target of type “Today extension” to your project . To debug/start Today extension just select the proper target and run.

Can the same code, e.g. views and controllers, be shared/utilized between Widget and App targets?

Yes. Be sure to select checkboxes for the corresponding files in the “Target Membership” window of the Xcode. There are, however, some limitations, especially using swipe gestures. The swipe gesture triggers swiping between the Today and Notifications sections within Notification Center, so it doesn’t really provide the best or most reliable user experience.

What about CoreData in Widgets?

No problem, almost.. In general, by default, an App and its extension cannot access the same data, since their security domains are different. In order to solve this problem there should be created an App Group. An App Group provides a shared bundle that can be used by the app and its extensions as a shared container in which data can be stored. The App group can be configured in the apple developer portal (s. nice tutorial) or directly in Xcode under target capabilities.

Read More

Detecting incoming and outgoing calls in Android

Detecting incoming and outgoing calls in Android can be realized in several ways. One of the possibilities is to use a custom PhoneStateListener which can be attached to the TelephonyManager in your onReceive() function of the custom BroadcastReceiver. This is a “clean” way, beacause the BoradcastReceiver object is destroyed as soon as the onReceive() function is left. But if you just want to do some little stuff, you can implement your logic directly in the onReceive() function. Here how it works.

For detecting outgoing calls you need to register android.permission.PROCESS_OUTGOING_CALLS permission. The android.intent.action.NEW_OUTGOING_CALL will be broadcasted when an outgoing call is initiated. Use an extra string variable Intent.EXTRA_PHONE_NUMBER to detect the outgoing number.

For incoming call you need to register your BroadcastReceiver for the action android.intent.action.PHONE_STATE. This will be broadcasted when the phone state is changed. The receiving intent contains an extra string variable TelephonyManager.EXTRA_STATE. If this state is TelephonyManager.EXTRA_STATE_RINGING then there will be another extra string variable (! only if state = TelephonyManager.EXTRA_STATE_RINGING !). Use TelephonyManager.EXTRA_INCOMING_NUMBER to read the incoming phone number.

And now the corresponding code. In your manifest.xml add following lines for permissions:

 
 <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />

Furthermore add your BroadcastReceiver:

 
<receiver android:name="YourBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.PHONE_STATE"></action>
        <action android:name="android.intent.action.NEW_OUTGOING_CALL"></action>
    </intent-filter>
</receiver>

Your code would look like this:

public class YourBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
   Bundle bundle = intent.getExtras();
   if (bundle == null)
      return;
   String phoneNumber = null;
	
   // Incoming call
   String state = bundle.getString(TelephonyManager.EXTRA_STATE);
   if ((state != null) 
        &amp;amp;&amp;amp; (state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING))) {
	   phoneNumber = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);	
	   // Here: do something with the number	         
   }
   // Outgoing call
   else if (state == null) {		
      phoneNumber = bundle.getString(Intent.EXTRA_PHONE_NUMBER);
      // Here: do something with the number
   }  
 }	
}

Copy text to Clipboard in Android

Copy some text to a clipboard in Android is pretty simple. Use a code snippet below:

private void CopyNumber(String someText, Context context) {
     ClipboardManager clipMan = (ClipboardManager)context
                    .getSystemService(Context.CLIPBOARD_SERVICE);
     clipMan.setText(someText);
}

context parameter is required if you want to use the function outside Activities

Open Folder Dialog in Delphi

For as you know, Delphi does not really have a standard dialog for choosing a particular folder, like OpenFolderDialog. The function below uses ShellAPI and implements exactly the desired behaviour.

function GetFolderDialog(const ACaption: string; 
                      out ADirectory: string): boolean;
const
  BIF_NEWDIALOGSTYLE = $0040;
  BIF_NONEWFOLDERBUTTON = $0200;
 BIF_USENEWUI = BIF_NEWDIALOGSTYLE or BIF_EDITBOX;
var
  pWindowList: Pointer;
  tbsBrowseInfo: TBrowseInfo;
  pBuffer: PChar;
  iOldErrorMode: cardinal;
  pIemIDList: PItemIDList;
  pShellMalloc: IMalloc;
begin
  CoInitialize(nil);
  try
    Result := false;
    ADirectory := '''';
    FillChar(tbsBrowseInfo, sizeof(tbsBrowseInfo), 0);
    if (ShGetMalloc(pShellMalloc) = S_OK) 
                   and Assigned(pShellMalloc) then begin
      pBuffer := pShellMalloc.Alloc(MAX_PATH);
      try
        with tbsBrowseInfo do begin
          hwndOwner := Application.Handle;
          pidlRoot := nil;
         pszDisplayName := pBuffer;
          lpszTitle := PChar(ACaption);
          ulFlags := BIF_USENEWUI or 
                         BIF_RETURNONLYFSDIRS or 
                         BIF_NONEWFOLDERBUTTON;
          lParam := 0;
        end;
       pWindowList := DisableTaskWindows(0);
        iOldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
        try
          pIemIDList := ShBrowseForFolder(tbsBrowseInfo);
        finally
          SetErrorMode(iOldErrorMode);
          EnableTaskWindows(pWindowList);
        end;
        Result := Assigned(pIemIDList);
        if Result then begin
          ShGetPathFromIDList(pIemIDList, pBuffer);
          pShellMalloc.Free(pIemIDList);
          ADirectory := pBuffer;
        end;
      finally
        pShellMalloc.Free(pBuffer);
     end;
    end;
  finally
    CoUninitialize;
  end;
end;

Dynamic Programming Languages

The topic of current post is a special class of high level languages that execute dynamic programm code not known to a compile time. The key advantage of such languages is that a program and its parts written once can be later modified without recompiling the code! When can this bahaviour be useful?
Dynamic languages are widely used in web development and in games development. When a clear seperation of the fuctionality and content management is required, dynamic lanugages are of great help. For example you wrote a game and it’s obviously that it would be more better to handle the multilingual dialogs and other text in your game in such a way, that when you make changes to the content you don’t need to recompile your game.
Let’s start with PHP. It is currently one of the most popular languages in the web development sphere. PHP interpreter is typically installed as a module into a webserver like Apache and executes scripts written by programmers. There is also a standalone version of PHP, that supports GUI development. Familiar evolution process is revealed by Perl. There also exist implementations as a module and as a standalone application. Perl was first time released in 1987. It partly borrows syntax and language constructions from a set of languages like C, shell (sh), AWK and Lisp.

Looking once for a dynamic language for PDAs I came across Tcl with graphical user interface toolkit Tk. The advantage of TCl/Tk is its platform independence. A program implemented in TCL/TC can be interpreted and executed on the most popular platforms like Linux, Macintosh, Windows, Windows CE etc. The only differece is look and feel of user interface components. The early versions of TCL didn”t support OOP but nowadays there are implementations supportig the advantages of OO concept.

Another dynamic language I’d like to introduce is Python. It’s a stable and a very popular multi-paradigm programming language. Python is used in such large projects as Youtube, Zope etc. Besides Python standalone version there exists  java implementation of Python called Jython and .NET integration of Python called IronPython. In these implementations one can execute pythons scripts within java or .Net programs. Unfortunately, I found out that IronPython doesn’t work in Compact Framework because annotations aren’t fully supported in CF and IronPython rely on these libraries very strong.

A good alternative to Python is Lua. There are also implementations of this interpreter for many popular platforms. Lua integration with Java is called LuaJava and the .NET version is called Lua.NET. Lua”s interpreter is very small and very quickly. Lua is often used for games creation. The most popular games implemented in Lua are: World of Warcraft, Monkey Island 4, Parkan 2 etc. Unfortunately, the documentation for Lua leaves much to be desired.

For more information on dynamic programming languages please refer to wiki article Dynamic Programming Languages. For more information on scripting languages supported in Java visit this page.