- Define your app id (e.g. config.xml... widget id="my.company.appname")
- Define your app version (e.g. config.xml ... version="1.0.0"...)
- Change the in-app version, automated via a hook, or manually
- Change the uri whitelist to e.g. <access uri="https://bladieblah.full.path.com/leading?to=wherever&use_a_wildcard=*" subdomains="true" />
- Build. e.g. webworks build --release -k <the password you used to do signing> -b 1
- Pray
Friday, October 30, 2015
Deploy your webworks produced bar file to Blackberry Enterprise Server, then go to the bar
Thursday, October 15, 2015
Install a bar file to your blackberry10 device in debug mode using node / webworks
How to install a bar file (e.g. blackberry application package) to your blackberry10 device:
I'm assuming you're using node and already did: npm -g install webworks, also you already have a blackberry id. To make this work you have to make a debug token (filename: bbidtoken.csk) request via the website.
To make this work you need two files: author.p12, bbidtoken.csk
Both should be copied to $HOME/.rim where webworks can find it by default on Linux;
author.p12 can be generated using bbidtoken.csk with the following commands:
Finally to install your app (assumingly made with cordova/webworks):
I'm assuming you're using node and already did: npm -g install webworks, also you already have a blackberry id. To make this work you have to make a debug token (filename: bbidtoken.csk) request via the website.
To make this work you need two files: author.p12, bbidtoken.csk
Both should be copied to $HOME/.rim where webworks can find it by default on Linux;
~/Library/Research\ In\ Motion/on a mac.
author.p12 can be generated using bbidtoken.csk with the following commands:
blackberry-keytool -genkeypair -storepass [The passphrase you used to request the debug token] -dname "CN=[Company name]" blackberry-deploy -installDebugToken bbidtoken.csk -device [ipv4 address] --password [The passphrase to access the device internals]
Finally to install your app (assumingly made with cordova/webworks):
webworks --verbose run --devicepass [The passphrase to access the device internals] --keystorepass [The passphrase you used to request the debug token]
Labels:
bar,
blackberry,
blackberry10,
cordova,
node,
webworks
Tuesday, September 8, 2015
Generate a self-signed certificate for your azure subscription
- Create a new certificate (public)
makecert -sky exchange -r -n "CN=<certificatename>" -pe -a sha1 -len 2048 -ss "<certificatename>.cer"
- Run certmgr.exe, locate
<certificatename>
, export it - Add the certificate to azure's subscription settings, locate and copy the subscription id
- Create a subscription with visual studio
- Profit!
Labels:
azure,
certificate,
export,
SSL,
subscription,
TLS,
TLS/SSL
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:
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:
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!
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.
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
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?
- Everything Xtend has to offer, e.g. lambdas, Active Annotations;
- 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?
- Git clone and import the project thru git into eclipse;
- (Optional) Setup maven, on your IDE and OS;
- Ensure that you have the proper Xtext/Xtend dependencies installed in eclipse, look here for instructions;
- 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.
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.
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.
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.
git update-index --assume-unchanged {filename}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 channelsFor 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
My adventures on playing and looping sounds on android, part 2
AudioTrack
This entry will be about to playing sounds and writing loops with AudioTrack on Android for a single channel, 44.1kHz sample rate (number of samples per second), 16-bit depth per sample (2 bytes per sample, i.e. the fidelity of a sound can be expressed in two bytes per sample), sound file. Let's call this set of parameters, for this specific sound file: S.I prepared a sample with Audacity, by exporting a wav file (microsoft's uncompressed pcm file) with these parameters S.
Feeding data
There are two ways to feed data to AudioTrack's audio buffer:- Set the data feed type to stream, i.e. feed it in increments:
private AudioTrack audioTrack; // ... InputStream is = getResources().openRawResource(R.raw.click); // res/raw/click.wav audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM); int i = 0; byte[] music = null; // feed in increments of 512 bytes try{ music = new byte[512]; audioTrack.play(); while((i = is.read(music)) != -1) { audioTrack.write(music, 0, i); Log.d(getClass().getName(), "samples: " + Arrays.toString(music)); } } catch (IOException e) { e.printStackTrace(); } - Set the data feed type to static, i.e. feed it in one go:
InputStream is = getResources().openRawResource(R.raw.click); final int WAV_FILE_BYTE_SIZE = 6878; // command line: wc -c click.wav assert WAV_FILE_BYTE_SIZE > minBufferSize; audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, WAV_FILE_BYTE_SIZE, AudioTrack.MODE_STATIC); byte[] music = new byte[WAV_FILE_BYTE_SIZE]; try { is.read(music); } catch (IOException e) { e.printStackTrace(); }finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } audioTrack.write(music, 0, music.length); audioTrack.play(); // ...
In either case, it would be wise to know the minimum buffer size, for the setting S. The minimum buffer size for a sample like this can be determined like this:
int minBufferSize = AudioTrack.getMinBufferSize(44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
Log.d(getClass().getName(), "minBufferSize: " + minBufferSize); // minBufferSize: 4096
Caveat callbacks
Please bear in mind, that AudioTrack does not have any convenient callbacks (interfaces) to tell you if a sample has been loaded correctly or when a sample has finished playing. If you're doing it wrong, then it will simply blow up in your face.Although, it has a single very versatile AudioTrack.OnPlaybackPositionUpdateListener callback interface and AudioTrack#setNotificationMarkerPosition/(1 or 2), to do stuff when AudioTrack has reached a certain marker position.
Some examples:
- mark the end of the sound file to trigger the callback, to set the head to the start then restart itself (i.e. a loop);
- mark the end of the sound file to clean up resources, e.g. stop, flush, release;
- feed a few measures of music and mark the time needed for a single beat and use the #onPeriodicNotification/1 to signify the beats, with another sound, i.e. add a metronome function;
- mark certain points in the sound file to trigger other events, e.g. start other sounds, CRUD new game characters, etc.
WAV files
WAV files always contain a header section of 44 bytes (11 frames), before you get to the actual sonic payload. You can either feed these bytes as if they were sounds or you can choose not to feed them to the sound buffer. These initial bytes will probably sound like noise. In my examples above, I did not skip over these bytes.This is one way to skip over the header:
InputStream is = getResources().openRawResource(R.raw.click);
// ...
final int WAV_FILE_BYTE_SIZE = 6878;
// ...
final int WAV_HEADER_BYTE_SIZE = 44;
byte[] music = new byte[WAV_FILE_BYTE_SIZE - WAV_HEADER_BYTE_SIZE];
try {
is.read(music, WAV_HEADER_BYTE_SIZE, WAV_FILE_BYTE_SIZE);
} catch (IOException e) {
// ...
Leak prevention
To prevent any memory leaks, do the following:- Release your AudioTrack resources:
@Override protected void onDestroy() { if (audioTrack != null) { audioTrack.flush(); audioTrack.release(); } super.onDestroy(); } - Close all your streams:
InputStream is = getResources().openRawResource(R.raw.click); // ... byte[] music = new byte[WAV_FILE_BYTE_SIZE]; try { is.read(music); } catch (IOException e) { e.printStackTrace(); }finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } // ...
Loops for fun and profit
There are two general ways to loop with AudioTrack:- For incremental feeds, i.e. using the AudioTrack.MODE_STREAM parameter, you can simply achieve a loop by writing to the buffer repeatedly with a while/for loop, while the stream is playing;
- For a static feed, i.e. one time feed, using the AudioTrack.MODE_STATIC parameter, use #setLoopPoints/3:
// ... audioTrack.write(music, 0, music.length); final int WAV_FILE_FLOORED_FRAME_SIZE = 1719; // math.floor (6878.0 / 4) == 1719 final int WAV_HEADER_FRAME_SIZE = 11; final int INFINITE_LOOP = -1; audioTrack.setLoopPoints(WAV_HEADER_FRAME_SIZE, WAV_FILE_FLOORED_FRAME_SIZE, INFINITE_LOOP); audioTrack.play(); // ...
When this starts happening, in the static case:
...:E/AndroidRuntime(3110): Caused by: java.lang.IllegalArgumentException: Invalid audio buffer size ...:E/AndroidRuntime(3110): at android.media.AudioTrack.audioBuffSizeCheck(AudioTrack.java:437)
you probably exceeded the allowed buffer size. That's it, just use your imagination.
Monday, February 3, 2014
My adventures on playing and looping sounds on android, part 1
General wisdom
If you want to do simple looping, use SoundPool and MediaPlayer, they both have a function to do this.If you want to do low-level manipulations of samples, .e.g. mucking around with byte arrays etc., adding effects, to create your own programmatic sound samples, use AudioTrack.
Use JetPlayer for midi tracks.
I'll provide some code about SoundPool and MediaPlayer to give a general idea.
AudioTrack and JetPlayer both deserve their own blog entry...
Soundpool
public class MainActivity extends Activity implements OnLoadCompleteListener {
private final static int INVALID_STREAM_ID = -1;
//...
private SoundPool soundPool;
private int streamId = INVALID_STREAM_ID;
private void setupSound() {
final int SINGLE_STREAM = 1; // you can use multiple
soundPool = new SoundPool(SINGLE_STREAM, AudioManager.STREAM_MUSIC, 0);
soundPool.setOnLoadCompleteListener(this);
// R.raw.click is located in res/raw/click.ogg
streamId = soundPool.load(this, R.raw.click, 1); // load the sonic content
}
//...
private final static int SP_PLAY_ONCE = 0;
private final static int SP_PLAY_LOOP = -1;
/**
*
* This part below actually starts playing the sound,
* otherwise you risk the chance of failing
* to play because the system hasn't
* finished loading yet
*/
@Override
public void onLoadComplete(SoundPool pool, int id, int status) {
// to loop, see SP_PLAY_LOOP and replace SP_PLAY_ONCE
pool.play(id, .5f, .5f, 1, SP_PLAY_ONCE, 1.0f);
}
@Override
protected void onDestroy() {
if (soundPool != null)
{
if (streamId != INVALID_STREAM_ID)
soundPool.unload(streamId);
soundPool.release();
}
super.onDestroy();
}
You can also use the onLoadComplete callback to do specific stuff e.g. to start looping stuff under certain conditions, set a delay before playing the sonic content, etc.
MediaPlayer
public class MainActivity extends Activity implements onCompletionListener {
private MediaPlayer mediaPlayer;
// ...
mediaPlayer = MediaPlayer.create(this, R.raw.click);
// mediaPlayer.setLooping(true);
mediaPlayer.start();
// to reuse the mediaPlayer object, with a different sound
// you have to #reset, #setDataSource #prepare
// ...
@Override
public void onCompletion(MediaPlayer mp) {
// do stuff...
}
@Override
protected void onDestroy() {
if (mediaPlayer != null)
{
mediaPlayer.reset();
mediaPlayer.release();
}
super.onDestroy();
}
Getting the media file length in milliseconds
private int getSoundFileLengthInMs(int resId)
{
MediaPlayer mp = MediaPlayer.create(this, resId);
int duration = mp.getDuration();
mp.release();
return duration;
}
Stuff I learned from trial and error
- Do not combine Animation callbacks to do your timing with your sounds if you're doing precision work, in the order of milliseconds. Do not use those callbacks with anything important. Ever. I don't know why I have to relearn that lesson...
- Looping sounds using callbacks with either MediaPlayer's OnCompletionListener or some combination of SoundPool and Handler and Runnables, will not give you enough metronome like precision.
- Do not use TimerTask, to loop and set delays. The constant allocation of objects will cost you cpu-time and memory. Use a single Handler and single Runnable, to set delays.
private MediaPlayer mediaPlayer; // initialized and prepared somewhere else //... private Handler handler = new Handler(); private Runnable runnable = new Runnable() { @Override public void run() { // do stuff beforehand... mediaPlayer.start(); } }; //... handler.postDelayed(this, delayInMs); - AudioTrack is the only viable solution if you're planning on building a dynamic metronome application, due to the high degree of control.
The end!
Mass install on android devices via BASH
How to install on all your android devices consecutively
This is the command you copy paste on your bash prompt or script:for d in $(adb devices | egrep "device$" | sed "s/[[:space:]]device$//"); do adb -s $d install -r bin/some.apk; done
Determine that adb can be accessed from the $PATH variable. That or write out the full path where the adb command is located.
PATH="$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools:$PATH"
Happy coding!
P.S. broken-ass implementations of sed like on mac os x don't acknowledge the existence of
[[:space:]]
so, use something like
\s+
or
[\t ]+
and you might have to use sed like this:
sed -e ...
Friday, June 1, 2012
Yet another XMPP Client for Android
First of all, git it from github: https://github.com/Buggaboo/android_xmpp_client



The features
- GreenDao, database access. Say goodbye to e.g. SQL injection exploits, crap manual data type conversions;
- Smack library (xmpp), modified for Android, with bugs, but not crashworthy;
- It vibrates messages to morse code; (3 june 2012: WIP)
- The messages can be translatable to different languages, just by leveraging the xml resources;
- Multiple provider support, i.e. connect with google, microsoft, meebo, whatever you want;
- Licence: GPLv3;
- Support for android api levels 10 thru 15 (from gingerbread to ice cream sandwich due to compatibility library, 80% of the android market);
- Support for android api level 15 (pure ice cream sandwich, less than 10%);
- Support for fragments (12 june 2012: WIP);
- Support for android Notifications;



The general design
- Sharing data between Contexts via the database: A context alpha (e.g. Activity or Service) pokes another context beta with an Intent with a Bundle payload containing the record id of a certain database table.
- To prevent competition for the same database resource, certain services take randomized naps, aka Thread.sleep(Long);
- A message entity has a buddy entity has a connection entity, i.e. I use foreign keys, to sort and group data etc., GreenDao generates all the code you need;
- BroadcastReceivers and ArrayAdapters work together to refresh your ListViews.
Known Issues
- There are no bounds on how much data is pulled from the database and rendered as a view, the ListViews are potential memory hogs;
- There are no arbitrary limits on data input, which could eat all your memory;
- I have not stress-tested how many connections can be kept alive at the same time, before thread-related issues arise;
- I suspect that the smack library has its own issues with regard to Presence;
- I have not checked for memory leakages, I use nested classes for my BroadcastReceivers, I haven't checked for cyclical references, I don't understand fully how garbage collection on android works;
- The vibrator notification can get annoying, or fun, depending on your mood.
Tuesday, December 13, 2011
XSS techniques: defeat a target that only escapes single and double quotes
I assume that you found an entry point either, from
Try to break the webpage with '-->', e.g. html comment termination,
inject your payload, e.g. <script>...</script>
Escaping double and single quotes:
a.
b.
c. replace (for compression)
Use this python snippet to prepare the payload:
The drawback of this technique is that the decimal payload will be huge and it might overflow the input, i.e. url input on the browser, input-tag, form etc.
- the url
- an injectable
<input .../>
- or a form input, find functions on certain websites are very exploitable
Try to break the webpage with '-->', e.g. html comment termination,
inject your payload, e.g. <script>...</script>
Escaping double and single quotes:
a.
(new String(1)).replace((new Number(1)).toString(10), /look no single or double quotes/);
b.
String.fromCharCode(n1, n2, ..., nX)
c. replace (for compression)
Use this python snippet to prepare the payload:
[ ord(c) for c in "http://payload_in_decimal" ]
The drawback of this technique is that the decimal payload will be huge and it might overflow the input, i.e. url input on the browser, input-tag, form etc.
Friday, July 22, 2011
Song lyrics memorization using method of loci
Sometimes when studying to play a song on guitar or bass it's difficult enough to memorize chord changes, let alone singing along. This becomes more difficult if there are any syncopations or some rhythmic off-beat device in the song. In some songs some words in the whole chorus are different each time in a different bar, but you just can't manage to memorize which words belong to which repetition of the chorus. I propose a remedy for this problem.
First the muscle memory must already be familiar with the chord progressions, if you're compin' along to the melodies, the chords could be anchored to the lyrics and melody of the song.
Use the mnemonic device called the method of loci. The advantage of this method is that you can jump between from verse and chorus by just stepping into the room you've associated the verse or chorus with (in your mind).
Use real objects in the room, that are usually there, (e.g. tv, couch, rug in the living room, and toilet seat, shower in the bathroom) to anchor an initial strand of a story. The story is just a sequential translation of the lyrics into memorable narrative. The more outrageous, the more memorable.
If you speak multiple languages use translations of words and the phonetic information to link words together.
Manipulate the object translation of words in the lyrics in the space e.g. explosions, actions etc. Use a phonetic approximation of the word if it isn't an easily translatable object. It's important to anchor to existing objects in the space, e.g. tv, couch, toilet, showerhead, cupboard, dining table etc. One could also use synonyms but this would tend to require some thought (introduce a new layer of translation), which would take extra time.
If you speak multiple languages use translations of words and the phonetic information to link words together.
It's key to reduce the recall-time, to stay in the rhythm of the song, even before you actually need the information.
I discovered a trick to optimize on recall time, by grouping triggers together for the next word which fall on the start of the musical phrase, before you actually need the trigger. For example, you need to recall B in the following melodic phrase, you need A in the current melodic phrase, so you chunk mnemonic triggers for AB together, before you actually need B. You could also memorize a meta-trigger for B, instead of the real trigger for B.
It's important to walk through (in the mind) the rooms, during practice, as if you're walking through different parts of the song, so the sequence of the verse, bridge, chorus is easy to traverse. I use my friends homes to memorize songs.
For instance a pop song of 2 minutes, there would be at most 3 distinct lyrical parts e.g. verse, chorus, bridge. If certain parts occur together like two verses followed by a chorus, this could be chunked together in one room, then the rest could be chunked together in the following room; a song could theoretically require two rooms. Two songs could theoretically could fit into a locus of 5 rooms, mnemonically speaking.
You can also try to engage your limbic brain in memorizing the lyrics, by imagining the sensations produced by the lyrics. You can imagine feeling a warmth on your cheeks, when you sing the word "Hot" etc.
It's also good to use multiple non-conflicting triggers (e.g. sensations, images, narrative, onomotopeia, synonyms), in your story to encode the lyrics, eventually the strongest trigger will remain.
It's fairly obvious that one should also practice recalling the triggers.
First the muscle memory must already be familiar with the chord progressions, if you're compin' along to the melodies, the chords could be anchored to the lyrics and melody of the song.
Use the mnemonic device called the method of loci. The advantage of this method is that you can jump between from verse and chorus by just stepping into the room you've associated the verse or chorus with (in your mind).
Use real objects in the room, that are usually there, (e.g. tv, couch, rug in the living room, and toilet seat, shower in the bathroom) to anchor an initial strand of a story. The story is just a sequential translation of the lyrics into memorable narrative. The more outrageous, the more memorable.
If you speak multiple languages use translations of words and the phonetic information to link words together.
Manipulate the object translation of words in the lyrics in the space e.g. explosions, actions etc. Use a phonetic approximation of the word if it isn't an easily translatable object. It's important to anchor to existing objects in the space, e.g. tv, couch, toilet, showerhead, cupboard, dining table etc. One could also use synonyms but this would tend to require some thought (introduce a new layer of translation), which would take extra time.
If you speak multiple languages use translations of words and the phonetic information to link words together.
It's key to reduce the recall-time, to stay in the rhythm of the song, even before you actually need the information.
I discovered a trick to optimize on recall time, by grouping triggers together for the next word which fall on the start of the musical phrase, before you actually need the trigger. For example, you need to recall B in the following melodic phrase, you need A in the current melodic phrase, so you chunk mnemonic triggers for AB together, before you actually need B. You could also memorize a meta-trigger for B, instead of the real trigger for B.
It's important to walk through (in the mind) the rooms, during practice, as if you're walking through different parts of the song, so the sequence of the verse, bridge, chorus is easy to traverse. I use my friends homes to memorize songs.
For instance a pop song of 2 minutes, there would be at most 3 distinct lyrical parts e.g. verse, chorus, bridge. If certain parts occur together like two verses followed by a chorus, this could be chunked together in one room, then the rest could be chunked together in the following room; a song could theoretically require two rooms. Two songs could theoretically could fit into a locus of 5 rooms, mnemonically speaking.
You can also try to engage your limbic brain in memorizing the lyrics, by imagining the sensations produced by the lyrics. You can imagine feeling a warmth on your cheeks, when you sing the word "Hot" etc.
It's also good to use multiple non-conflicting triggers (e.g. sensations, images, narrative, onomotopeia, synonyms), in your story to encode the lyrics, eventually the strongest trigger will remain.
It's fairly obvious that one should also practice recalling the triggers.
Labels:
memorization,
method of loci,
mnemonic,
songlyrics
Monday, March 14, 2011
IT worker with a mind like water
Introduction
In this entry, I'll be proselytizing about my interpretation of Getting Things Done (GTD) by David Allen, mindfulness and my implementation of Agile principles.
All of this culminates in a project portfolio, for a high-level view of the project status.
GTD principles and mindfulness
In order to work at maximum efficiency in bursts during the day, one must maintain a mind which flows like water. IT-workers, like physical athletes, chess champions etc. must keep their cool and maintain a certain level-headedness to perform at the top of their game. An IT-worker can get to this state by practicing mindfulness excercises during down-time and implement GTD in their personal and professional lives.
Why GTD? Because it is a means to cast away projects and tasks and entrust them to a externalized system, so there would be no need to retain excess information in the mind. So your mind is free to react to or observe the situation. I'll write up a blog entry to illustrate some points made by cognitive studies which support the beneficial effects of the GTD system.
Why mindfulness? Because it's the new fad. No, not really, meditation has been with us for a long time, but meditation is only a means to an end.
Mindfulness can potentially relieve (not a 100% cure) certain physical manifestations of mental blockages (I'm not a dualist in the cartesian tradition). Like all other things in life, you need a time and a place to do this and practice. So that's taking care of the body/mind. Regular physical conditioning/exercise is also a good idea. I won't cite the hundreds of research papers which confirm the relation between being mentally fit and physical exercise.
A common goal mindfulness and GTD is to empty the mind of all baggage and to get in a relaxed control of the task at hand, with minimum interference from other senses. Even if you think it's all weird esoteric unscientific crap, there's always a possibility of a positive placebo effect on your mind. So try it.
David Allen also stresses the importance of setting positive goals. This creates a positive feedback loop, when things actually don't turn out like the worst-case scenario you initially envisioned.
Teams and Agile and GTD
I could imagine that the other team members might not fully appreciate your fascination with GTD or mindfulness. So lead by example.
So, how does one share a mind-like-water epiphenomenal state with your colleagues? Grab adhesive pieces of paper (e.g. stick-it), get a large sheet of paper or a whiteboard, start writing down all of the project details as a group. Group together similar tasks / details. Find a comfortable granularity i.e. level of description for the tasks for the whole team. Not too abstract and not too detailed. Unload your team's collective mind. This is a free-flowing brainstorm / brain unload state. The unloading state can be done over a week or in 5 minutes. Depending on the size of the project. I personally did a drive-by braindump with my team once.
Get together with your team. Your role is to provide the constraints of the project. Per task, sort the precedence of certain tasks depending on the priority of the task. This is a filtering state. Make a plan in iterations for the coming x weeks. Every iteration should be no longer than 2 weeks. For every task, subproject, try to make a informed guess how long that task would take to accomplish. Also try to define the priority of that feature with the client and your teammates. It's important to make a clear seperation between the "unloading" state and the filtering / analytical / censor state.
If management insists on disrupting you or team members to do multi-project multi-tasking, use GTD on a lower-level for each disruptable team member. Use your project portfolio and project backlog to defend your team member, against unwelcome intrusions like these, for example make your point clear to "intruders" that your project has no time to spare etc. In any case a project portfolio is a common base you can use to negotiate, within the team or with upper-management.
Another method to maintain a team's commitment during a barrage of incidental crap, use a kanban to keep the focus on the project at hand. Also, use commitment and consistency. Let the person(s) who is or are going to be responsible for the task write down her name on the piece of paper.
For software developers you might want to describe the following states on the kanban (per feature) for an iteration:
Depending on the size of the team, do standups. Do project backlogs, so you can make a project portfolio, do a velocity charts. But in any case never plan alone, always use the data provided by the whole team.
My software idea
I envision a drag and drop interface to create an online kanban system, where states can be defined. Using xmpp and bosh to give project members updates in changes within the kanban system. Integration with XMPP-based chat systems. All of this integrated with a calendar (gcalendar?) and a GTD based system where tasks can be delegated to people and be inserted to the wait list or the calendar. Ad hoc commands are in the protocol to deliver the data payload.
Conclusion
There is a common thread between agile and GTD. If you include team members and let them actively participate, you can leverage the group's wisdom to improve commitment to the project and also improve the way it is going to be developed. This is a way for your team to get into the zone.
In this entry, I'll be proselytizing about my interpretation of Getting Things Done (GTD) by David Allen, mindfulness and my implementation of Agile principles.
All of this culminates in a project portfolio, for a high-level view of the project status.
![]() |
| Quick reference to GTD |
GTD principles and mindfulness
In order to work at maximum efficiency in bursts during the day, one must maintain a mind which flows like water. IT-workers, like physical athletes, chess champions etc. must keep their cool and maintain a certain level-headedness to perform at the top of their game. An IT-worker can get to this state by practicing mindfulness excercises during down-time and implement GTD in their personal and professional lives.
Why GTD? Because it is a means to cast away projects and tasks and entrust them to a externalized system, so there would be no need to retain excess information in the mind. So your mind is free to react to or observe the situation. I'll write up a blog entry to illustrate some points made by cognitive studies which support the beneficial effects of the GTD system.
Why mindfulness? Because it's the new fad. No, not really, meditation has been with us for a long time, but meditation is only a means to an end.
Mindfulness can potentially relieve (not a 100% cure) certain physical manifestations of mental blockages (I'm not a dualist in the cartesian tradition). Like all other things in life, you need a time and a place to do this and practice. So that's taking care of the body/mind. Regular physical conditioning/exercise is also a good idea. I won't cite the hundreds of research papers which confirm the relation between being mentally fit and physical exercise.
![]() |
| Meditating Lotus |
A common goal mindfulness and GTD is to empty the mind of all baggage and to get in a relaxed control of the task at hand, with minimum interference from other senses. Even if you think it's all weird esoteric unscientific crap, there's always a possibility of a positive placebo effect on your mind. So try it.
David Allen also stresses the importance of setting positive goals. This creates a positive feedback loop, when things actually don't turn out like the worst-case scenario you initially envisioned.
Teams and Agile and GTD
I could imagine that the other team members might not fully appreciate your fascination with GTD or mindfulness. So lead by example.
So, how does one share a mind-like-water epiphenomenal state with your colleagues? Grab adhesive pieces of paper (e.g. stick-it), get a large sheet of paper or a whiteboard, start writing down all of the project details as a group. Group together similar tasks / details. Find a comfortable granularity i.e. level of description for the tasks for the whole team. Not too abstract and not too detailed. Unload your team's collective mind. This is a free-flowing brainstorm / brain unload state. The unloading state can be done over a week or in 5 minutes. Depending on the size of the project. I personally did a drive-by braindump with my team once.
![]() |
| Braindump / fun with stick-its |
![]() |
| The whiteboard |
Get together with your team. Your role is to provide the constraints of the project. Per task, sort the precedence of certain tasks depending on the priority of the task. This is a filtering state. Make a plan in iterations for the coming x weeks. Every iteration should be no longer than 2 weeks. For every task, subproject, try to make a informed guess how long that task would take to accomplish. Also try to define the priority of that feature with the client and your teammates. It's important to make a clear seperation between the "unloading" state and the filtering / analytical / censor state.
If management insists on disrupting you or team members to do multi-project multi-tasking, use GTD on a lower-level for each disruptable team member. Use your project portfolio and project backlog to defend your team member, against unwelcome intrusions like these, for example make your point clear to "intruders" that your project has no time to spare etc. In any case a project portfolio is a common base you can use to negotiate, within the team or with upper-management.
![]() |
| Spreadsheet based project portfolio, left: monthly plan, right: weekly plan. |
Another method to maintain a team's commitment during a barrage of incidental crap, use a kanban to keep the focus on the project at hand. Also, use commitment and consistency. Let the person(s) who is or are going to be responsible for the task write down her name on the piece of paper.
![]() |
| Simple KanBan: wait, active, finished. |
For software developers you might want to describe the following states on the kanban (per feature) for an iteration:
- Develop
- Test
- Refactor
- Merge
- Commit to version control
- Integration Test
- Deploy
Depending on the size of the team, do standups. Do project backlogs, so you can make a project portfolio, do a velocity charts. But in any case never plan alone, always use the data provided by the whole team.
My software idea
I envision a drag and drop interface to create an online kanban system, where states can be defined. Using xmpp and bosh to give project members updates in changes within the kanban system. Integration with XMPP-based chat systems. All of this integrated with a calendar (gcalendar?) and a GTD based system where tasks can be delegated to people and be inserted to the wait list or the calendar. Ad hoc commands are in the protocol to deliver the data payload.
Conclusion
There is a common thread between agile and GTD. If you include team members and let them actively participate, you can leverage the group's wisdom to improve commitment to the project and also improve the way it is going to be developed. This is a way for your team to get into the zone.
Wednesday, December 15, 2010
Wat ik geleerd heb van het kopen van een pak
Introductie
Blijkbaar is het een ongeschreven regel dat men voor een solicitatiegesprek voor een management of leidinggevende positie in het algemeen, met een pak moet aankomen. Ik ga ervanuit dat de lezer, net zoals ik, graag herenpakken wil (gaan) dragen, dus ik schrijf deze blogpost niet vanuit het perspectief van de vrouw. Maar sommige principes die ik beschrijf zijn ook wel van toepassing op vrouwenpakken, denk ik.
Gij zult een corporate kostuum dragen voor een belangrijk gesprek. Ongeacht of die mooie trui waarmee jij wil verschijnen en een goede indruk wil wekken honderden euro's gekost heeft. Ongeacht of dat speciaal shirtje van je, je eerder geluk heeft mogen brengen, waardoor jij dat shirt al in jaren niet meer hebt gewassen... doe gewoon een pak aan. Zoals dat sentiment mooi verwoord wordt in de tv-serie, HIMYM (How I met your mother):
Basisstappen
Nee? Nog nooit een pak gekocht? Geen ramp. Let op de volgende zaken:
Het beïnvloeden van je perceptie
Een competente verkoper zal je op vriendelijk en toeschietelijk wijze benaderen, die zal lachen om jouw grapjes (stel dat je ze maakt). Je zult die persoon wellicht mogen. Wanneer een potentiële koper een verkoper mag, dan wordt er een weg gebaand voor wederkerigheid. Kortom, de verkoper is aardig tegen me, dus ik zal als koper-zijnde zal je belonen d.m.v. de aankoop op deze pak en talloze dure acessoires. Mensen zijn eerder geneigd om zich te associeren met mensen die zij uit een positieve ervaring kennen, waardoor een koper eerder geneigd om dezelfde aankoop op dezelfde plaats te doen.
Let op de invloed van perceptuele contrast, d.w.z., wanneer je veel dure dingen om je heen hebt, dan zullen andere dure kleine artikelen (relatief t.o.v. andere winkels) alleen normaal geprijsd lijken, bijv. je wordt omringd door pakken van duizenden euro's, (die je uiteraard, niet allemaal moet gaan kopen) dan lijkt een paar sokken van 25 euro normaal. Terwijl je misschien bij de hema voor dat bedrag 50 van dezelfde paar sokken kan kopen, als het ware. Kortom, besteed geen geld aan de acessoires die relatief normaal afgeprijsd lijken. Koop die horloge, overhemd, dassen, schoenen, sokken, manchetknopen elders als je geld wilt besparen. In dit geval is het contrast normaliserend.
Perceptuele contrast geldt ook voor hebbedingetjes die in de aanbieding zijn, let op de prijzen van alle artikelen in de winkel. Is alles boven 500 euro en hoger? Is die paar sokken afgeprijsd van 75 naar 25 euro? Voor paar sokken... wauw, dat lijkt goedkoop. Hier is het contrast versterkend.
Het is verstandig om te bepalen welke winkels goedkoop zijn en welke duur zijn. De aanname, dat goedkoop is duurkoop of dat duur impliceert goede kwaliteit, gaat niet atijd op, wees daar bewust van. Het gaat om de perceptie van de mensen die de pak waarnemen. Als je zegt dat iets duur is, (zonder dat dit werkelijk duizenden euro's gekost heeft), als men die perceptie al hebben, dan is dat ook zo in hun verbeelding. De reden waarom grote bedrijven die pakken verkopen, mega-winst kunnen maken is omdat zij het hele productieproces uitbesteden aan lage-lonen landen. De werkelijke waarde is een optelsom van de materiaalkosten plus productieloonkosten plus vervoerkosten plus verkoperskosten, denk aan provisie voor elk pak voor de verkoper en zijn uurloon. Ik heb geen concrete cijfers gezien, maar ik heb zo'n flauw vermoeden.
Stel dat de pak die je wilt nog enigzins bijgesneden moet worden of op één of een andere manier bewerkt moet worden en je hebt nog niet definitief besloten dat je de pak wil aanschaffen. Een effectieve verkoper zal jou proberen te beïnvloeden, d.m.v. de schaarsheid principe. Bijvoorbeeld, stel dat je heel snel binnenkort een pak nodig hebt, dit heb je per ongeluk verteld aan de verkoper. De verkoper zal je aan herinneren dat jouw pak (ongeacht welke pak dat moge zijn) wel 4 à 6 weken zou gaan duren om te maken, om je ook indirect te herinneren aan gemiste mogelijke kansen in het verschiet. Het effect van deze herinnering is dat je een enorme aandrang zult voelen om die betreffende pak meteen aan te schaffen. Mensen raken in het algemeen sneller in paniek wanneer zij geloven dat zij dingen zullen mislopen in de toekomst, waardoor zij de helderheid verliezen om verstandige besluiten te nemen.
Afgezien van de schaarste in de tijd, kunnen verkopers producten ook schaars laten lijken. Denk aan zeldzaam geziene pakken die gemaakt zijn door een of een andere belangrijke ontwerper die niet zoveel pakken maakt.
Een wat oudere (uitziende) verkoper, of een verkoper die meent dat hij al langer in het vak zit, zal mogelijk erop aandringen dat je zijn advies moet nemen en vele autoriteitsargumenten geven, zoals: "Uit ervaring heb ik geleerd dat bladibladibla.". Je brein vertelt je dat deze persoon is een autoriteit, je brein zegt: "...dus ik moet wel zijn advies volgen, anders is dat ten nadele van mij, die niet zoveel weet hierover...".
Een goede verkoper zal veel voorstellen doen wat betreft acessoires, opties, combinaties etc. De verkoper zal je veel dingen laten aanraken. Zij weten echter dat wanneer verkoopartikelen eenmaal aangeraakt worden door een potentiële koper, dan zal dat artikel met een grotere kans gekocht worden door de (hand)tastelijke koper. Ik vermoed dat dit te maken heeft met de commitment en consistentie principes. Wanneer de commitment voor het kopen van een artikel reeds vaag aanwezig is, zal de commitment hieraan versterkt worden door een positieve tastzintuigelijke waarneming, waardoor het consistentie gedeelte van de beïnvloeding zal zegevieren over de rede, (heb ik deze prullaria wel nodig?), kortom, je brein zegt: "oe leuk, koop die hap!".
Vermijd cognitieve dissonanties, geen vloekende kleuren (bijv. laat iemand die niet kleurenblind is je ensemble'tje nakijken). Sluit belachelijke contrasten uit, bijv. hele donkere sokken bij een witte broek, behalve als je moet moonwalken als Michael Jackson. De waarnemer van je pak, bij degene waar de coginitieve dissonantie ontstaat, zal bewust of onbewust een oordeel vormen over jouw hele persoon op basis van deze schijnlijke bedrieglijke onbelangrijke "foutje". Wellicht is de perceptie van de waarnemer van jou in één woord samen te vatten: slordig.
Wat ik nog niet genoemd heb is social proof en conformity, vrij vertaald, sociale bewijsvoering en conformiteit, dit is wanneer een groep verkopers menen dat een bepaald voorwerp je mooi staat, bijv. een duur acessoire bij je dure pak, terwijl jij dat ding zelf bij voorbaat afschuwelijk vindt. Er ontstaat een grote aandrang om te conformeren aan de verwachting van die groep, ik kan me voorstellen dat de volgende gedachtes door je hoofd gaat: "Er zijn zoveel mensen die hetzelfde denken, ik zal wel gek zijn. Ik zal het maar moeten kopen."
Deze psychologische beïnvloedingstactieken zoals liking (iemand mogen, vriendelijk zijn), autoriteit, perceptuele contrast, schaarsheid, wederkerigheid, commitment en consistentie, sociale bewijsvoering en conformiteit zijn ook van toepassing op andere branches. Denk aan een mooie auto die bij je pak past in de autoverkoopbranche. Dat artikel schrijf ik later wel als ik zelf hoger ben opgeklommen en een auto nodig heb.
Onderhandeling
Een beetje ervaren verkoper zal je gelijk een derde oor proberen aan te naaien, maar trap er niet in! Ga in discussie, neem vooraf onderzoek naar prijzen van pakken en gebruik deze feiten die je oppikt tijdens de onderhandeling over de prijs. Maak aantekeningen als je geen goed geheugen hebt. Neem desnoods foto's, maar vraag eerst om de toestemming van de zaak.
Val de verkoper aan op prijs, gebruik wat je weet over de objectieve gemiddelde prijs, maar wees geduldig en beleefd voor de andere onderhandelende partij.
Bijvoorbeeld, zeg dat je twee dassen wil met die pak, all-in. Want dat scheelt jullie twee de moeite. Het scheelt de verkoper de moeite om een nieuwe sukkel te vinden. Voor jouw scheelt het de moeite om die dassen elders vinden. Probeer anders af te dingen, je zegt bijv. "okee, één das dan...". Probeer wederzijdse concessies te maken.
Stel dat je onderhandeling mislukt, je zult die das niet zomaar krijgen met die pak, all-in, want blijkbaar is de prijs echte heel scherp (o, echt waar?), we hebben nog altijd het internet. Bovendien, er is slechts één maat voor alle dassen. Tijdens de onderhandeling, probeer te benadrukken dat jij onderhandelt vanuit het algemene belang, dat je uitgaat van een win-win situatie. Zeg dat je binnenkort (half jaar?) ook voor andere festiviteiten een pak nodig hebt, wat verdomd veel lijkt op een lange-termijn relatie lijkt tussen jou en verkoper.
Conclusie
Een pak kopen vereist voorbereiding. Om te voorkomen dat je te veel betaalt voor iets moet je bewust omgaan met bepaalde beïnvloedingen om je heen.
Links & Bronnen
Blijkbaar is het een ongeschreven regel dat men voor een solicitatiegesprek voor een management of leidinggevende positie in het algemeen, met een pak moet aankomen. Ik ga ervanuit dat de lezer, net zoals ik, graag herenpakken wil (gaan) dragen, dus ik schrijf deze blogpost niet vanuit het perspectief van de vrouw. Maar sommige principes die ik beschrijf zijn ook wel van toepassing op vrouwenpakken, denk ik.
Gij zult een corporate kostuum dragen voor een belangrijk gesprek. Ongeacht of die mooie trui waarmee jij wil verschijnen en een goede indruk wil wekken honderden euro's gekost heeft. Ongeacht of dat speciaal shirtje van je, je eerder geluk heeft mogen brengen, waardoor jij dat shirt al in jaren niet meer hebt gewassen... doe gewoon een pak aan. Zoals dat sentiment mooi verwoord wordt in de tv-serie, HIMYM (How I met your mother):
![]() | |||||
Nee? Nog nooit een pak gekocht? Geen ramp. Let op de volgende zaken:
- Bepaal ten eerste wat je maximaal wil gaan betalen, kortom bepaal je budget, als de euro geen zware inflatie ondergaat, dan zal 450 euro voldoen, incl. schoenen, overhemd en das);
- Kijke, kijke, niet kope, zoek een aantal winkels op in de grote stad, wellicht ook in de buurt van jouw omgeving;
- Bepaal bij de eerste zaak die je bezoek welke maat je hebt, door dat aan iemand te vragen, dit scheelt tijd namelijk, voor je volgende bezoeken;
- Vraag om hulp, wees niet te trots om hulp te vragen, wees assertief, maar niet onbeschoft, jij bent de klant en de klant is koning, maar vraag expliciet aan de verkoper of hij zijn professionele advies wil geven, wanneer je merkt dat er te vaak ja wordt geknikt;
- Bekijk verschillende pakken, let op bepaalde aspecten wat je wel of niet leuk vindt;
- Vraag de hulpgevende winkelbediende (of hoe dat tegenwoordig heet), hoe lang verkoper werkzaam is in de kostuumbranche (herenmode branch);
- Toets de kennis van de verkoper, bijv. vraag wat voor effect horizontale, diagonale, verticale lijnen heeft op de drager van een pak:
- Horizontaal maakt dik (als je slankt bent);
- Verticaal maakt lang;
- Diagonaal voor het versterken van het contrast t.o.v. de reeds aanwezige lijnen. Je ziet doorgaands nooit pakken met diagonale strepen, dit wekt de indruk (vermoedelijk) dat je wankel bent, en scheef staat.
- Als je een zaak binnenloopt, bepaal alvorens voor jezelf met welk doel je die pak gaat aantrekken, bij voorbeeld een blauw pak met verticale strepen, dus je lijkt langer en autoritair, in ieder geval, met die pak straal je zelfvertrouwen uit, vertel de verkoper welk doel jij beoogt;
Het beïnvloeden van je perceptie
![]() |
| Manchetknopen |
Een competente verkoper zal je op vriendelijk en toeschietelijk wijze benaderen, die zal lachen om jouw grapjes (stel dat je ze maakt). Je zult die persoon wellicht mogen. Wanneer een potentiële koper een verkoper mag, dan wordt er een weg gebaand voor wederkerigheid. Kortom, de verkoper is aardig tegen me, dus ik zal als koper-zijnde zal je belonen d.m.v. de aankoop op deze pak en talloze dure acessoires. Mensen zijn eerder geneigd om zich te associeren met mensen die zij uit een positieve ervaring kennen, waardoor een koper eerder geneigd om dezelfde aankoop op dezelfde plaats te doen.
Let op de invloed van perceptuele contrast, d.w.z., wanneer je veel dure dingen om je heen hebt, dan zullen andere dure kleine artikelen (relatief t.o.v. andere winkels) alleen normaal geprijsd lijken, bijv. je wordt omringd door pakken van duizenden euro's, (die je uiteraard, niet allemaal moet gaan kopen) dan lijkt een paar sokken van 25 euro normaal. Terwijl je misschien bij de hema voor dat bedrag 50 van dezelfde paar sokken kan kopen, als het ware. Kortom, besteed geen geld aan de acessoires die relatief normaal afgeprijsd lijken. Koop die horloge, overhemd, dassen, schoenen, sokken, manchetknopen elders als je geld wilt besparen. In dit geval is het contrast normaliserend.
Perceptuele contrast geldt ook voor hebbedingetjes die in de aanbieding zijn, let op de prijzen van alle artikelen in de winkel. Is alles boven 500 euro en hoger? Is die paar sokken afgeprijsd van 75 naar 25 euro? Voor paar sokken... wauw, dat lijkt goedkoop. Hier is het contrast versterkend.
Het is verstandig om te bepalen welke winkels goedkoop zijn en welke duur zijn. De aanname, dat goedkoop is duurkoop of dat duur impliceert goede kwaliteit, gaat niet atijd op, wees daar bewust van. Het gaat om de perceptie van de mensen die de pak waarnemen. Als je zegt dat iets duur is, (zonder dat dit werkelijk duizenden euro's gekost heeft), als men die perceptie al hebben, dan is dat ook zo in hun verbeelding. De reden waarom grote bedrijven die pakken verkopen, mega-winst kunnen maken is omdat zij het hele productieproces uitbesteden aan lage-lonen landen. De werkelijke waarde is een optelsom van de materiaalkosten plus productieloonkosten plus vervoerkosten plus verkoperskosten, denk aan provisie voor elk pak voor de verkoper en zijn uurloon. Ik heb geen concrete cijfers gezien, maar ik heb zo'n flauw vermoeden.
Stel dat de pak die je wilt nog enigzins bijgesneden moet worden of op één of een andere manier bewerkt moet worden en je hebt nog niet definitief besloten dat je de pak wil aanschaffen. Een effectieve verkoper zal jou proberen te beïnvloeden, d.m.v. de schaarsheid principe. Bijvoorbeeld, stel dat je heel snel binnenkort een pak nodig hebt, dit heb je per ongeluk verteld aan de verkoper. De verkoper zal je aan herinneren dat jouw pak (ongeacht welke pak dat moge zijn) wel 4 à 6 weken zou gaan duren om te maken, om je ook indirect te herinneren aan gemiste mogelijke kansen in het verschiet. Het effect van deze herinnering is dat je een enorme aandrang zult voelen om die betreffende pak meteen aan te schaffen. Mensen raken in het algemeen sneller in paniek wanneer zij geloven dat zij dingen zullen mislopen in de toekomst, waardoor zij de helderheid verliezen om verstandige besluiten te nemen.
Afgezien van de schaarste in de tijd, kunnen verkopers producten ook schaars laten lijken. Denk aan zeldzaam geziene pakken die gemaakt zijn door een of een andere belangrijke ontwerper die niet zoveel pakken maakt.
Een wat oudere (uitziende) verkoper, of een verkoper die meent dat hij al langer in het vak zit, zal mogelijk erop aandringen dat je zijn advies moet nemen en vele autoriteitsargumenten geven, zoals: "Uit ervaring heb ik geleerd dat bladibladibla.". Je brein vertelt je dat deze persoon is een autoriteit, je brein zegt: "...dus ik moet wel zijn advies volgen, anders is dat ten nadele van mij, die niet zoveel weet hierover...".
Een goede verkoper zal veel voorstellen doen wat betreft acessoires, opties, combinaties etc. De verkoper zal je veel dingen laten aanraken. Zij weten echter dat wanneer verkoopartikelen eenmaal aangeraakt worden door een potentiële koper, dan zal dat artikel met een grotere kans gekocht worden door de (hand)tastelijke koper. Ik vermoed dat dit te maken heeft met de commitment en consistentie principes. Wanneer de commitment voor het kopen van een artikel reeds vaag aanwezig is, zal de commitment hieraan versterkt worden door een positieve tastzintuigelijke waarneming, waardoor het consistentie gedeelte van de beïnvloeding zal zegevieren over de rede, (heb ik deze prullaria wel nodig?), kortom, je brein zegt: "oe leuk, koop die hap!".
![]() |
| Contrast |
Vermijd cognitieve dissonanties, geen vloekende kleuren (bijv. laat iemand die niet kleurenblind is je ensemble'tje nakijken). Sluit belachelijke contrasten uit, bijv. hele donkere sokken bij een witte broek, behalve als je moet moonwalken als Michael Jackson. De waarnemer van je pak, bij degene waar de coginitieve dissonantie ontstaat, zal bewust of onbewust een oordeel vormen over jouw hele persoon op basis van deze schijnlijke bedrieglijke onbelangrijke "foutje". Wellicht is de perceptie van de waarnemer van jou in één woord samen te vatten: slordig.
Wat ik nog niet genoemd heb is social proof en conformity, vrij vertaald, sociale bewijsvoering en conformiteit, dit is wanneer een groep verkopers menen dat een bepaald voorwerp je mooi staat, bijv. een duur acessoire bij je dure pak, terwijl jij dat ding zelf bij voorbaat afschuwelijk vindt. Er ontstaat een grote aandrang om te conformeren aan de verwachting van die groep, ik kan me voorstellen dat de volgende gedachtes door je hoofd gaat: "Er zijn zoveel mensen die hetzelfde denken, ik zal wel gek zijn. Ik zal het maar moeten kopen."
Deze psychologische beïnvloedingstactieken zoals liking (iemand mogen, vriendelijk zijn), autoriteit, perceptuele contrast, schaarsheid, wederkerigheid, commitment en consistentie, sociale bewijsvoering en conformiteit zijn ook van toepassing op andere branches. Denk aan een mooie auto die bij je pak past in de autoverkoopbranche. Dat artikel schrijf ik later wel als ik zelf hoger ben opgeklommen en een auto nodig heb.
Onderhandeling
Een beetje ervaren verkoper zal je gelijk een derde oor proberen aan te naaien, maar trap er niet in! Ga in discussie, neem vooraf onderzoek naar prijzen van pakken en gebruik deze feiten die je oppikt tijdens de onderhandeling over de prijs. Maak aantekeningen als je geen goed geheugen hebt. Neem desnoods foto's, maar vraag eerst om de toestemming van de zaak.
Val de verkoper aan op prijs, gebruik wat je weet over de objectieve gemiddelde prijs, maar wees geduldig en beleefd voor de andere onderhandelende partij.
Bijvoorbeeld, zeg dat je twee dassen wil met die pak, all-in. Want dat scheelt jullie twee de moeite. Het scheelt de verkoper de moeite om een nieuwe sukkel te vinden. Voor jouw scheelt het de moeite om die dassen elders vinden. Probeer anders af te dingen, je zegt bijv. "okee, één das dan...". Probeer wederzijdse concessies te maken.
Stel dat je onderhandeling mislukt, je zult die das niet zomaar krijgen met die pak, all-in, want blijkbaar is de prijs echte heel scherp (o, echt waar?), we hebben nog altijd het internet. Bovendien, er is slechts één maat voor alle dassen. Tijdens de onderhandeling, probeer te benadrukken dat jij onderhandelt vanuit het algemene belang, dat je uitgaat van een win-win situatie. Zeg dat je binnenkort (half jaar?) ook voor andere festiviteiten een pak nodig hebt, wat verdomd veel lijkt op een lange-termijn relatie lijkt tussen jou en verkoper.
Conclusie
Een pak kopen vereist voorbereiding. Om te voorkomen dat je te veel betaalt voor iets moet je bewust omgaan met bepaalde beïnvloedingen om je heen.
Links & Bronnen
What I learned from a headhunter for a managerial job opening
First of all, I am an unofficial student of dr. Robert Cialdini's work, with regard to his published work on influence. Since I read and reread his seminal work, the world started to make sense, I started to understand on a deeper level, why people did certain things in a certain way. Especially people who wanted you to be compliant to their way of thinking or commit to their cause and be consistent about it too.
When dealing with these types of people, for instance this headhunter I met, he started with authority, i.e. "We are among the top three headhunters in the world, we have 600-700 shops around the world". This might not be true, but it's damn impressive nonetheless.
Then he proceeded with scarcity, i.e. "We only handle cases starting from 45k euro per annum otherwise it isn't interesting for us; when we request an interview with someone we mean business, we know who are the best", in my opinion the last is also meant to flatter the interviewee, which is liking and still a hint of authority, e.g. "We only interview the best" or some variation of that.
I think this is standard stuff for headhunters.
Suppose that you botch up the interview, by not being completely awake, because you couldn't sleep, with all the excitement bubbling inside of you because you have an interview the following day for a very special position (read: ka-ching). Anyway, you realize half-way you're not getting the job (right now), because you're not doing too well selling yourself, with buzz-words and short soundbites to describe your professional skills and experience, so you start to actually relax and do quite well, because you start to act as yourself and let your guard down.
In this case, apply active listening (from dr. Thomas Gordon), so the interviewer will tell you more than (s)he is actually allowed to tell you. Like the name of the company, so you can skip over the headhunter and go for the company yourself and negotiate.
I don't recommend screwing over headhunters, because they are also human and fallible, but if they start getting sloppy, they should learn like all human beings, e.g. by error, pain etc.
Okay, the things I learned actually can be summarized in bullets:
When dealing with these types of people, for instance this headhunter I met, he started with authority, i.e. "We are among the top three headhunters in the world, we have 600-700 shops around the world". This might not be true, but it's damn impressive nonetheless.
Then he proceeded with scarcity, i.e. "We only handle cases starting from 45k euro per annum otherwise it isn't interesting for us; when we request an interview with someone we mean business, we know who are the best", in my opinion the last is also meant to flatter the interviewee, which is liking and still a hint of authority, e.g. "We only interview the best" or some variation of that.
I think this is standard stuff for headhunters.
Suppose that you botch up the interview, by not being completely awake, because you couldn't sleep, with all the excitement bubbling inside of you because you have an interview the following day for a very special position (read: ka-ching). Anyway, you realize half-way you're not getting the job (right now), because you're not doing too well selling yourself, with buzz-words and short soundbites to describe your professional skills and experience, so you start to actually relax and do quite well, because you start to act as yourself and let your guard down.
In this case, apply active listening (from dr. Thomas Gordon), so the interviewer will tell you more than (s)he is actually allowed to tell you. Like the name of the company, so you can skip over the headhunter and go for the company yourself and negotiate.
I don't recommend screwing over headhunters, because they are also human and fallible, but if they start getting sloppy, they should learn like all human beings, e.g. by error, pain etc.
![]() |
| Get a suit for the interview |
Okay, the things I learned actually can be summarized in bullets:
- Watch your body language, give an impression with your body that you're comfortable with talking about yourself and you're enthusiastic about the job prospect;
- Familiarize yourself with real names of positions you would like to attain further on the (cannibalistic corporate canine-trophic) ladder;
- If you come from academia or your family and friends tend to talk on an abstract level, please leave the academic at home, be concrete, do not hide behind abstractions as a protection mechanism (i.e. a way to stay safe from a barrage of prying questions);
- Wear a suit and proportional management shoes for management positions, comb your hair;
- Wrap around stories based on certain keywords that are related to this position, e.g. I worked day and night on blabla, above and beyond..., (so you're dedicated); I negotiated hard on blabla, (so you're assertive...);
- Tell something about yourself with interview power words and emotive stories;
- Apply influence, make the stories believable and compelling, so they end up with the same conclusion or lead them to the same conclusion. Also use the interviewer's name when giving examples;
- Do not be self-deprecative, do not slag off your previous employer(s), just say you reached a certain level of growth in your profession, you want to excel beyond this level (mind you, excel is a power word);
- Oh, don't make shit up, they will find out. (I didn't, because I assume this is common sense and eventually you'll probably end up getting black-mailed.);
- Make sure your references back you up, because don't underestimate the power of social proof.
- Practice your pitch with an unbiased observer!
Subscribe to:
Posts (Atom)






















