SQLite contains full-text search module called FTS3, using this module you can easily add fast full text search to an Android application. First you need to create virtual table:
CREATE VIRTUAL TABLE TableName
USING FTS3(ColOne TEXT, ColTwo DATETIME)
Your table must contains at least 1 TEXT field. The FTS3 virtual table acts like a regular table, but you need to manually maintain the indexes to keep referential integrity — you should UPDATE the FTS3 table from time to time. The full-text query in SQLite looks like this:
SELECT * FROM TableName WHERE ColOne MATCH 'search phrase'
Make sure you use MATCH instead of equals or LIKE to scan a TEXT column in a virtual table. There is a sample application to demonstrate full-text search in action: Download full-text search sample application .
Sorry for delays in publication of “30 days” projects. I faced up with some technical troubles at my “home office”, hope they will be fixed soon.
Thanks to all for cheering up and supporting.
by
bakhtiyor |
Categories:
Uncategorized |
Comments Off
Android port of Fancy Gestures
See also algorithm description and customization information .
Download Android project and executable
/*
* Android FancyGestureDetector
* Copyright (c) 2009 Bakhtiyor Khodjayev (http://bakhtiyor.com)
*
* Version: 0.1
* Url: http://bakhtiyor.com/2009/05/fancy-gesture-detector/
*
* Original Javascript jQuery Version: Anant Garg (http://anantgarg.com/2009/05/21/jquery-fancy-gestures)
* Original ActionScript Version: Didier Brun (http://www.bytearray.org/?p=91) (didier@bytearray.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bakhtiyor.android.gestures;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.view.MotionEvent;
public class FancyGestureDetector {
public interface OnGestureListener {
public void onGesture(String gesture);
}
private final static int HIGHEST_SCORE = 100000;
private final static double SECTOR_RAD = Math.PI * 2 / 8;
@SuppressWarnings("serial")
private final static List<Double> ANGLES = new ArrayList<Double>() {
{
double step = Math.PI * 2 / 100;
double sector;
for (double i = -SECTOR_RAD / 2; i <= Math.PI * 2 - SECTOR_RAD / 2; i += step) {
sector = Math.floor((i + SECTOR_RAD / 2) / SECTOR_RAD);
add(sector);
}
}
};
private final OnGestureListener onGestureListener;
private final Map<String, int[]> gesturesMap = new HashMap<String, int[]>();
private final List<Double> moves = new ArrayList<Double>();
private double lastPositionX;
private double lastPositionY;
public FancyGestureDetector(OnGestureListener onGestureListener) {
this.onGestureListener = onGestureListener;
}
public void addGesture(String name, int[] sequence) {
gesturesMap.put(name, sequence);
}
public void addGestures(Map<String, int[]> gestures) {
gesturesMap.putAll(gestures);
}
public int[] getGesture(String name) {
return gesturesMap.get(name);
}
public Map<String, int[]> getGestures() {
return Collections.<String, int[]> unmodifiableMap(gesturesMap);
}
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setLastPosition(event.getX(), event.getY());
return true;
case MotionEvent.ACTION_MOVE:
addMove(event);
return true;
case MotionEvent.ACTION_UP:
matchGesture();
resetMoves();
return true;
}
return false;
}
public void removeGesture(String name) {
gesturesMap.remove(name);
}
private void addMove(MotionEvent event) {
double difx = (event.getX() - lastPositionX);
double dify = (event.getY() - lastPositionY);
double sqDist = (difx * difx + dify * dify);
double sqPrec = (8 * 8);
if (sqDist > sqPrec) {
setLastPosition(event.getX(), event.getY());
double angle = Math.atan2(dify, difx) + SECTOR_RAD / 2;
if (angle < 0) {
angle += Math.PI * 2;
}
int index = (int) Math.floor(angle / (Math.PI * 2) * 100);
moves.add(ANGLES.get(index));
}
}
private double costLeven(int[] a, Double[] b) {
if (a[0] == -1)
return b.length == 0 ? 0 : HIGHEST_SCORE;
double[][] d = new double[a.length + 1][b.length + 1];
double[][] w = new double[a.length + 1][b.length + 1];
int x, y;
for (x = 1; x <= a.length; x++) {
for (y = 1; y < b.length; y++) {
d[x][y] = difAngle(a[x - 1], b[y - 1]);
}
}
for (y = 1; y <= b.length; y++) {
w[0][y] = HIGHEST_SCORE;
}
for (x = 1; x <= a.length; x++) {
w[x][0] = HIGHEST_SCORE;
}
w[0][0] = 0;
double cost, pa, pb, pc;
for (x = 1; x <= a.length; x++) {
for (y = 1; y < b.length; y++) {
cost = d[x][y];
pa = w[x - 1][y] + cost;
pb = w[x][y - 1] + cost;
pc = w[x - 1][y - 1] + cost;
w[x][y] = Math.min(Math.min(pa, pb), pc);
}
}
return w[x - 1][y - 1];
}
private double difAngle(int a, double b) {
double dif = Math.abs(a - b);
if (dif > 8 / 2) {
dif = 8 - dif;
}
return dif;
}
private void matchGesture() {
double result = HIGHEST_SCORE;
double res;
String gesture = null;
for (Map.Entry<String, int[]> entry : gesturesMap.entrySet()) {
int[] matchMove = entry.getValue();
res = costLeven(matchMove, moves.toArray(new Double[moves.size()]));
if (res < result && res < 30) {
result = res;
gesture = entry.getKey();
}
}
if (gesture != null) {
onGestureListener.onGesture(gesture);
}
}
private void resetMoves() {
moves.clear();
setLastPosition(0, 0);
}
private void setLastPosition(float x, float y) {
lastPositionX = x;
lastPositionY = y;
}
@SuppressWarnings("serial")
public final static Map<String, int[]> LETTER_GESTURES = Collections
.<String, int[]> unmodifiableMap(new HashMap<String, int[]>() {
{
put("A", new int[] { 5, 3 });
put("B", new int[] { 2, 6, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 });
put("C", new int[] { 4, 3, 2, 1, 0 });
put("D", new int[] { 2, 6, 7, 0, 1, 2, 3, 4 });
put("E", new int[] { 4, 3, 2, 1, 0, 4, 3, 2, 1, 0 });
put("F", new int[] { 4, 2 });
put("G", new int[] { 4, 3, 2, 1, 0, 7, 6, 5, 0 });
put("H", new int[] { 2, 6, 7, 0, 1, 2 });
put("I", new int[] { 6 });
put("J", new int[] { 2, 3, 4 });
put("K", new int[] { 3, 4, 5, 6, 7, 0, 1 });
put("L", new int[] { 4, 6 });
put("M", new int[] { 6, 1, 7, 2 });
put("N", new int[] { 6, 1, 6 });
put("O", new int[] { 4, 3, 2, 1, 0, 7, 6, 5, 4 });
put("P", new int[] { 6, 7, 0, 1, 2, 3, 4, 5, 6 });
put("Q", new int[] { 4, 3, 2, 1, 0, 7, 6, 5, 4, 0 });
put("R", new int[] { 2, 6, 7, 0, 1, 2, 3, 4, 1 });
put("S", new int[] { 4, 3, 2, 1, 0, 1, 2, 3, 4 });
put("T", new int[] { 0, 2 });
put("U", new int[] { 2, 1, 0, 7, 6 });
put("V", new int[] { 3, 5 });
put("W", new int[] { 2, 7, 1, 6 });
put("X", new int[] { 1, 0, 7, 6, 5, 4, 3 });
put("Y", new int[] { 2, 1, 0, 7, 6, 2, 3, 4, 5, 6, 7 });
put("Z", new int[] { 0, 3, 0 });
put(" ", new int[] { 0 });
put("?", new int[] { 6, 7, 0, 1, 2, 3, 2 });
}
});
}
by
bakhtiyor |
Categories:
Uncategorized | Tagged:
android ,
gesture |
Comments Off