Pages

Wednesday, October 21, 2015

Android regional indicator symbols, country flags emoji's

So, i had this problem, instead of country flags like on iPhone, my app showed symbols like "US", "GB", etc. I needed to show them in a TextView.

I found out that those regional indicator symbols are supported starting with android 5.0, but genymotion test on a 5.0 device showed that they are not fully working there.

The logic of the workaround is like this:

  1. get those symbols
  2. convert them to normal characters like "us", "gb".
  3. get an appropriate png image from raw folder
  4. show in textview using spannable string
Detailed description (huge thanks to the blogspot code formatting xD):

First i separated the text part and the symbols part of the string. There is this special character '\uD83C'  that comes before each regional indicator symbol, and you can split the string on it. 

Character sc = '\uD83C';
if (input.indexOf(sc) > -1){
    //input has special regional characters    String[] parts = input.split(sc.toString());    String text = parts[0];
    String[] flagchars = new String[parts.length - 1];
    for (int i = 1; i < parts.length; i++){
        flagchars[i - 1] = parts[i];    }
}

So now the flagchars array contains only the regional indicator symbols.

Next step is to parse those symbols to normal characters
String flagLetters = "";for (int i = 0; i < flagchars.length; i++){
    char ch = flagchars[i].charAt(0);    flagLetters = flagLetters + parseRegionalSymbolToLetter(ch);}

private static String parseRegionalSymbolToLetter(char c) {
    String result = "";
    switch (c){
        case '\uDDE6': result = "A"; break;        case '\uDDE7': result = "B"; break;        case '\uDDE8': result = "C"; break;        case '\uDDE9': result = "D"; break;        case '\uDDEA': result = "E"; break;        case '\uDDEB': result = "F"; break;        case '\uDDEC': result = "G"; break;        case '\uDDED': result = "H"; break;        case '\uDDEE': result = "I"; break;        case '\uDDEF': result = "J"; break;        case '\uDDF0': result = "K"; break;        case '\uDDF1': result = "L"; break;        case '\uDDF2': result = "M"; break;        case '\uDDF3': result = "N"; break;        case '\uDDF4': result = "O"; break;        case '\uDDF5': result = "P"; break;        case '\uDDF6': result = "Q"; break;        case '\uDDF7': result = "R"; break;        case '\uDDF8': result = "S"; break;        case '\uDDF9': result = "T"; break;        case '\uDDFA': result = "U"; break;        case '\uDDFB': result = "V"; break;        case '\uDDFC': result = "W"; break;        case '\uDDFD': result = "X"; break;        case '\uDDFE': result = "Y"; break;        case '\uDDFF': result = "Z"; break;    }

    return result;}

Then, i need to return a List of bitmaps to where im setting the text to TextView

List<Bitmap> bl = getFlagIcons(flagLetters, c);

private static List<Bitmap> getFlagIcons(String flagLetters, Context c) {
    List<Bitmap> bl = new ArrayList<>();
    String remainingLetters = flagLetters;
    int i = 1;
    while (!remainingLetters.isEmpty()){
        String letters = remainingLetters.substring(0, i);        String imageName = checkImageName(letters);        Bitmap flag = getBitmapFromRaw(imageName, c);
        if (flag == null){
            i++;        }else{
            remainingLetters = remainingLetters.substring(i, remainingLetters.length());            bl.add(flag);            i = 0;        }
    }

    return bl;}

This method works like this (sample input string "USGBCA"):
  1. takes first char, tries to find a bitmap in raw folder - in first iteration looks for u.png, 2nd - us.png
  2. if there is no such file, adds one more letter and repeats
  3. if a file is found - adds to List of bitmaps and starts over for next letters.
Returns list of bitmaps. Input "USGBCA" will result in a list of 3 bitmaps with flags of US, GB, CA. This method will also locate 1 char and 3 char countries.

The checkImageName method is there to modify file names for countries if needed

private static String checkImageName(String letters) {

    String result = letters.toLowerCase();
    switch (result){
        case "do": result = "_do"; break;    }

    return result;}

Because a do.png file cant exist because do is a keyword.

public static Bitmap getBitmapFromRaw(String filename, Context context) {
    int identifier = context.getResources().getIdentifier(filename, "raw", context.getPackageName());    Bitmap bmp = null;    if (identifier != 0) {
        InputStream is = context.getResources().openRawResource(identifier);        BufferedInputStream bis = new BufferedInputStream(is);        bmp = BitmapFactory.decodeStream(bis);    }
    return bmp;}



So now we have the List of bitmaps that we need to put inside a TextView.

Next method returns a SpannableString.

public static SpannableString getSpannableString(String text, List<Bitmap> images, Context context) {
    int iml = images.size();    String spaces = "";    for (int k = 0; k < iml; k++){
        spaces = spaces + "  ";    }

    SpannableString ss = new SpannableString(text + spaces);    int l = text.length();
    if (!images.isEmpty()) {
        for (int i = 0; i < iml; i++) {
            Bitmap b = images.get(i);
            Drawable d = new BitmapDrawable(context.getResources(), b);            float scale = context.getResources().getDisplayMetrics().density * 1.3f;            float w = d.getIntrinsicWidth() * scale;            float h = d.getIntrinsicHeight() * scale;            d.setBounds(0, 0, (int) w, (int) h);            ImageSpan is = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);            ss.setSpan(is, l + i * 2, l + i * 2 + 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);        }
    }

    return ss;}

Which is then set to a textview

text.setText(ss);

And ofcourse you need to get flag pngs inside of your res/raw folder. I got mine from here http://www.famfamfam.com/lab/icons/flags/


Monday, September 14, 2015

JavaScript nudity detection script

http://stackoverflow.com/questions/713247/what-is-the-best-way-to-programatically-detect-porn-images

I found a python script in this SO answer, and adapted it to JavaScript. It counts skin colored pixels and compares to total pixel count.

Input - image data;

//nudity check script
function(data) {
var length = data.length;
var skinPixels = 0;
var totalPixels = 0;

for (var i = 0, n = length; i < n; i += 4) {
//i+3 is alpha (the fourth element)
    var r = data[i]; 
    var g = data[i+1]; 
    var b = data[i+2]; 

    totalPixels = totalPixels + 1;

    if ((r > 60) && (g < (r * 0.85)) && (b < (r * 0.7)) && (g > (r * 0.4)) && (b > (r * 0.2))) {
    skinPixels = skinPixels + 1;
    }
}

var isPorn = false;
var ratio = (skinPixels / totalPixels);

if (ratio > 0.0744) {
isPorn = true
}

// console.log("skin:" + skinPixels + ", total:" + totalPixels + ", ratio:" + ratio);

return isPorn;
}

Sample results are like this:


isPorn:true



isPorn:true



isPorn:false



isPorn:false



isPorn:false




Thursday, September 10, 2015

android M, sdk 23, proguard, apache library errors

Hi!

I've spent last one and a half days banging my head against the table because i could not build a signed apk file with proguard, because it had some errors, similar to this:


  • cant find superclass or interface org.apache...
  • cant find referenced class org.apache...

While debug builds and apk generation works without proguard, enabling proguard produces this error.

What i understood from this:

  • google removed apache library from android sdk 23. While the classes itself are still there, they were removed from some kind of index
  • thats why in debug modes everything works, but with enabled proguard proguard obfuscates apache classes making them unusable by some other libraries those are referencing apache classes
  • it also became clear that no additional jar files or dependencies are needed, because your debug modes works ok, just the correct settings for proguard are needed. (im talking about google's advice to add apache legacy library)
The problematic classes those i seen in error logs were:
  1. org.apache.http.*
  2. android.net.http.*
Also when i made a build my app crashed because of support library obfuscations (i could not open the preference activity, i checked stack trace from emulator and seen that support libraries tried to reference obfuscated classes/methods).

Summarising, everything was fixed and working on release apk with the next lines in my proguard-rules.pro file:


-keep class org.apache.http.** { *; }
-dontwarn org.apache.http.**

-keep class android.net.http.** { *; }
-dontwarn android.net.http.**

-keep class android.support.v7.** { *; }
-keep class android.support.v4.** { *; }

Friday, August 28, 2015

Passing data from notification click event to activity android

A lot of time spend until i made it work!

I had lots of notifications and all they should trigger different events in the activity.

The data passed through intent's putExtra methods was not reliable, because of way that intent works. Some extras did not change.

The solution i ended up with is like this:

1) In my custom receiver:
Intent intent = new Intent(null, Uri.parse("some data"), context, MainActivity.class);intent.putExtra("from_notification", true);intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

Create notification here. Btw logo should be set like this, because lollipop and higher logo must be only from white color:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
    iconId = R.raw.logo_white;}
else{
    iconId = R.raw.logo;}

mBuilder.setContentIntent(contentIntent);




My MainActivity:
@Overrideprotected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    boolean fromNotification = intent.getBooleanExtra("from_notification", false);
    if (fromNotification){
        String someData = intent.getData().getSchemeSpecificPart();        //some data is the unique string for each notification
    }
}

Also you should call  the method from onCreate, for cases when activity is not yet running when you tap the notification:

onNewIntent(getIntent());

And dont forget to register the receiver in manifest file with appropriate filters.

Saturday, August 22, 2015

android SQLite best practices (how to SQLite, android sqlite guide tutorial)

Some info i feel obliged to persist.

Had lots of problems and knowledge gaps with android SQLite database, now all seems to fit in its places.


I will share the approach i came to in a few months time of debugging and error fixing.


1) To work with android SQLite you must create your own helper class extending SQLiteOpenHelper.


2) You should use a singleton pattern for this helper instance and get the instance where needed in Activity's onCreate method:

public static synchronized DBHelper getInstance(Context context) {
    // Use the application context, which will ensure that you
    // don't accidentally leak an Activity's context.       
    if (sInstance == null) {
        sInstance = new DBHelper(context.getApplicationContext());    
    }
    return sInstance;
}
3) Before each db interaction (insert, delete, etc) open the database: 
db = this.getWritableDatabase();

4) The helper class should have methods for fetching/persisting data. Methods using cursor must close the cursor after using it. Never close the database itself in this class.


5) Use transaction mode for looped interactions:

db = this.getWritableDatabase();
db.beginTransaction();
try {
    for (...) {
        db.insert(...);
    }

    db.yieldIfContendedSafely();    
    db.setTransactionSuccessful();
}catch(Exception exc){
    exc.printStackTrace();
}finally {
    db.endTransaction();
}
6) My approach to Cursors/queries:
db = this.getWritableDatabase();
Cursor c = db.rawQuery("Select * from TABLE where ID = ?",new String[] {id});
c.moveToPosition(-1);
while (c.moveToNext()) {
    String s = c.getString(c.getColumnIndex("col_name"));
}
c.close();
7) onUpgrade method - when you increment the database version, this method is  called. Mine looks like this:
public static final int DATABASE_VERSION = 238;
@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    dropAll(db); 
    makeDB(db);
}

private SQLiteDatabase dropAll(SQLiteDatabase db){
    db.execSQL("DROP TABLE IF EXISTS tasks");
    return db;
}
public static void makeDB(SQLiteDatabase db){
    db.execSQL(CREATE_TABLE_TASKS);
}
private static final String CREATE_TABLE_TASKS = "CREATE TABLE IF NOT EXISTS tasks(user VARCHAR, ID INTEGER PRIMARY KEY AUTOINCREMENT);";
8) onCreate method:
@Overridepublic void onCreate(SQLiteDatabase db) {
    makeDB(db);
}

9) Working with database is very fast, performance drops might be caused by something else usually, so put that code in AsyncTask.

Monday, August 3, 2015

Anonymous messenger Stealthy.ms

Hi!

Last months i'm developing android version of the already popular iphone app Anonymous messenger "Stealthy". (http://stealthy.ms or http://smsSekret.ru)

The initial idea was to enable people to open their hearts to loved ones, anonymously. Or maybe send secret insides to your business partners, or any other kind of 2 way conversation where you wish to remain anonymous.

The realisation came as ability of the app was to send anonymous SMS to anyone from your contact list, and if they download the app they can answer to your anonymous sms, not knowing who it is. You will know who you are talking to, but not they, they will see you as "Secret Friend".

This app acts just like a simple chat/irc, but you are anonymous! There are group chats with people from your locations (also lots of group chats on different topics - cars/games/ etc), where you can troll everybody or even find new friends.

Also a chat roulette functionality is available, where you will be connected to a random active user of the other gender.

Saturday, April 25, 2015

android sqlite made easy tutorial

Hi!

Start using SQLite in your android app is very easy! SQLite is supported from start for any android app, you dont need to configure anything. There are some frameworks, but i found easier to use without them. Also using frameworks have some litimations, for example currently frameworks do not support encryption of the database.

Also check my second post about SQLite: http://tocrva.blogspot.com/2015/08/android-sqlite-best-practices-how-to.html

1) private field in the activity and add the needed imports:

private SQLiteDatabase db;

2) In onCreate method:

db = openOrCreateDatabase("dbname.db", MODE_PRIVATE, null);

As you might understand, this creates or opens a database named dbname.db in private mode. Private mode means that only your app will have access to this database. Note that the database itself is persisted in text file form and can be accesses easily from a rooted device or a emulator.

3) Now you must create a table inside your database:

db.execSQL("CREATE TABLE IF NOT EXISTS mytable (column1 VARCHAR, column2 VARCHAR);");

This also is self explanatory. Standart SQL sintax. The execSQL method is used to execute sql queries that do not return anything.

4) Inserting values, the best practice using ContentValues (inside try/catch):

ContentValues cv = new ContentValues();
cv.put("column1", "some value");
db.insert("mytable", null, cv);

5) Fetching values. You can provide a static query in the first argument of rawQuery method, or use array of arguments new String[]{"arg1", "arg2", "arg3"}, those will be put in places of "?" in the query:

Cursor c = db.rawQuery("select * from mytable where column1 = ?", new String[]{"some value"});

c.moveToPosition(-1);
while (c.moveToNext()) {
    String column1value = c.getString(0);
}
c.close();

6) Performance optimisation for cycled operations:

db.beginTransaction();
try {
    for(){
        //some insert query
    }
    db.yieldIfContendedSafely();
    db.setTransactionSuccessful();
}catch(Exception exc){
    exc.printStackTrace();
}
finally {
    db.endTransaction();
}

7) A good practice would be to close the db when you will not use it anymore, for example in activity's onPause method:

db.close();

Wednesday, April 1, 2015

Grails mail plugin: implementing email validation (part 2)

Continuing the 1st part of email validation.

In my urlmappings the default controller is user:

//"/"(view:"/index")
"/"(controller:"user", action:"index")

Inside the UserController :
def index() {
if(params.id){
Map model = [queueId: params.id]
redirect(controller:'queue', action:'view', params:model)
}
if(params.confirmationCode){
print "email confirmation code: '${params.confirmationCode}'"
Map params = [confirmationCode: params.confirmationCode]
redirect(controller:'user', action:'confirmEmail', params: params)
}

}

When user opens the link from email like www.yourapp.com/?confirmationCode=32irm4oifjij then the flow passes to the confirmEmail action

confirmEmail action:

def confirmEmail(){
def confirmationCode = params.confirmationCode
def decoded = new String(params.confirmationCode.decodeBase64())
def separatorIndex = decoded.indexOf("QQQ")
def userId = decoded.substring(0, separatorIndex).toInteger()
def user = User.findById(userId)
def proceed = true
if(!user){
proceed = false
flash.message = "User not found with such id."
}
if(confirmationCode != user.temp){
proceed = false
flash.message = "Wrong confirmation code!"
}
if(proceed){
user.temp = null
user.emailVerified = true
user.save(flush:true)
flash.message = "Email was successfully verified for user '${user.userName}'."
}
redirect(controller:'user', action:'index')

}
This is a string decoded in base64 format. For my application queit the format was next: [user id]QQQ[confirmation code]

So the decoded string would look like "1QQQ#@FR$G#ESD", while the encoded string looks something like "ferGW$GFHWgweroih6"

The id is used to fetch user from DB. The user table has a "temp" field where i stored the confirmation code when registering and then sending email.

I believe the rest is self explanatory.

Monday, March 30, 2015

java transliterate cyrillic to latin

Hi! Fast solution without any 3rd party API's:

public static String transliterate(String message){
char[] abcCyr =   {' ','а','б','в','г','д','е', 'ё', 'ж','з','и','й','к','л','м','н','о','п','р','с','т','у','ф','х', 'ц', 'ч', 'ш''щ','ъ','ы','ь','э', 'ю', 'я'
  ,'А','Б','В','Г','Д','Е', 'Ё', 'Ж','З','И','Й','К','Л','М','Н','О','П','Р','С','Т','У','Ф','Х', 'Ц', 'Ч', 'Ш''Щ','Ъ','Ы','Б','Э', 'Ю', 'Я'
  ,'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
  ,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
String[] abcLat = {" ","a","b","v","g","d","e","e","zh","z","i","y","k","l","m","n","o","p","r","s","t","u","f","h","ts","ch","sh","sch", "","i", "","e","ju","ja"
  ,"A","B","V","G","D","E","E","Zh","Z","I","Y","K","L","M","N","O","P","R","S","T","U","F","H","Ts","Ch","Sh","Sch", "","I", "","E","Ju","Ja"
  ,"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"
  ,"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
StringBuilder builder = new StringBuilder();
for (int i = 0; i < message.length(); i++) {
for(int x = 0; x < abcCyr.length; x++ )
if (message.charAt(i) == abcCyr[x]) {
builder.append(abcLat[x]);
}
}
return builder.toString();

}

Wednesday, March 18, 2015

Grails flash message not working in production mode

In dev mode it works, but on production flash messages do not appear. If i put message in session scope then it appears, but not in flash.message. The first idea is that there are some additional redirects happening in production mode, those clear the flash message. Also if i run my app with command grails prod run-app, then flash messages also do not appear. There must be some configuration that disables flash messages for production mode!

The only difference that i found in config.groovy between prod and dev modes was this line:

 grails.logging.jul.usebridge = false

But altering the value didn't affect the production environment flash messages in any way.

Also when i created a test project and ran it in prod mode, the flash message appeared correctly. So there must be something wrong with my project. 

SOLVED:
With a bit of help from ZYRO <3 from grails at freenode.

I had a heroku plugin installed, that was sucking in a database session plugin that had some deprecated class and turns out that was causing the problem.
OMFG. How easy was that:

  1. Check logs.
  2. See what causes the problem.
  3. Disable that thing.

Two days of desperate researching were wasted because of incorrect approach. 

Thursday, March 5, 2015

Groovy:unexpected char: 0xFFFF

Just had this strange error. There was some strange symbol at the end of the class. Turned out that i had an extra double quote in one of my strings, removing which resulted in the error disappearing.

Grails mail plugin: email validation (part 1)

Long story short - i couldn't find a easy and understandable tutorial about this stuff, so i will just save the knowledge here.

1) Add to build config:  compile ":mail:1.0.7"

2) Add email account configuration settings in Config.groovy:

grails.mail.default.from="YOURNAME@gmail.com"

grails {
mail {
  host = "smtp.gmail.com"
  port = 465
  username = "your username"  //ex "bob@gmail.com"
  password = "aplication_specific_password_from_gmail"
  props = ["mail.smtp.auth":"true",
  "mail.smtp.socketFactory.port":"465",
  "mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
  "mail.smtp.socketFactory.fallback":"false"]
}

 }

These settings are for gmail. There are also setting for hotmai/live and yahoo. Actually this can be configured for any email service. Just like you would configure outlook for one. 

Now your email account is set up.

3) Now in your controllers you can use such a closure:

sendMail {
to "email adress"
subject "subject"
body "This is the email body"
}

Or you can use the next approach, like i did:

def sendMail(String email, String confirmationCode){
sendMail {
to email
subject "Queit - confirm your email"
Map model = [confirmationCode:confirmationCode]
html g.render(template:"emailConfirmationTemplate", model:model)
}
}

For additional info check the official documentation: http://grails.org/plugin/mail

Wednesday, March 4, 2015

Grails scheduled execution of some method aka job

In my project i needed a method to execute once per day, that did something to my database, or schedule a job. There is a plugin for this - quartz. Setting up took 5 minutes.

1) In build config add next line, then refresh dependencies:

compile ":quartz:1.0.2"

2) run command: grails create-job YourJobName

3) In your project grails-app/jobs folder the file will be created. In the execute() method put what needs to be executed, or a call to a service method, as i did.

4) Inside the static triggers add some trigger. There are several types of triggers, easy one, cron trigger and some other one. Easy trigger just triggers the execute method, for example, each 5 minutes. The cron trigger allows you to enter a cron expression to schedule the execute method.

static triggers = {
  cron  cronExpression: "00 00 00 * * ?"
  /**
  * cronExpression: "s m h D M W Y"
       *           | | | | | | `- Year [optional]
       *           | | | | | `- Day of Week, 1-7 or SUN-SAT, ?
       *               | | | | `- Month, 1-12 or JAN-DEC
       *               | | | `- Day of Month, 1-31, ?
       *               | | `- Hour, 0-23
       *               | `- Minute, 0-59
       *          `- Second, 0-59
  */

    }

The cron trigger above triggers the execute method every day at 00 hours, 00 minutes and 00 seconds. Not that if the expression would be * * 00 * * ?, then the job would be executed at 00 hours all the time, and will stop cycling the execute method when hours become 01.

Well, now when you do grails run-app the scheduling is turned on and you have a working scheduled job waiting for the specified time to be executed.

Oh, and in case something is unclear, check the documentation -> http://grails-plugins.github.io/grails-quartz/guide/introduction.html

Friday, February 27, 2015

Hello, World! - amazing post, source link at bottom

When a programmer picks up a new language it is customary to write the timeless Hello Worldapplication to ease your way into a daunting codebase with an overly-simplistic view of its syntax.  I’ve personally done this at least 20 times throughout the last 13 years of my life starting in college, and up to about two years ago as I was diving into ruby.  It’s an interesting concept to me, really.  You take an incredibly advanced and complex programming language, and dumb it down to the absolute bare essentials in order to embark on the journey of learning a new system.  Today, I begin a journey in which I look at the concept of “Hello World” a little bit differently.
I started my life as a programmer at a fairly late age in comparison to most others.  Though, I had always been fascinated by computers, I didn’t really get into things until my second year in college after taking an introductory computer science class.  Writing that first Hello World program in 8-bit binary took about 8 hours to complete with a lab partner, and spanned about 3 pages of 8.5″ x 11″ printer paper.  I was so undeniably fascinated by what we had accomplished that I ended up changing my major the very next day.  After 4 more years of college I decided to call it quits with s0-called higher education, and continued learning to code on my own.  As a man who was raised by a fairly “normal” family and a fairly “normal” society, without even thinking twice about it I started to look for jobs.  After about a month of searching I was hired by a company who managed data for insurance agents.  This was it!  This is where my real life actually begins!  Little did I know it was really the beginning of the end of my life as a programmer.
This particular job was an incredibly bad one.  A super conservative environment where all of the developers (code monkeys to the fullest) were shoved in a fluorescent-lit room with no windows to hack away at bugs directly in production environments.  It only took about a year and a half for it to fully suck my soul away, at which time I ultimately quit.  Over the next couple years I began working as a chef, and as a bartender to make my living and I was fairly happy with that lifestyle.  After two years of slinging craft beer, preparing braised short ribs, and drinking with friends until the wee hours of the night my girlfriend at the time gave me the news that we were having a child together.
This news instantly put me into dad-mode, and I knew that it was time to go back to the “real world” to get a job with a good salary and benefits.  This time, however, I lucked out in a huge way (or so I thought).  I ended up with one of the most amazing companies a person could ask to work for, and they offered the ideal package.  A great salary, great benefits, trips to Vegas and New York City, a great group of people, a host of fantastic client names, beer and whisky in the office, and the occasional happy hour event outside of work.  They utilized modern web frameworks, version control systems, cloud-based service providers, automation tools, and I learned more in the next three years than I could have learned in a lifetime with most other companies.  They treated me incredibly well as an employee, and as an actual human being.
Today, however, I sit here writing this post as a 32-year-old man with a head of gray hair, a mind that cannot stop thinking a million miles a minute about a million different things, and eyes that have only been open to the digital world.  I am burnt out on writing code.  I am burnt out on configuration.  I am burnt out on automating monotonous tasks.  I am burnt out on completing tickets.  I am burnt out on completing tickets that undo what those other tickets accomplished.  I am burnt out on debugging third-party advertising code.  I am burnt out on having 16 terminal tabs open.  I am burnt out on contributing to the “connected” culture.  I am burnt out on having a “40 hour” work week that actually occupies the majority of my mental time.  I am burnt out on sitting at a desk.  This state of being burnt out has invaded so much of my out-of-work life that I have decided to take my Life back.
Actually, I lied.  Today, I stand here with 2 days left at my current job, and a new fire inside of me that I can’t hold back.  Next week I embark on an adventure that consists of working on a local farm, and building a tiny house on wheels.  An adventure that puts my bony, cramped fingers back into the earth where they belong.  An adventure that allows me to build, engineer, and grow tangible creations that I can be proud of.  An adventure that will release me from what I consider to be the life-long imprisonment of a mortgage or rent payment.  A journey that allows more time for me to be an active participant in raising my children into good men.  A journey with a larger purpose.  A journey that will feed me in ways money cannot. A journey that will breed true Life.
Today, I write these words without fear of errors or exceptions…
Hello, World!
source: http://hello-world.io/hello-world/

Sunday, February 22, 2015

grails auto refresh a div with jquery

I guess the toughest dead end i had so far - i needed to refresh only a part of a page, one div, every 10 seconds, for example. I had completely no idea how to solve it. After some time and no responses on SO i thought that i probably needed to create a separate view and point the div to this view with jquery, something like that. 
The solution turned out to be almost like i thought.
I've solved this with help of joshm76 from #grails on freenode.
There are several steps for this solution:
  1. i need a template with the div contents i need to update
  2. i need a controller that with a model passes needed values to the template
  3. i need to include this inside the div i want to update with a 
  4. with jquery i update the div contents
1) Template is a .gsp file with _ before the name, like _myTemplate.gsp. Put it in the view folder of the controller you will be using.
2)
    def action(){
    def var
    //some logic to populate the variable

    Map model = [myVar: var]
    render(template: '_myTemplate', model: model)
}
in the template the variable can be accessed with ${myVar}
3) inside the div you need to update, put the <g:include> instead of the content you had there before (now the content is in the template)
<g:include controller='controller' action='action' />
4) the jquery part (fetches the template every 5 seconds):
    $(document).ready(
            function() {
                setInterval(function() { 
                $('#divId').load('/app/controller/action');
                }, 5000);
            });
you can also use the $.get() function, the result seems to be identical