COOKIES! This blog uses cookies!
I am completely out of control of cookies here, otherwise I would have disabled them (it is controlled by the platform).
If you don't like cookies and being tracked please leave this blog immediately.

Thursday, 16 April 2015

Redirect user directly from a webpage to a cordova / phonegap app

There's a Cordova/Phonegap plugin to define custom schemes:
>cordova plugin add https://github.com/EddyVerbruggen/LaunchMyApp-PhoneGap-Plugin.git --variable URL_SCHEME=mycoolapp

The plugin will automatically update a platform config when the platform added or updated.

With this plugin installed custom scheme URLs like two below will invoke the application:
mycoolapp://
mycoolapp://testscreen

It is also possible to handle these URLs in your hybrid app. The handleOpenURL is called when the application is invoked via the custom scheme
/**
 * Custom schema launch plugin callback
 * @param url
 */
var handleOpenURL = function(url) {
    //your code to process the url
};

The example with AngularJS redirecting user to some particular screen of app:
/**
 * Custom schema launch plugin callback
 * @param url
 */
var handleOpenURL = function(url) {
  setTimeout(function(){
    var hash = url.replace("slingshotapp://","");
    var body = document.getElementById("mySlingshotApp");
    var app = angular.element(body);
    var $injector = app.injector();
    var $scope = app.scope();
    var $location = $injector.get('$location');
    $location.path('/'+hash);
    $scope.$apply();
  },300);
};

Please notice that if you install the plugin with the --save flag it will save the URL_SCHEME variable as `prop`, but it should be saved as a `variable` in order to be properly restored on `plugin add` or `update`. Here's the proper feature definition for config.xml:
    <feature name="Custom URL scheme">
        <param name="id" value="nl.x-services.plugins.launchmyapp" />
        <param name="url" value="https://github.com/EddyVerbruggen/LaunchMyApp-PhoneGap-Plugin.git" />
        <variable name="URL_SCHEME" value="mycoolapp" />
    </feature>

Friday, 10 April 2015

Invoke phone Dialer from Cordova / Phonegap

There's a "tel:" schema available to invoke an external dialer from the app.

The usage example:
<a href="tel:0-800-202020">0-800-202020</a>

It works in the same way for other schemas such as "mailto:", "sms:", "geo:" and "market:".

To enable this functionality the following access permissions should be added into the config.xml:
<access origin="tel:*" launch-external="yes"/>
<access origin="geo:*" launch-external="yes"/>
<access origin="mailto:*" launch-external="yes"/>
<access origin="sms:*" launch-external="yes"/>
<access origin="market:*" launch-external="yes"/>

Tuesday, 31 March 2015

My git cheatsheet


Rebase changes from the master onto current branch

Fetch changes first
git fetch

Rebase
git rebase origin/master

Push
git push origin yourbranchname -f

Branches

Rename/move branch
git branch -m <oldname> <newname>


Tags

Add a tag
git tag -a v1.2 -m 'my annotation for v1.2'

Push the tag:
git push origin v1.2


Diverges
Solutions other than normal merge / mergetool workflow

Hard reset to the origin
git reset --hard origin/branchname

Fixing diverge by deleting branch (loosing you changes)
Checkout master:
git checkout master

Delete diverged branch (dispose all local changes):
git branch -D branchname

Checkout branch back:
git checkout branchname

Fixing diverge by hard reset to some particular commit (loosing you changes)
git reset --hard g00dcmid
assume that you're currently at diverged branch and g00dcmid is a last commit before diverge
please be aware that it will revert all files in the INDEX and in the WORKDIR

Reverts

revert a commit
git revert c0mm1tid
notice, that this will revert this particular commit, not revert to this commit

delete local commits
git reset --hard <commit or branch>

Search

search in commit names
git log --all --grep='some stuff'
--all means - search in all branches

search in patches / diffs (Pickaxe)
git log -S "text to find"
it is also possible to add -p option to list actual diffs

Diffs

show staged diff
git diff --cached

add only non white-space changes
git diff -w --no-color | git apply --cached --ignore-whitespace

Local User
Define a user for single repository:
git config user.email "your@mail.com"
git config user.name "Your Name"

Monday, 23 March 2015

Json Formatter is a pretty good chrome extension to render JSON in human-readable format:
https://chrome.google.com/webstore/detail/json-formatter/bcjindcccaagfpapjjmafapmmgkkhgoa?hl=en-GB

Monday, 9 March 2015

Sending iOS push notifications from JAVA

This post was originally posted in 2015 and most likely to be irrelevant today. 
It remains published solely for historic reasons.

This example presumes that you've already registered your device for Push Notifications and retrieved the device token from the Apple Push Notification Service (APNS) on the iOS side.
The code below uses the notnoop/java-apns Java library to send notifications to the APNS server.

The code

Suggested files structure:
src/main/java/PushNotifications.java - simple java class to send notifications
src/main/resources/dev_cert.p12 - development certificate
src/main/resources/prod_cert.p12 - production certificate
pom.xml - maven config

pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>PushNotifications</groupId>
    <artifactId>PushNotifications</artifactId>
    <version>1.0</version>

    <dependencies>
        <dependency>
            <groupId>com.notnoop.apns</groupId>
            <artifactId>apns</artifactId>
            <version>1.0.0.Beta6</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.7</version>
        </dependency>
    </dependencies>

</project>

PushNotifications.java:
import com.notnoop.apns.APNS;
import com.notnoop.apns.ApnsService;
import com.notnoop.apns.ApnsServiceBuilder;

public class PushNotifications {

    public static void main(String [] args) {
        System.out.println("Sending an iOS push notification...");

        String token = "";
        String type = "dev";
        String message = "the test push notification message";

        try {
            token = args[0];
        } catch (Exception e) {
            System.out.println("Usage: PushNotifications devicetoken [message] [type prod|dev]");
            System.out.println("example: PushNotifications 1testdevicetoken3eb414627e78991ac5a615b4a2a95454c6ba5d18930ac137 'hi there!' prod");
            return;
        }
        try {
            message = args[1];
        } catch (Exception e) {
            System.out.println("no message defined, using '"+message+"'");
        }
        try {
            type = args[2];
        } catch (Exception e) {
            System.out.println("no API type defined, using "+type);
        }

        System.out.println("The target token is "+token);

        ApnsServiceBuilder serviceBuilder = APNS.newService();

        if (type.equals("prod")) {
            System.out.println("using prod API");
            String certPath = PushNotifications.class.getResource("prod_cert.p12").getPath();
            serviceBuilder.withCert(certPath, "password")
                    .withProductionDestination();
        } else if (type.equals("dev")) {
            System.out.println("using dev API");
            String certPath = PushNotifications.class.getResource("dev_cert.p12").getPath();
            serviceBuilder.withCert(certPath, "password")
                    .withSandboxDestination();
        } else {
            System.out.println("unknown API type "+type);
            return;
        }

        ApnsService service = serviceBuilder.build();


        //Payload with custom fields
        String payload = APNS.newPayload()
                .alertBody(message)
                .alertTitle("test alert title")
                .sound("default")
                .customField("custom", "custom value").build();

        ////Payload with custom fields
        //String payload = APNS.newPayload()
        //        .alertBody(message).build();

        ////String payload example:
        //String payload = "{\"aps\":{\"alert\":{\"title\":\"My Title 1\",\"body\":\"My message 1\",\"category\":\"Personal\"}}}";


        System.out.println("payload: "+payload);
        service.push(token, payload);

        System.out.println("The message has been hopefully sent...");
    }
}
Compile the code:
>mvn compile

Run the code:
>mvn exec:java -Dexec.mainClass="PushNotifications" -Dexec.args="1testdevicetoken3eb414627e789ba5d18930ac137 'My test iOS push notification!' dev"

Getting certificates from the Apple
Certificates are quite tricky and confusing part of iOS push notifications.

1. First of all we need to create a SigningRequest
Keychain Access -> Certificate Assistant -> Request a certificate from a Certificate Authority
Enter the apple dev email into the Certificate Assistant form, select the "Save to disk" radio
Save the Signing Request onto the disk (don't forget to give it some reasonable name);

2. Go to the developer.apple.com/account/ios/
Certificates, Identifiers & Profiles > App IDs > [the app id] > Edit > Push notifications >
Production SSL Certificate > Create / Create Additional,
ensure that Push Notifications enabled for your app,
Generate a new certificate using the SigningRequest from 1.
Download the generated certificate;

3. (on the Mac) Double click the certificate to import into the keychain;

4. Locate the Certificate in the Keychain Access, expand it to see the Key inside,
right click and Export "keyname"...
Save the p12 file;

5. Notice that after regenerating your certificates you need to refresh your provisioning profiles and use them to deploy your app. In xCode go to Preferences -> Accounts, selet your dev apple-id, click "View Details", do refresh. It is not going to be a problem, if you generated the certeficates before getting to code.

Monday, 23 February 2015

Eclipse hotkeys / shortcuts

These are useful shortcuts I always forget after a few weeks not using Eclipse:

Show shortcuts list: ctrl+shift+L

Spellcheck suggestions: ctrl+1
Quick fix suggestions: F2

Rename all occurencies: shift+alt+R
Open resource: ctrl+shift+R
Show Occurrences: ctrl+shift+U
Enable “Block”(rectangle) selection: alt+shift+A
Duplicate Line: ctrl+alt+UP

Select blocks of code: alt+shift+Up (each press selects block one level higher)
De-select blocks of code: alt+shift+Down (each press selects block one level higher)

type hinting (for dynamic typing languages): /* @var $varName \Type */


Preserve case replace:
ctrl+f (edit->find/replace)
tick "Regular expressions" check-box
Find: general
Replace with: \CSeparate

Here \C is a regex retain-case operator it will cause the following results of replacements:
general->separate
General->Separate

Friday, 20 February 2015

Get document PDF preview in Alfresco

Alfresco is able to transform document types.
For example transform MSWord doc file into PDF

The quick way to access PDF preview (or of any other available type) is a ThumbnailService

An example:
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
//...
public class YourClass{
  //...
  @Autowired
  ThumbnailService thumbnailService;
  //...
  public yourMethod {
      NodeRef documentNodeRef = new NodeRef(
          request.getParameter("nR")
      );
      NodeRef pdfPreviewNodeRef = null;
      //...
      pdfPreviewNodeRef = thumbnailService.getThumbnailByName(
          documentNodeRef, ContentModel.PROP_CONTENT, "pdf"
      );
      if (pdfPreviewNodeRef==null) {
        //generate a new PDF preview if one is not available yet
        pdfPreviewNodeRef = thumbnailService.createThumbnail(
            documentNodeRef, ContentModel.PROP_CONTENT,
            "application/pdf", new SWFTransformationOptions(), "pdf"
        );
      }
      //...
  }
  //...
}