Testphase wird am 30.04.2017 abgeschlossen

Die PolterApp ist nun seit knapp 9 Monaten im App-Store. Sie wurde inzwischen mehrere Hundertmale installiert und wird täglich in verschiedenen Forstbetrieben eingesetzt. Diejenigen Nutzer, die am Beta-Testing aktiv teilgenommen hatten, haben einen großen Beitrag an die Entwicklung der App geleistet. Dank der engen Zusammenarbeit ist ein stabiler Stand erreicht worden, der auch funktional alle Basis-Bedürfnisse der täglichen Arbeit abdeckt. Damit kann die Beta-Phase als erfolgreich bezeichnet werden und wird damit am 30.04.2017 abgeschlossen.

Wie geht es nun weiter? Damit die PolterApp auch weiterhin entwickelt werden kann, wird die App ab dem 01.05.2017 kostenpflichtig zu einem fairen einmaligen Preis von 27,99 Euro angeboten. Das betrifft nur die Neu-Käufe. Alle Beta-Tester, die PolterApp auf ihrem Device haben, müssen nichts tun und nichts zahlen. Wurde die App ein mal kostenlos installiert bleibt sie und die zukünftigen Updates absolut kostenlos. Daher ein Tipp an die PolterApp-Nutzer und potenzielle Interessenten: bis zum 30.04.2017 bleibt noch Zeit die App kostenlos zu erwerben.

HTTPS request with self signed certificate in iOS 10.3

iOS 10.3 seems to handle self signed certificates different then iOS 10.2. Even with the option NSAllowsArbitraryLoads enabled the request fails with the error:

The certificate for this server is invalid. You might be connecting to a server that is pretending to be “Domain name” which could put your confidential information at risk.

To fix the issue install the self signed certificate as usual. Afterwards go to

Settings -> About -> Certificate Trust Settings

and just enable the Full Trust for your root certificate.

No Password Field in Skype Login Dialog

I faced the problem for the first time 2 years ago on Windows 7 computer with Internet Explorer 11. After launching skype a blanc window appeared. There were no input fields for entering user name and password. Searching for the answered in the internet revealed some interesting facts:

  • skype relies on Internet Explorer engine for displaying the login window
  • it plays no role, wether IE is your default browser. You may use Chrome, Firefox, Safari etc., but skype still embeds Internet Explorer and obviously accesses its settings

The login problem was fixed by creating a skype shortcut on the desktop and editing the starting parameters:

"C:\Program Files\Skype\Phone\Skype.exe" /legacylogin

Quotes are important! The starting parameter /legacylogin used to force skype to call the “old fashioned” login window instead of the window based on Internet Explorer. However, in the current version of Skype 7.34 this workaround seems not to work anymore… And again searching and verifying various solutions. At last I found out, that it is possible to start skype directly with username and password parameters!

"C:\Program Files\Skype\Phone\Skype.exe" /username:YourUserName] /password:YourPassword

Hopefully, this workaround continues to work after the next skype update.

Progressive Web Apps

Last week I had a pleasant acquaintance with Adam Giemza, head of solution architecture and security at DB Schenker AG. He asked me about Progressive web and my opinion to it. Frankly speaking, I had no opinion at all, because I’m specialized more on native apps for iOS and Android. Of course, hybrid apps, mobile first approach, responsive design are the things I heard of and had even a bit experience with them. But what are Progressive web apps? I began to read about it.

The term “progressive web” appeared 2015  to describe web apps taking advantage of features supported by modern browsers, including Service Workers and Web App Manifests. Progressive web apps are:

  • Progressive – Work for every user, regardless of browser choice because they’re built with progressive enhancement as a core tenet.
  • Responsive – Fit any form factor: desktop, mobile, tablet, or forms yet to emerge.
  • Connectivity independent – Service workers allow work offline, or on low quality networks.
  • App-like – Feel like an app to the user with app-style interactions and navigation.
  • Fresh – Always up-to-date thanks to the service worker update process.
  • Safe – Served via HTTPS to prevent snooping and ensure content hasn’t been tampered with.
  • Discoverable – Are identifiable as “applications” thanks to W3C manifests and service worker registration scope allowing search engines to find them.
  • Re-engageable – Make re-engagement easy through features like push notifications.
  • Installable – Allow users to “keep” apps they find most useful on their home screen without the hassle of an app store.
  • Linkable – Easily shared via a URL and do not require complex installation.

As far as I understand the main difference to the hybrid apps, e.g. based on Cordova is that progressive web apps are not wrapped into some mobile application, but are more like a website. It is the web browser features, i.e. service worker and manifest which make these web application look and feel like native apps. And in opposite, the difference to a responsive web site is that progressive web apps can be used offline and look more “native”.

The concept of progressive web apps is very interesting. It is on one hand the next step towards cross platform development. On the other hand it is the step towards app distribution without app stores. I can think of many use cases where a progressive app has more advantages over native implementation for multiple platforms. Some examples of progressive web apps can be found here.

 

“App Programmierer” auf Ebay Kleinanzeigen

Auf Ebay Kleinanzeigen wird man fündig. Gebrauchte Lampen, Fernseher, Spielzeuge, Gartenmöbel und auch “App Programmierer”. Die letzteren werden zwar selten angeboten, dafür aber gerne gesucht.

Ich habe eine sehr gute Idee für eine App für Smartphones und würde diese gerne umsetzen

Ich bin auf der Suche nach engagierten und couragierten Programmierer

Ich brauche eine App, wo man mit Geld verdienen kann

Das sind nur ein Paar Anzeigen, die in Essen im Umkreis von 10 km veröffentlicht sind. Um Gesuche besonders attraktiv zu machen, werden Berge aus Gold versprochen, allerdings erst wenn sich die Projekte rentieren. Ein User mit dem Namen “Eva” möchte gerne auch ein oder mehrere Entwickler für die Umsetzung seine Ideen gewinnen. Anteile am Startup, Mitbestimmungsrecht und andere irdische Güter wären dabei denkbar. Davor hat Eva 15 andere Anzeigen veröffentlicht: Alufelgen, hochwertigen Schubladenschrank, Couchtisch… warum eigentlich nicht was anderes probieren?

 

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.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&amp;amp;amp;amp;amp;amp;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

VMWare Fusion: /dev/vmmon konnte nicht geöffnet werden

On my MacBook Pro I have VMWare Fusion with Windows 10 installed. It worked quite well until I started getting following error message:

 

/dev/vmmon konnte nicht geöffnet werden: Es existiert keine Datei und kein Ordner dieser Art. Stellen Sie sicher dass das Kernelmodul “vmmon” geladen ist.

It is the same as the the english variant

Could not open /dev/vmmon: No such file or directory.

First, I thought it could be an error after upgrading the MAC OS from Yosemite to Mavericks. However, it turned out to be a conflict with Oracle’s VirtualBox, known as Oracle VM VirtualBox. VirtualBox is a free software for running virtual machines, i.e. same purpose as VMWare. I didn’t realize, that it was installed on my MAC. It might came with some other Apps, that were previously installed. Like Android emulator “Andy” or some other.

So how to fix the issue? Just uninstall VirtualBox. Follow the steps below:

The system restart is not required, your VMWare Fusion should work from now on properly. If you need VirtualBox in the future for other apps, you can install it again from Oracle’s website.