Pages

Tuesday, June 23, 2015

Get your mac device's (iPhone/iPad) UDID from the command line

Add this to your .bashrc or .bash_aliases
alias udid="system_profiler SPUSBDataType | sed -n -e '/iPad/,/Serial/p' -e '/iPhone/,/Serial/p' | tail -n1 | sed 's/Serial Number: //'"
Then hit
udid
.

Monday, February 16, 2015

Musings on libnodejs (or libiojs) on Android

What can you do with nodejs on android?

Here are some examples:

  • Run your own server in nodejs on your android device, using the same code you would use for a nodejs x86/x86_64 back end! (e.g. udp/tcp/ip, http, websocket, bit/webtorrent server, webrtc client/STUN/TURN/ICE server);
  • Use existing libraries and code for nodejs and run them in your pocket; (which reminds me NPM (not-paid monkey) is on my TODO list)
  • Connect to other android devices running nodejs;
  • Run nodejs on wearables (ehhh... run a server on your watch?);
  • Use the same javascript client code for testing/production on android;
  • Connect to android sensors/instruments/services via unix domain sockets. (e.g. bluetooth);
  • Connect nodejs with android.webkit.WebView and recreate cordoba/phonegap (wretch);
    • Run cordova-cli on your android device directly;
    • Create stunningly fast mockups with (local) back end code in nodejs
I feel that my hobby/job is coming to full circle, I started out coding in C/C++/javascript/java at the uni. Now I'm still coding in the same languages, but with one more in the mix, Xtend(lang).

I'll clean up my code and release a POC (piece of crap) on the android app store.

Friday, February 13, 2015

Progress report: nodejs / iojs on android

I set out to embed node in an android application and I have succeeded in doing so. It's not an earth-shattering accomplishment, but I'm happy all the same.

I'm exploring ways of passing state between an embedded nodejs instance on android and an android zygote process, via unix domain sockets and http sockets. If the unix domain socket method works, then JNI calls to pass state to and fro can be eliminated completely, except for setting up a nodejs instance.

I managed to build shared libraries and executables for arm-android using either libnodejs.so and libiojs.so. I can load it using an activity-bound sticky android.app.Service and load an http-stream repl script.

I documented how I got there here.

Also, see this commit on how to build the shared lib.

I have a working http-stream REPL via an android device's localhost:8000. Any machine can connect to it.

I'm currently working on a way to expose a node CLI/REPL to the user using android.widget.{EditText, TextView} combined with an android domain socket REPL.

After experimenting with node's domain socket server creating abilities on x86-linux and arm-android, I came to the conclusion that android.net.LocalSocket and nodejs domain socket server will not play nice with each other.

After a lot of pacing and some hair-loss, I realized that I have to determine whether bionic is being called properly by libnodejs (on android).

Right now I have two options:
  • Determine that node's C++ code is calling bionic properly to create a domain socket;
  • turn it around: let android create a android.net.LocalServerSocket, let node connect bind/connect with a domain socket client and start the REPL on the client. I'll have to see if this even works on x86-linux.
I also put some effort into stdio redirection, in the hope that the built-in REPL in nodejs would kick in, but that sort of magical thinking usually leads to nowhere, and it didn't.

Update 14-feb-2015:

Next step: fix libuv; I suspect that pipe.c is not properly coded for android; I suspect that android.net.Local bind/connect fails due to a bad addrlen. According to the code in Pro Android with the NDK page 267-268, a socket that is not in the linux abstract namespace and its addrlen must comply to certain rules, the most important rule is the address length.

Update (same day):

Inserted #if defined(__ANDROID__) ... statements to pipe.c and reused libcutils code instead of libuv socket code, that is shared with android.net.Local(Server)Socket's native methods.

Still not connecting.

Update 16-02-2015:

Mission accomplished. My modified libuv can connect with android.net.LocalSocket over a filesystem-based domain unix socket.

In theory my modification supports abstract domain unix sockets, but I don't know if libuv even supports this.

This means that I have IPC over domain sockets on android, between the main thread and the thread running nodejs.

I have tcp/udp/unix domain socket communication, between android and nodejs!

Woohoo!

Sunday, November 2, 2014

Initial experience with Xtend + RoboVM

Setting stuff up


I woke up feeling like doing something for Xtend developers, so I decided to check out RoboVM.

RoboVM is a project sponsored by Trillian Mobile AB, Gothenborg, Sweden.


I had so much fun contributing to the Xtendroid, I thought I could pull the same trick for the RoboVM project; the trick being writing massively intelligent boilerplate killers for common coding tasks.

I plan to use Xtend and its active annotations to cut away RoboVM boilerplate.

I set up the following things:
  • Installed java 8; (\o/ yea for lambdas)
  • Installed Xcode, installed the command-line tools (you must have a mac);
  • Installed Eclipse (version Luna, updated it);
  • Installed Xtend on eclipse via the update site;
  • Installed RoboVM on eclipse via the update site;
  • Cloned (via git) and imported (eclipse) the official RoboVM sample projects;
  • Cloned an imported the Xtend+RoboVM sample project
Also checkout these RoboVM bindings, they might be useful later.

Caveat emptor!

Beware buyer! I immediately got the feeling that the samples aren't being maintained much after the recent release; some of the method names declared in the official RoboVM samples are slightly fubar. Eclipse will complain that certain @Override declarations are not required. You will have to find the correct method and rename the borken method to that correct one. Most of the work requires matching method signatures.

If you feel generous, you can do a pull-request via github where the samples are hosted; that's what I'm planning on doing too.

The other thing that bothered me is the following error that occurs after you push the compile button, on certain sample projects:

Error occurred during initialization of VM
java/lang/NoClassDefFoundError: java/lang/ref/FinalReference

After I filtered through the noise on StackOverflow and some additional mucking around with java and eclipse.ini, it dawned on me, that I should use "compile as..." build option instead of trusting the default compilation settings.

Everything went smoothly afterwards.

Watch this space

Like I said, I plan on doing a Xtendroid on RoboVM. I think I'll call it XtendRobo, because it sounds cute.

Cheerio.

Wednesday, June 18, 2014

Full support for Xtend on Spark

Spark and Xtend

Spark (the micro web framework) accidentally started supporting Xtend lambda syntax to define Routes, since Spark started supporting java8 lambdas.

 For instance:

package spark

import static spark.Spark.before
import static spark.Spark.get
import static spark.Spark.halt

class XtendTest {
    def static void main(String[] args) {
        get("/hello/:name", [request, response |
            System.out.println("request = " + request.pathInfo());
            return "Hello " + request.params("name")
        ])
        
        val boilerplate = "is a necessary evil"
        val builtInTemplatingSystem = "woohoo, gotta love xtend, I ain't gotta escape no nothin'."
        before("/protected/*", "application/json", [request, response |
            halt(401,
            '''
            {"«boilerplate»": "«builtInTemplatingSystem»"}
            ''')
        ])
        
        get("/love/me/some/xml", "application/xml", [rq, rp | '''
        
  «boilerplate»
        
        '''])
    }
}
And the generated code:
package spark;

import org.eclipse.xtend2.lib.StringConcatenation;
import spark.Filter;
import spark.Request;
import spark.Response;
import spark.Route;
import spark.Spark;

@SuppressWarnings("all")
public class XtendTest {
  public static void main(final String[] args) {
    final Route _function = new Route() {
      public Object handle(final Request request, final Response response) {
        String _pathInfo = request.pathInfo();
        String _plus = ("request = " + _pathInfo);
        System.out.println(_plus);
        String _params = request.params("name");
        return ("Hello " + _params);
      }
    };
    Spark.get("/hello/:name", _function);
    final String boilerplate = "is a necessary evil";
    final String builtInTemplatingSystem = "woohoo, gotta love xtend, I ain\'t gotta escape no nothin\'.";
    final Filter _function_1 = new Filter() {
      public void handle(final Request request, final Response response) throws Exception {
        StringConcatenation _builder = new StringConcatenation();
        _builder.append("{\"");
        _builder.append(boilerplate, "");
        _builder.append("\": \"");
        _builder.append(builtInTemplatingSystem, "");
        _builder.append("\"}");
        _builder.newLineIfNotEmpty();
        Spark.halt(401, _builder.toString());
      }
    };
    Spark.before("/protected/*", "application/json", _function_1);
    final Route _function_2 = new Route() {
      public Object handle(final Request rq, final Response rp) {
        StringConcatenation _builder = new StringConcatenation();
        _builder.append("        ");
        _builder.append("");
        _builder.newLine();
        _builder.append(boilerplate, "");
        _builder.newLineIfNotEmpty();
        _builder.append("        ");
        _builder.append("");
        _builder.newLine();
        return _builder;
      }
    };
    Spark.get("/love/me/some/xml", "application/xml", _function_2);
  }
}

So, what do you get for it?
  1. Everything Xtend has to offer, e.g. lambdas, Active Annotations;
  2. Another native templating system, i.e. the ''' blah ''' syntax, that translates to native java, thus negating the necessity for a third party templating system.
So, how do I start playing with it?
  1. Git clone and import the project thru git into eclipse;
  2. (Optional) Setup maven, on your IDE and OS;
  3. Ensure that you have the proper Xtext/Xtend dependencies installed in eclipse, look here for instructions;
  4. Start hacking Xtend code using the Spark framework to build your API or web site, and forget about MVC... and start writing unmanageable, unbuzzworded (e.g. separation of concerns, MVC, etc.) code.

Caveat

It's not necessary to have java8 installed on your system, but some of the examples that rely on java8 features will break. Xtend/Spark with java7 works just fine.

The author (me) tested this stuff on Eclipse Juno, using the latest stable Xtend version (2.3.*) and the latest release of Spark, using apache maven 3.0.5.

Edit (24 June 2014):

A few days after discovering this. I found out about Sparkle. Sparkle is bundled with Xtend and everything else, it was a prescient refactoring of Sparky, somewhere around a year ago, it hasn't been updated for a while.

Thursday, March 27, 2014

How to make git stop ignoring your gitignore

When you find that git is ignoring the pattern of specific files in your .gitignore or .git/info/exclude, then it is very likely that the file(s) in question have already been (--force) committed by someone.

Sometimes you just want to ignore changes to your IDE, for instance eclipse project files e.g. .classpath, project.properties, .project. This is what you should do to stop git ignoring your intention to ignore changes to certain files.

  1. git update-index --assume-unchanged {filename}
  2. echo {filename} >> .git/info/exclude

Step 1. serves to make git stop ignoring your intentions with some {filename}.

Step 2. serves to make locally ignore these files in your own repository, i.e. this ignore directive will not be shared with other people.

Use .gitignore instead of .git/info/exclude in the root of your repository in Step 2. if you want to share this with everybody who has a clone of your repository. Don't forget to add and commit the .gitignore file.

Thursday, February 6, 2014

My adventures on playing and looping sounds on android, part 3

Intent

During my adventures I bumped into some definitions. I'll try to explain some of those. 
  • Sample rate
  • Bit depth
  • Channels
  • Bit rate

 

Sample rate

The number of samples required for a second of digital sound. A stream (digital payload) consists of samples. You can imagine that a sample is a unit for the movement of a membrane that vibrates the air in your surrounding area, from your sound amplification device.

 

Bit depth

Depth defines the digital sonic resolution (think: dimensional resolution for screens, but in this case digital sound) or quality and/or fidelity of a single sample.

 

Channels

Channels are the number of tracks on a stream (digital payload) so that each may have different sonic content on them, e.g. track 1 for drums and bass, track 2 for guitars and violins.

 

Bit rate

Bit rate = sample rate x bit depth x channels

For instance the bit rate of a mono channel, 16 byte bit depth, 44.1kHz sample rate, audio file is 88200. Which also means that for each second of digital sound, 88200 bytes are required to be filled with data. Or silence will ensue...

Why is this useful ? You can use this to calculate how much data is required to play a certain length of sound for these specific parameters (sample rate, depth, no. of channels).

To play a sound for 77 milliseconds, in my previous example, it will require 6834 bytes of data, i.e. 88200 x 0.077 = 6834 bytes.

The End