06
May 12

Two Way Road

Have a look at this picture and tell me if it’s a one or two way road.

2012-05-04-17-55-11

The answer is: it’s a two way road! This happens about every 5 minutes during rush hour outside of my apartment. It really shows the lack of law enforcement and more so people just not caring about anyone but themselves while driving. It was originally a two lane road with a large bike lane, but cars park in the bike lane, which is ok. People try to swing around each other, which would work if there was some place to go, but there isn’t. It ends up in 2 or 2 cards next to each other blocking oncoming traffic front bumper to front bumper.


29
Apr 12

Android: Quickly Get and Set Preferences

There are many ways to do this, but I feel this is the most effective and compact way to deal with getting and setting preferences. It’s only one line of code to set it and one to get it!

To set a string preference we’ll use “putString” which requires you to first declare the preference name and then value.

getPreferences(MODE_PRIVATE).edit().putString("name", "josh").commit();

When retrieving the preference you call “getString” which requires you enter the preference name and then a default value to return. The default value it important, because in the event it isn’t set you won’t get a null pointer exception. In this example I set the default value to an empty string, but you could change it to anything.

(getPreferences(MODE_PRIVATE).getString("name", "");

29
Apr 12

Android: Validating Chinese, Japanese and Korean Input

Need to check whether a textbox contains Chinese, Japanese or Korean text? Here is a small function to handle it and return a boolean result. It also checks for Japanese hiragana and katakana as well as Korean hangul.

private boolean isAsianType(String val) {
    String str = val;
    int offset = 0, strLen = str.length();
    while (offset < strLen) {
        int curChar = str.codePointAt(offset);
    	offset += Character.charCount(curChar);
    	if (Character.UnicodeBlock.of(curChar) != Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS &&
    	    Character.UnicodeBlock.of(curChar) != Character.UnicodeBlock.HIRAGANA &&
    	    Character.UnicodeBlock.of(curChar) != Character.UnicodeBlock.KATAKANA &&
    	    Character.UnicodeBlock.of(curChar) != Character.UnicodeBlock.HANGUL_SYLLABLES) {
    	        return false;
    	}
    }
    return true;
}

26
Apr 12

Roller skating

Last week we went roller skating again and tried to snap some pictures, but dimly lit gymnasiums aren’t the best place to do so. It surprisingly gave me the feeling of being at Castle Skateland back home when I was younger. The floor wasn’t as nice, but the skates were the same and people were still skating in the same circle.

dsc01034

I tried to organize it so that we’d have a group of about five or more going, but ran into some of the stubborn foreigner issues that arise here from time to time. I guess living here for a long time has made a few of them overly cynical and pessimistic. I received excuses including a minor leg injury, the skates wouldn’t be big enough for foreign feet and forgetting to bring a bike lock. Oh well, I’ll try again next time and now I know who not  to invite.

dsc01038

21
Apr 12

Staying On Time

I have a phone and a computer and the the time displayed on both often varies. So how can I have them both running on the same time server? A few tweaks here and there will have them both synced to less than a minute (usually only a few seconds) of discrepancy. This will sync your Windows and Android environment using the poop.ntp.org time server. I chose this one, but it seems to work more efficiently in a more global setting.

Windows XP/7
First we’ll start with Windows. It should be the same on Vista, but I haven’t tested it. We’ll be adding a line to the local registry for this to work.

  • Using the run command open “regedit.exe”
  • Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\ Microsoft\Windows\CurrentVersion\DateTime\Servers
  • Select edit -> new -> string value
  • Change the name to the next number in the ordered sequence
  • Right-click and select modify
  • Type in “pool.ntp.org” for the value data

Now you should be able to select a new time server from the clock settings dialog.

Android
Setting up an Android device doesn’t require a rooted phone, but the tool to do it is more useful if the phone is rooted. It requires Android 1.5+ to run the application. Click the following link and download the app to start syncing your phone.


Get it on Google Play


18
Apr 12

Android: Sorting Objects

Here is a piece of code directly from my most recent project. My application matches character based on their match score. I needed to be able to sort these WrittenCharacter object by their score attribute so I can easily display the top matches. Using the collections.sort method quickly and efficiently solved my problem.

Collections.sort(this.results, new Comparator<WrittenCharacter>() {
    public int compare(WrittenCharacter lhs, WrittenCharacter rhs) {
        if (lhs.matchScore > rhs.matchScore) {
	    return 1;
	} else if (lhs.matchScore < rhs.matchScore) {
	    return -1;
	}
 
        return 0;
    }
});

First it loads the results and creates a new comparator. It then moves them forward, backwards or keep them in the same position based on whether they are bigger or smaller than the item they are compared against. In this example it’s sorting them from the smallest score to the highest score. This is because in my application the lower the score the better the match.


16
Apr 12

Android: Locally Using the WebView

I’m mostly writing this example so that I don’t forget how to do it. It’s a small thing, but essentially you could map out an entire interface using locally stored HTML files. It might be a bit slow and take up space if you’re using a lot of high quality graphics though. None the less, the important thing is disabling the zoom and scroll bars.

WebView webv = new WebView(this);
webv.loadUrl("file:///android_asset/map.html");
webv.getSettings().setLoadsImagesAutomatically(true);
webv.getSettings().setSupportZoom(false);
webv.setVerticalScrollBarEnabled(false);
webv.setHorizontalScrollBarEnabled(false);

14
Apr 12

Visual Basic: Create an XML File

Here is a simple example that will create a new XML file and save it somewhere. It’s a dictionary that has one entry and also uses an attribute. It’s important to make sure that all of the elements are properly closed, otherwise when the document is open things won’t be structured correctly. I’ve commented on which end element tag is closing what.

Dim file_save As String = "C:\save_your_file_here"
Dim xml As New XmlTextWriter(file_save, System.Text.Encoding.UTF8)
 
xml.WriteStartDocument(True)
xml.Formatting = Formatting.Indented
xml.Indentation = 2
xml.WriteComment("This is just a comment line!")
xml.WriteStartElement("dictionary")
 
xml.WriteStartElement("entry")
xml.WriteAttributeString("id", "a101")
 
xml.WriteStartElement("word")
xml.WriteString("hello")
xml.WriteEndElement() 'word

xml.WriteEndElement() 'entry

xml.WriteEndElement() 'dictionary
xml.WriteEndDocument()
xml.Close()

13
Apr 12

Warming Up

It’s started warming up here and a few days have definitely been t-shirt weather which is nice. It never got deathly cold here, but the change is welcome. Here is a picture from one of the parks in Zibo. More and more people are getting outside to fly their kites.

2012-04-08-15-24-30

On this day day me and Liuna went  a ceramics and pottery museum here. As I get older I seem to like museums more and more. I especially like them here, because it’s always a challenge for me to try to recognize the more obscure characters that come hand in hand with history.

I’ve been really working on hard on learning more about Android programming. Here are two pictures of my latest project. I’ve been trying to get a reusable handwriting view fully code and it’s almost finished! The recognition is right most of the time, but still needs a little more tweaking for my liking.

2012-04-11-01-16-18 2012-04-11-01-16-50

03
Apr 12

Android: Reusable Drawing Canvas

Here is a simple way to implement a reusable drawing canvas. It is based on the Google example FingerPaint.java, but has been changed so it can be used as a widget on a layout.

package your.class.here;
 
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Cap;
import android.graphics.Paint.Join;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PorterDuff.Mode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
 
public class CanvasView extends View {
	private Bitmap mBitmap;
	private Canvas mCanvas;
	private Paint mPaint, mBitmapPaint;
	private Path mPath;
 
	// contructors
	public CanvasView(Context context) {
		super(context);
		setDefaults();
	}
	public CanvasView(Context context, AttributeSet attrs) {
		super(context, attrs);
		setDefaults();
	}
	public CanvasView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		setDefaults();
	}
 
	// sets the default canvas
	public void setDefaults() {
		mPaint = new Paint();
		mPaint.setAntiAlias(true);
		mPaint.setDither(true);
		mPaint.setColor(Color.CYAN);
		mPaint.setStyle(Paint.Style.STROKE);
	        mPaint.setStrokeJoin(Paint.Join.ROUND);
		mPaint.setStrokeCap(Paint.Cap.ROUND);
		mPaint.setStrokeWidth(12);	
		mPath = new Path();
		mBitmapPaint = new Paint(Paint.DITHER_FLAG);
	}
 
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
		mCanvas = new Canvas(mBitmap);
	}
 
	protected void onDraw(Canvas canvas) {
		canvas.drawColor(Color.WHITE);
		canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
		canvas.drawPath(mPath, mPaint);
	}
 
	private float mX, mY;
    private static final float TOUCH_TOLERANCE = 5; // default 5
 
    private void touch_start(float x, float y) {
        mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }
    private void touch_move(float x, float y) {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
        if (dx &gt;= TOUCH_TOLERANCE || dy &gt;= TOUCH_TOLERANCE) {
            mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
            mX = x;
            mY = y;
        }
    }
    private void touch_up() {
        mPath.lineTo(mX, mY);
        mCanvas.drawPath(mPath, mPaint);
        mPath.reset();
    }
 
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
 
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touch_start(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                touch_move(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                touch_up();
                invalidate();
                break;
        }
        return true;
    }
 
    // clears the drawing canvas
    public void clearCanvas() {
    	mCanvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
    }
 
    // sets the drawing color
    public void setColor(int color) {
    	mPaint.setColor(color);
    }
 
    // sets the drawing style
    public void setStyle(Style style) {
    	mPaint.setStyle(style);
    }
 
    // sets the stroke join
    public void setStrokeJoin(Join join) {
    	mPaint.setStrokeJoin(join);
    }
 
    // sets the stroke cap
    public void setStrokeCap(Cap cap) {
    	mPaint.setStrokeCap(Paint.Cap.ROUND);
    }
 
    // sets the stroke width
    public void setStrokeWidth(int width) {
    	mPaint.setStrokeWidth(width);
    }
}

You can interact with it by declaring it in your activity. Here is an example of how to force a clear.

CanvasView canvas = (CanvasView) findViewById(R.id.canvas);
canvas.clearCanvas();
canvas.invalidate();